matching mesh's vertex format with shader's vertex format - closes #390

This commit is contained in:
Mikulas Florek 2014-12-21 21:13:00 +01:00
parent 71a3423055
commit 450b4d65d6
12 changed files with 201 additions and 144 deletions

View file

@ -1,92 +1,89 @@
#include "graphics/geometry.h"
#include "core/fs/ifile.h"
#include "core/log.h"
#include "core/math_utils.h"
#include "core/profiler.h"
#include "graphics/gl_ext.h"
#include "graphics/renderer.h"
#include "graphics/shader.h"
namespace Lumix
{
void VertexDef::parse(const char* data, int size)
void VertexDef::addAttribute(Renderer& renderer, const char* name, VertexAttributeDef type)
{
m_attributes[m_attribute_count].m_name_index = renderer.getAttributeNameIndex(name);
m_attributes[m_attribute_count].m_type = type;
}
bool VertexDef::parse(Renderer& renderer, FS::IFile* file)
{
uint32_t attribute_count;
file->read(&attribute_count, sizeof(attribute_count));
m_vertex_size = 0;
int index = 0;
for(int i = 0; i < size; ++i)
for (uint32_t i = 0; i < attribute_count; ++i)
{
ASSERT(index < 15);
switch(data[i])
char tmp[50];
uint32_t len;
file->read(&len, sizeof(len));
if (len > sizeof(tmp) - 1)
{
case 'f':
++i;
if (data[i] == '4')
{
m_attributes[index] = VertexAttributeDef::FLOAT4;
m_vertex_size += 4 * sizeof(float);
}
else if (data[i] == '2')
{
m_attributes[index] = VertexAttributeDef::FLOAT2;
m_vertex_size += 2 * sizeof(float);
}
else
{
ASSERT(false);
}
return false;
}
file->read(tmp, len);
tmp[len] = '\0';
m_attributes[i].m_name_index = renderer.getAttributeNameIndex(tmp);
file->read(&m_attributes[i].m_type, sizeof(m_attributes[i].m_type));
switch (m_attributes[i].m_type)
{
case VertexAttributeDef::FLOAT4:
m_vertex_size += 4 * sizeof(GLfloat);
break;
case 'i':
++i;
if (data[i] == '4')
{
m_attributes[index] = VertexAttributeDef::INT4;
m_vertex_size += 4 * sizeof(int);
}
else if (data[i] == '1')
{
m_attributes[index] = VertexAttributeDef::INT1;
m_vertex_size += sizeof(int);
}
else
{
ASSERT(false);
}
case VertexAttributeDef::POSITION:
case VertexAttributeDef::FLOAT3:
m_vertex_size += 3 * sizeof(GLfloat);
break;
case 'p':
m_attributes[index] = VertexAttributeDef::POSITION;
m_vertex_size += 3 * sizeof(float);
case VertexAttributeDef::FLOAT2:
m_vertex_size += 2 * sizeof(GLfloat);
break;
case 'b':
++i;
if (data[i] == '4')
{
m_attributes[index] = VertexAttributeDef::BYTE4;
m_vertex_size += 4 * sizeof(char);
}
else
{
ASSERT(false);
}
case VertexAttributeDef::FLOAT1:
m_vertex_size += 1 * sizeof(GLfloat);
break;
case 's':
++i;
if (data[i] == '2')
{
m_attributes[index] = VertexAttributeDef::SHORT2;
m_vertex_size += 2 * sizeof(short);
}
else
{
ASSERT(false);
}
case VertexAttributeDef::INT4:
m_vertex_size += 4 * sizeof(GLint);
break;
case VertexAttributeDef::INT3:
m_vertex_size += 3 * sizeof(GLint);
break;
case VertexAttributeDef::INT2:
m_vertex_size += 2 * sizeof(GLint);
break;
case VertexAttributeDef::INT1:
m_vertex_size += sizeof(GLint);
break;
case VertexAttributeDef::BYTE4:
m_vertex_size += 4 * sizeof(GLbyte);
break;
case VertexAttributeDef::SHORT4:
m_vertex_size += 4 * sizeof(GLshort);
break;
case VertexAttributeDef::SHORT2:
m_vertex_size += 2 * sizeof(GLshort);
break;
default:
ASSERT(false);
break;
}
++index;
}
m_attributes[index] = VertexAttributeDef::NONE;
m_attribute_count = index;
m_attribute_count = attribute_count;
return true;
}
@ -95,26 +92,41 @@ int VertexDef::getPositionOffset() const
int offset = 0;
for(int i = 0; i < m_attribute_count; ++i)
{
switch(m_attributes[i])
switch (m_attributes[i].m_type)
{
case VertexAttributeDef::FLOAT2:
offset += 2 * sizeof(float);
break;
case VertexAttributeDef::FLOAT4:
offset += 4 * sizeof(float);
break;
case VertexAttributeDef::INT4:
offset += 4 * sizeof(int);
break;
case VertexAttributeDef::INT1:
offset += sizeof(int);
break;
case VertexAttributeDef::POSITION:
return offset;
break;
case VertexAttributeDef::FLOAT3:
offset += 3 * sizeof(float);
break;
case VertexAttributeDef::FLOAT2:
offset += 2 * sizeof(float);
break;
case VertexAttributeDef::FLOAT1:
offset += 1 * sizeof(float);
break;
case VertexAttributeDef::INT4:
offset += 4 * sizeof(int);
break;
case VertexAttributeDef::INT3:
offset += 3 * sizeof(int);
break;
case VertexAttributeDef::INT2:
offset += 2 * sizeof(int);
break;
case VertexAttributeDef::INT1:
offset += 1 * sizeof(int);
break;
case VertexAttributeDef::BYTE4:
offset += 4 * sizeof(char);
break;
case VertexAttributeDef::SHORT4:
offset += 4 * sizeof(short);
break;
case VertexAttributeDef::SHORT2:
offset += 2 * sizeof(short);
break;
@ -131,54 +143,67 @@ void VertexDef::begin(Shader& shader, int start_offset) const
{
PROFILE_FUNCTION();
int offset = start_offset;
int shader_attrib_idx = 0;
int attribute_count = Math::minValue(m_attribute_count, shader.getAttributeCount());
for(int i = 0; i < attribute_count; ++i)
{
GLint attrib_id = shader.getAttribId(shader_attrib_idx);
switch(m_attributes[i])
GLint attrib_id = shader.getAttribId(m_attributes[i].m_name_index);
switch (m_attributes[i].m_type)
{
case VertexAttributeDef::FLOAT4:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 4, GL_FLOAT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLfloat) * 4;
break;
case VertexAttributeDef::POSITION:
case VertexAttributeDef::FLOAT3:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 3, GL_FLOAT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLfloat) * 3;
++shader_attrib_idx;
break;
case VertexAttributeDef::SHORT2:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 2, GL_SHORT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLshort) * 2;
++shader_attrib_idx;
break;
case VertexAttributeDef::FLOAT2:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 2, GL_FLOAT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLfloat) * 2;
++shader_attrib_idx;
break;
case VertexAttributeDef::FLOAT4:
case VertexAttributeDef::FLOAT1:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 4, GL_FLOAT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLfloat) * 4;
++shader_attrib_idx;
glVertexAttribPointer(attrib_id, 1, GL_FLOAT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLfloat) * 1;
break;
case VertexAttributeDef::SHORT4:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 4, GL_SHORT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLshort) * 4;
break;
case VertexAttributeDef::SHORT2:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 2, GL_SHORT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLshort) * 2;
break;
case VertexAttributeDef::INT4:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 4, GL_INT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLint) * 4;
++shader_attrib_idx;
break;
case VertexAttributeDef::INT3:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 3, GL_INT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLint) * 3;
break;
case VertexAttributeDef::INT2:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 2, GL_INT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLint) * 2;
break;
case VertexAttributeDef::INT1:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 1, GL_INT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(GLint) * 1;
++shader_attrib_idx;
break;
case VertexAttributeDef::BYTE4:
glEnableVertexAttribArray(attrib_id);
glVertexAttribPointer(attrib_id, 4, GL_BYTE, GL_FALSE, m_vertex_size, (GLvoid*)offset);
offset += sizeof(char) * 4;
++shader_attrib_idx;
break;
default:
ASSERT(false);
@ -192,25 +217,9 @@ void VertexDef::begin(Shader& shader, int start_offset) const
void VertexDef::end(Shader& shader) const
{
PROFILE_FUNCTION();
int shader_attrib_idx = 0;
for(int i = 0; i < m_attribute_count; ++i)
{
switch(m_attributes[i])
{
case VertexAttributeDef::POSITION:
case VertexAttributeDef::BYTE4:
case VertexAttributeDef::SHORT2:
case VertexAttributeDef::INT1:
case VertexAttributeDef::INT4:
case VertexAttributeDef::FLOAT4:
case VertexAttributeDef::FLOAT2:
glDisableVertexAttribArray(shader.getAttribId(shader_attrib_idx));
++shader_attrib_idx;
break;
default:
ASSERT(false);
break;
}
glDisableVertexAttribArray(shader.getAttribId(m_attributes[i].m_name_index));
}
}

View file

@ -4,7 +4,7 @@
#include "core/delegate.h"
#include "core/vec3.h"
#include "graphics/gl_ext.h"
#include "graphics/shader.h"
namespace Lumix
{
@ -13,14 +13,19 @@ namespace Lumix
class Shader;
enum class VertexAttributeDef : uint8_t
enum class VertexAttributeDef : uint32_t
{
FLOAT4,
FLOAT2,
INT4,
INT1,
POSITION,
FLOAT1,
FLOAT2,
FLOAT3,
FLOAT4,
INT1,
INT2,
INT3,
INT4,
SHORT2,
SHORT4,
BYTE4,
NONE
};
@ -29,15 +34,25 @@ enum class VertexAttributeDef : uint8_t
struct VertexDef
{
public:
void parse(const char* data, int size);
VertexDef() : m_attribute_count(0) {}
void addAttribute(Renderer& renderer, const char* name, VertexAttributeDef type);
bool parse(Renderer& renderer, FS::IFile* file);
int getVertexSize() const { return m_vertex_size; }
int getPositionOffset() const;
void begin(Shader& shader, int start_offset) const;
void end(Shader& shader) const;
VertexAttributeDef getAttributeType(int i) const { return i < m_attribute_count ? m_attributes[i] : VertexAttributeDef::NONE; }
VertexAttributeDef getAttributeType(int i) const { return i < m_attribute_count ? m_attributes[i].m_type : VertexAttributeDef::NONE; }
private:
VertexAttributeDef m_attributes[16];
class Attribute
{
public:
VertexAttributeDef m_type;
int m_name_index;
};
private:
Attribute m_attributes[Shader::MAX_ATTRIBUTE_COUNT];
int m_attribute_count;
int m_vertex_size;
};

View file

@ -12,6 +12,7 @@
#include "core/vec3.h"
#include "graphics/geometry.h"
#include "graphics/material.h"
#include "graphics/model_manager.h"
#include "graphics/pose.h"
#include "graphics/renderer.h"
@ -155,18 +156,7 @@ void Model::getPose(Pose& pose)
bool Model::parseVertexDef(FS::IFile* file, VertexDef* vertex_definition)
{
ASSERT(vertex_definition);
int vertex_def_size = 0;
file->read(&vertex_def_size, sizeof(vertex_def_size));
char tmp[16];
ASSERT(vertex_def_size < 16);
if (vertex_def_size >= 16)
{
g_log_error.log("renderer") << "Model file corrupted " << getPath().c_str();
return false;
}
file->read(tmp, vertex_def_size);
vertex_definition->parse(tmp, vertex_def_size);
return true;
return vertex_definition->parse(static_cast<ModelManager*>(m_resource_manager.get(ResourceManager::MODEL))->getRenderer(), file);
}
bool Model::parseGeometry(FS::IFile* file)

View file

@ -4,21 +4,29 @@
namespace Lumix
{
class Renderer;
class LUMIX_ENGINE_API ModelManager : public ResourceManagerBase
{
public:
ModelManager(IAllocator& allocator)
ModelManager(IAllocator& allocator, Renderer& renderer)
: ResourceManagerBase(allocator)
, m_allocator(allocator)
, m_allocator(allocator)
, m_renderer(renderer)
{}
~ModelManager() {}
Renderer& getRenderer() { return m_renderer; }
protected:
virtual Resource* createResource(const Path& path) override;
virtual void destroyResource(Resource& resource) override;
private:
IAllocator& m_allocator;
Renderer& m_renderer;
};
}

View file

@ -279,6 +279,12 @@ struct PipelineImpl : public Pipeline
}
Renderer& getRenderer()
{
return static_cast<PipelineManager*>(m_resource_manager.get(ResourceManager::PIPELINE))->getRenderer();
}
virtual ~PipelineImpl() override
{
ASSERT(isEmpty());
@ -1093,7 +1099,9 @@ void DrawScreenQuadCommand::deserialize(PipelineImpl& pipeline, JsonSerializer&
{
m_geometry = m_allocator.newObject<Geometry>();
VertexDef def;
def.parse("pt", 2);
Renderer& renderer = pipeline.getRenderer();
def.addAttribute(renderer, "in_position", VertexAttributeDef::POSITION);
def.addAttribute(renderer, "in_tex_coords", VertexAttributeDef::SHORT2);
int indices[6] = { 0, 1, 2, 0, 2, 3 };
const int GEOMETRY_VERTEX_ATTRIBUTE_COUNT = 20;
float v[GEOMETRY_VERTEX_ATTRIBUTE_COUNT];

View file

@ -27,11 +27,13 @@ class IFile;
class LUMIX_ENGINE_API PipelineManager : public ResourceManagerBase
{
public:
PipelineManager(IAllocator& allocator)
PipelineManager(IAllocator& allocator, Renderer& renderer)
: ResourceManagerBase(allocator)
, m_renderer(renderer)
, m_allocator(allocator)
{}
~PipelineManager() {}
Renderer& getRenderer() { return m_renderer; }
protected:
virtual Resource* createResource(const Path& path) override;
@ -39,6 +41,7 @@ protected:
private:
IAllocator& m_allocator;
Renderer& m_renderer;
};

View file

@ -149,7 +149,8 @@ namespace Lumix
count += m_texts.at(i).m_text.length() << 2;
}
VertexDef vertex_definition;
vertex_definition.parse("f2f2", 4);
vertex_definition.addAttribute(m_engine.getRenderer(), "in_position", VertexAttributeDef::FLOAT2);
vertex_definition.addAttribute(m_engine.getRenderer(), "in_tex_coords", VertexAttributeDef::SHORT2);
Array<int> indices(m_allocator);
Array<float> data(m_allocator);
indices.reserve(count);
@ -574,7 +575,7 @@ namespace Lumix
serializer.read(exists);
if(exists)
{
m_terrains[i] = m_allocator.newObject<Terrain>(Entity::INVALID, *this, m_allocator);
m_terrains[i] = m_allocator.newObject<Terrain>(m_renderer, Entity::INVALID, *this, m_allocator);
Terrain* terrain = m_terrains[i];
terrain->deserialize(serializer, m_universe, *this, i);
}
@ -649,7 +650,7 @@ namespace Lumix
{
if (type == TERRAIN_HASH)
{
Terrain* terrain = m_allocator.newObject<Terrain>(entity, *this, m_allocator);
Terrain* terrain = m_allocator.newObject<Terrain>(m_renderer, entity, *this, m_allocator);
m_terrains.push(terrain);
Component cmp = m_universe.addComponent(entity, type, this, m_terrains.size() - 1);
m_universe.componentCreated().invoke(cmp);

View file

@ -44,11 +44,12 @@ struct RendererImpl : public Renderer
: m_engine(engine)
, m_allocator(engine.getAllocator())
, m_texture_manager(m_allocator)
, m_model_manager(m_allocator)
, m_model_manager(m_allocator, *this)
, m_material_manager(m_allocator)
, m_shader_manager(m_allocator)
, m_font_manager(m_allocator)
, m_pipeline_manager(m_allocator)
, m_pipeline_manager(m_allocator, *this)
, m_attribute_names(m_allocator)
{
m_texture_manager.create(ResourceManager::TEXTURE, engine.getResourceManager());
m_model_manager.create(ResourceManager::MODEL, engine.getResourceManager());
@ -419,6 +420,20 @@ struct RendererImpl : public Renderer
}
virtual int getAttributeNameIndex(const char* name) override
{
for (int i = 0; i < m_attribute_names.size(); ++i)
{
if (m_attribute_names[i] == name)
{
return i;
}
}
m_attribute_names.emplace(name, m_allocator);
return m_attribute_names.size() - 1;
}
Engine& m_engine;
Debug::Allocator m_allocator;
TextureManager m_texture_manager;
@ -436,6 +451,7 @@ struct RendererImpl : public Renderer
Matrix m_view_matrix;
Matrix m_projection_matrix;
Shader* m_debug_shader;
Array<string> m_attribute_names;
};
@ -607,11 +623,13 @@ void renderGeometry(int indices_offset, int vertex_count)
glDrawElements(GL_TRIANGLES, vertex_count, GL_UNSIGNED_INT, (void*)(indices_offset * sizeof(GLint)));
}
void renderQuadGeometry(int indices_offset, int vertex_count)
{
glDrawElements(GL_QUADS, vertex_count, GL_UNSIGNED_INT, (void*)(indices_offset * sizeof(GLint)));
}
int getUniformLocation(const Shader& shader, int name)
{
return shader.getFixedCachedUniformLocation((Shader::FixedCachedUniforms)name);

View file

@ -59,6 +59,7 @@ class LUMIX_ENGINE_API Renderer : public IPlugin
virtual uint32_t getPass() = 0;
virtual void applyShader(Shader& shader, uint32_t combination) = 0;
virtual Shader& getDebugShader() = 0;
virtual int getAttributeNameIndex(const char* name) = 0;
virtual void setProjection(float width, float height, float fov, float near_plane, float far_plane, const Matrix& mtx) = 0;
virtual void setViewMatrix(const Matrix& matrix) = 0;

View file

@ -151,7 +151,8 @@ void Shader::createCombination(const char* defines)
for (int i = 0; i < m_attributes.size(); ++i)
{
combination->m_vertex_attributes_ids[i] = glGetAttribLocation(combination->m_program_id, m_attributes[i].c_str());
int attr_idx = m_renderer.getAttributeNameIndex(m_attributes[i].c_str());
combination->m_vertex_attributes_ids[attr_idx] = glGetAttribLocation(combination->m_program_id, m_attributes[i].c_str());
}
combination->m_fixed_cached_uniforms[(int)FixedCachedUniforms::WORLD_MATRIX] = glGetUniformLocation(combination->m_program_id, "world_matrix");
combination->m_fixed_cached_uniforms[(int)FixedCachedUniforms::GRASS_MATRICES] = glGetUniformLocation(combination->m_program_id, "grass_matrices");

View file

@ -163,7 +163,7 @@ namespace Lumix
};
Terrain::Terrain(const Entity& entity, RenderScene& scene, IAllocator& allocator)
Terrain::Terrain(Renderer& renderer, const Entity& entity, RenderScene& scene, IAllocator& allocator)
: m_mesh(NULL)
, m_material(NULL)
, m_root(NULL)
@ -181,6 +181,7 @@ namespace Lumix
, m_last_camera_position(m_allocator)
, m_grass_types(m_allocator)
, m_free_grass_quads(m_allocator)
, m_renderer(renderer)
{
generateGeometry();
}
@ -850,7 +851,8 @@ namespace Lumix
generateSubgrid(points, indices, indices_offset, 8, 8);
VertexDef vertex_def;
vertex_def.parse("pt", 2);
vertex_def.addAttribute(m_renderer, "in_position", VertexAttributeDef::POSITION);
vertex_def.addAttribute(m_renderer, "in_tex_coords", VertexAttributeDef::SHORT2);
m_geometry.setAttributesData(&points[0], sizeof(points[0]) * points.size());
m_geometry.setIndicesData(&indices[0], sizeof(indices[0]) * indices.size());
m_mesh = m_allocator.newObject<Mesh>(vertex_def, m_material, 0, 0, points.size() * sizeof(points[0]), indices.size(), "terrain", m_allocator);

View file

@ -75,7 +75,7 @@ class Terrain
static const int GRASS_QUAD_SIZE = 10;
public:
Terrain(const Entity& entity, RenderScene& scene, IAllocator& allocator);
Terrain(Renderer& renderer, const Entity& entity, RenderScene& scene, IAllocator& allocator);
~Terrain();
void render(Renderer& renderer, PipelineInstance& pipeline, const Vec3& camera_pos);
@ -135,6 +135,7 @@ class Terrain
Vec3 m_brush_position;
float m_brush_size;
bool m_force_grass_update;
Renderer& m_renderer;
};