Browse Source

prepare codepath for default meshes/shaders

testing
cinnaboot 6 years ago
parent
commit
db54b4b635
  1. 15
      include/entity.h
  2. 49
      include/render_object.h
  3. 10
      include/shader_program.h
  4. 16
      include/types.h
  5. 62
      src/entity.cpp
  6. 272
      src/render_object.cpp
  7. 8
      src/renderer.cpp
  8. 5
      src/util.cpp

15
include/entity.h

@ -5,31 +5,25 @@
#include "mesh.h" #include "mesh.h"
#include "render_object.h" #include "render_object.h"
#include "types.h"
enum mesh_group_type
{
DEFAULT_MESHES = 0,
SIMPLE_MESH = 1
};
// TODO: having a separate code path for each shader is annoying and error // TODO: having a separate code path for each shader is annoying and error
// prone. could try using opaque pointers at high level (renderer, entity), // prone. could try using opaque pointers at high level (renderer, entity),
// and then cast to the appropriate render_object/mesh/shader type in the lower // and then cast to the appropriate render_object/mesh/shader type in the lower
// level functions based on the mesh_type property // level functions based on the mesh_type property
struct entity struct entity
{ {
mesh_group_type mesh_type; mesh_t mesh_type;
simple_mesh mesh; simple_mesh mesh;
simple_render_object simple_ro; simple_render_object* simple_ro;
GLenum draw_mode; GLenum draw_mode;
// TODO: should be a pointer into a global array of mesh_info(s) or // TODO: should be a pointer into a global array of mesh_info(s) or
// mesh_groups stored on the render_state object // mesh_groups stored on the render_state object
mesh_group meshes; mesh_group meshes;
render_object* render_objs; render_objects* render_objs;
uint ro_count;
}; };
bool entInitModel(entity& e, const char* model_path); bool entInitModel(entity& e, const char* model_path);
@ -45,3 +39,4 @@ void entTranslate(entity& e, glm::vec3 v);
void entScale(entity& e, glm::vec3 v); void entScale(entity& e, glm::vec3 v);
void entRotate(entity& e, float angle, glm::vec3 axis); void entRotate(entity& e, float angle, glm::vec3 axis);

49
include/render_object.h

@ -10,40 +10,41 @@
#include "shader_program.h" #include "shader_program.h"
struct render_object struct render_objects;
{ struct simple_render_object;
glm::mat4 node_xform;
GLuint tex_id; render_objects*
GLuint vertex_buffer_id; roInitModel(mesh_group meshes);
GLuint normal_buffer_id;
GLuint uv_buffer_id;
GLuint index_buffer_id;
uint index_buffer_count;
};
struct simple_render_object void
{ roFree(render_objects* r_objs);
glm::mat4 model_transform;
GLuint vertex_buffer_id;
GLuint vertex_color_buffer_id;
uint vertex_count;
};
bool roInit(mesh_info* mi_in, render_object& ro_out); simple_render_object*
roInitSimpleMesh(simple_mesh& mesh_in);
bool roInitSimpleMesh(simple_mesh& mesh_in, simple_render_object& ro_out); void
roFreeSimple(simple_render_object* ro);
void roFree(render_object& ro); void
roTranslate(render_objects* r_objs, glm::mat4 xform);
void roFreeSimple(simple_render_object& ro); void
roScale(render_object* ro, glm::mat4 xform);
void roDraw(render_object& ro, void
roRotate(render_object* ro, glm::mat4 xform);
// TODO: we probably want to re-introduce a world_transform matrix here again
// so we can do: projection * view * world_transform * model_transform
// that way model animations and world orientation/position can be separated
void
roDraw(render_objects* r_ojbs,
camera& cam, camera& cam,
default_shader_program& shader, shader_wrapper sw,
light_group* lights); light_group* lights);
void roDrawSimple(simple_render_object& ro, void
roDrawSimple(simple_render_object* ro,
camera& cam, camera& cam,
simple_shader_program& shader, simple_shader_program& shader,
GLenum draw_mode); GLenum draw_mode);

10
include/shader_program.h

@ -3,6 +3,8 @@
#include <GL/glew.h> #include <GL/glew.h>
#include "types.h"
struct default_shader_program struct default_shader_program
{ {
@ -25,15 +27,9 @@ struct simple_shader_program
GLuint vertex_array_id; GLuint vertex_array_id;
}; };
enum shader_type
{
SIMPLE_SHADER = 0,
DEFAULT_SHADER = 1
};
struct shader_wrapper struct shader_wrapper
{ {
shader_type type; shader_t shader_type;
default_shader_program* default_shader; default_shader_program* default_shader;
simple_shader_program* simple_shader; simple_shader_program* simple_shader;
}; };

16
include/types.h

@ -0,0 +1,16 @@
#pragma once
enum shader_t
{
SIMPLE_SHADER,
DEFAULT_SHADER
};
enum mesh_t
{
SIMPLE_MESH,
DEFAULT_MESHES
};

62
src/entity.cpp

@ -25,9 +25,9 @@ entInitModel(entity& e, const char* model_path)
if (meLoadFromFile(e.meshes, model_path)) if (meLoadFromFile(e.meshes, model_path))
{ {
e.ro_count = e.meshes.num_meshes; e.render_objs = roInitModel(e.meshes);
e.render_objs = UTIL_ALLOC(e.ro_count, render_object);
if (loadMeshesIntoGL(e)) if (e.render_objs != nullptr)
return true; return true;
} }
@ -63,20 +63,8 @@ entInitSimpleMesh(entity& e, simple_mesh& mesh, GLenum draw_mode)
void void
entFree(entity& e) entFree(entity& e)
{ {
if (e.mesh_type == DEFAULT_MESHES) roFree(e.render_objs);
meFreeMeshGroup(e.meshes);
if (e.mesh_type == SIMPLE_MESH) {
meFreeSimpleMesh(e.mesh);
roFreeSimple(e.simple_ro);
}
for (uint i = 0; i < e.ro_count; i++)
roFree(e.render_objs[i]);
utilSafeFree(e.render_objs);
e.render_objs = nullptr; e.render_objs = nullptr;
e.ro_count = 0;
} }
void void
@ -115,8 +103,8 @@ void
entScale(entity& e, glm::vec3 v) entScale(entity& e, glm::vec3 v)
{ {
#if 0 #if 0
e.world_transform = glm::scale(e.world_transform, v); //e.world_transform = glm::scale(e.world_transform, v);
#endif
if (e.mesh_type == SIMPLE_MESH) { if (e.mesh_type == SIMPLE_MESH) {
// //
} }
@ -127,18 +115,18 @@ entScale(entity& e, glm::vec3 v)
ro.node_xform = glm::scale(ro.node_xform, v); ro.node_xform = glm::scale(ro.node_xform, v);
} }
} }
#endif
} }
void void
entRotate(entity& e, float angle, glm::vec3 axis) entRotate(entity& e, float angle, glm::vec3 axis)
{ {
#if 0 #if 0
e.world_transform = glm::rotate(e.world_transform, angle, axis); //e.world_transform = glm::rotate(e.world_transform, angle, axis);
#endif
if (e.mesh_type == SIMPLE_MESH) { if (e.mesh_type == SIMPLE_MESH) {
e.simple_ro.model_transform = glm::mat4& xform = roGetTransform(e.simple_ro);
glm::rotate(e.simple_ro.model_transform, angle, axis); xform = glm::rotate(xform, angle, axis);
} }
if (e.mesh_type == DEFAULT_MESHES) { if (e.mesh_type == DEFAULT_MESHES) {
@ -147,6 +135,7 @@ entRotate(entity& e, float angle, glm::vec3 axis)
ro.node_xform = glm::rotate(ro.node_xform, angle, axis); ro.node_xform = glm::rotate(ro.node_xform, angle, axis);
} }
} }
#endif
} }
@ -159,34 +148,17 @@ initDefaults(entity& e)
entSetWorldPosition(e, glm::vec3(0, 0, 0)); entSetWorldPosition(e, glm::vec3(0, 0, 0));
} }
bool
loadMeshesIntoGL(entity& e)
{
for (uint i = 0; i < e.meshes.num_meshes; i++) {
assert(e.render_objs != nullptr);
render_object& ro = e.render_objs[i];
mesh_info* mi = e.meshes.meshes[i];
assert(mi != nullptr);
if (!roInit(mi, ro)) {
LOG(Error) << "Error initializing render objects\n";
entFree(e);
return false;
}
}
return true;
}
bool bool
loadSimpleMeshIntoGL(entity& e) loadSimpleMeshIntoGL(entity& e)
{ {
assert(e.mesh.num_vertices > 0); assert(e.mesh.num_vertices > 0);
e.simple_ro = roInitSimpleMesh(e.mesh);
if (roInitSimpleMesh(e.mesh, e.simple_ro)) if (e.simple_ro == nullptr) {
return true;
LOG(Error) << "Error initializing render object\n"; LOG(Error) << "Error initializing render object\n";
entFree(e); entFree(e);
return false; return false;
} }
return true;
}

272
src/render_object.cpp

@ -7,128 +7,230 @@
// forward declarations // forward declarations
struct default_render_object
{
glm::mat4 node_xform;
GLuint tex_id;
GLuint vertex_buffer_id;
GLuint normal_buffer_id;
GLuint uv_buffer_id;
GLuint index_buffer_id;
uint index_buffer_count;
};
struct simple_render_object
{
glm::mat4 model_transform;
GLuint vertex_buffer_id;
GLuint vertex_color_buffer_id;
uint vertex_count;
};
struct render_objects
{
void* objects;
uint count;
mesh_t mesh_type;
};
void drawSimple(render_objects* r_objs,
camera& cam,
shader_wrapper sw,
light_group* lights);
void drawDefault(render_objects* r_objs,
camera& cam,
shader_wrapper sw,
light_group* lights);
bool initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id); bool initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id);
bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id); bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id);
bool initGLTexture(const util_image image, GLuint& tex_id); bool initGLTexture(const util_image image, GLuint& tex_id);
inline void bool loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in);
updateMatrices(default_shader_program& shader, camera& cam, inline void updateMatrices(default_shader_program* shader,
camera& cam,
glm::mat4 node_xform); glm::mat4 node_xform);
inline void enableGLFloatBuffer(uint buffer_id, uint location); inline void enableGLFloatBuffer(uint buffer_id, uint location);
// interface // interface
bool render_objects*
roInit(mesh_info* mi_in, render_object& ro_out) roInitModel(mesh_group mg)
{ {
if (initGLFloatBuffer(mi_in->vertices, uint count = mg.num_meshes;
mi_in->num_vertices, assert(count > 0);
ro_out.vertex_buffer_id) &&
initGLFloatBuffer(mi_in->normals, render_objects* r_objs = UTIL_ALLOC(1, render_objects);
mi_in->num_vertices, r_objs->objects = UTIL_ALLOC(count, default_render_object);
ro_out.normal_buffer_id) && r_objs->count = count;
initGLFloatBuffer(mi_in->texture_coords, r_objs->mesh_type = DEFAULT_MESHES;
mi_in->num_vertices,
ro_out.uv_buffer_id) && default_render_object* objects = (default_render_object*) r_objs->objects;
initGLIndexBuffer(mi_in->indices,
mi_in->num_indices, for (uint i = 0; i < count; i++) {
ro_out.index_buffer_id) && if (!loadMeshIntoGL(&objects[i], mg.meshes[i])) {
initGLTexture(mi_in->diffuse_texture, ro_out.tex_id)) roFree(r_objs);
return nullptr;
}
}
return r_objs;
}
void
roFree(render_objects* r_objs)
{ {
ro_out.node_xform = mi_in->model_transform; if (r_objs->mesh_type == SIMPLE_MESH) {
ro_out.index_buffer_count = mi_in->num_indices; //
return true; } else if (r_objs->mesh_type == DEFAULT_MESHES) {
default_render_object* objects =
(default_render_object*) r_objs->objects;
for (uint i = 0; i < r_objs->count; i++) {
glDeleteBuffers(1, &objects[i].vertex_buffer_id);
glDeleteBuffers(1, &objects[i].normal_buffer_id);
glDeleteBuffers(1, &objects[i].uv_buffer_id);
glDeleteBuffers(1, &objects[i].index_buffer_id);
glDeleteTextures(1, &objects[i].tex_id);
} }
LOG(Error) << "Failed to initialize render_object\n"; utilSafeFree(r_objs->objects);
roFree(ro_out); utilSafeFree(r_objs);
return false; }
} }
bool simple_render_object*
roInitSimpleMesh(simple_mesh& mesh_in, simple_render_object& ro_out) roInitSimpleMesh(simple_mesh& mesh_in)
{ {
// TODO: switch on mesh type here
simple_render_object* ro_out = UTIL_ALLOC(1, simple_render_object);
if (initGLFloatBuffer(mesh_in.vertices, if (initGLFloatBuffer(mesh_in.vertices,
mesh_in.num_vertices, mesh_in.num_vertices,
ro_out.vertex_buffer_id) && ro_out->vertex_buffer_id) &&
initGLFloatBuffer(mesh_in.vert_colors, initGLFloatBuffer(mesh_in.vert_colors,
mesh_in.num_vertices, mesh_in.num_vertices,
ro_out.vertex_color_buffer_id)) ro_out->vertex_color_buffer_id))
{ {
ro_out.model_transform = mesh_in.model_transform; ro_out->model_transform = mesh_in.model_transform;
ro_out.vertex_count = mesh_in.num_vertices; ro_out->vertex_count = mesh_in.num_vertices;
return true; return ro_out;
} }
LOG(Error) << "Failed to initialize render_object\n"; LOG(Error) << "Failed to initialize render_object\n";
roFreeSimple(ro_out); roFreeSimple(ro_out);
return false; return nullptr;
} }
void void
roFree(render_object& ro) roFreeSimple(simple_render_object* ro)
{ {
glDeleteBuffers(1, &ro.vertex_buffer_id); glDeleteBuffers(1, &ro->vertex_buffer_id);
glDeleteBuffers(1, &ro.normal_buffer_id); glDeleteBuffers(1, &ro->vertex_color_buffer_id);
glDeleteBuffers(1, &ro.uv_buffer_id); utilSafeFree(ro);
glDeleteBuffers(1, &ro.index_buffer_id);
glDeleteTextures(1, &ro.tex_id);
} }
void void
roFreeSimple(simple_render_object& ro) roTranslate(render_objects* r_objs, glm::mat4 xform)
{ {
glDeleteBuffers(1, &ro.vertex_buffer_id); if (r_objs->mesh_type == SIMPLE_MESH) {
glDeleteBuffers(1, &ro.vertex_color_buffer_id); //
}
else if (r_objs->mesh_type == DEFAULT_MESHES) {
//
}
} }
void void
roDraw(render_object& ro, roScale(render_object* ro, glm::mat4 xform)
camera& cam,
default_shader_program& shader,
light_group* lights)
{ {
glUseProgram(shader.program_id);
updateMatrices(shader, cam, ro.node_xform);
enableGLFloatBuffer(ro.vertex_buffer_id, 0);
enableGLFloatBuffer(ro.normal_buffer_id, 1);
// TODO: could pass in a stride parameter here to enableGLFloatBuffer()
// could then use a 2d buffer for uv coords
enableGLFloatBuffer(ro.uv_buffer_id, 2);
glBindTexture(GL_TEXTURE_2D, ro.tex_id);
glUniform1i(shader.sampler_id, 0);
if (lights->needs_update) }
lightsUpdate(lights, &shader);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro.index_buffer_id); void
glDrawElements(GL_TRIANGLES, ro.index_buffer_count, GL_UNSIGNED_INT, 0); roRotate(render_object* ro, glm::mat4 xform)
{
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glUseProgram(0);
} }
void void
roDrawSimple(simple_render_object& ro, roDraw(render_objects* r_objs,
camera& cam,
shader_wrapper sw,
light_group* lights)
{
if (r_objs->mesh_type == SIMPLE_MESH) {
drawSimple(r_objs, cam, sw, lights);
} else if (r_objs->mesh_type == DEFAULT_MESHES) {
drawDefault(r_objs, cam, sw, lights);
}
}
void
roDrawSimple(simple_render_object* ro,
camera& cam, camera& cam,
simple_shader_program& shader, simple_shader_program& shader,
GLenum draw_mode) GLenum draw_mode)
{ {
glUseProgram(shader.program_id); glUseProgram(shader.program_id);
cam.MVP = cam.projection * cam.view * ro.model_transform; cam.MVP = cam.projection * cam.view * ro->model_transform;
glUniformMatrix4fv(shader.MVP_id, 1, GL_FALSE, &cam.MVP[0][0]); glUniformMatrix4fv(shader.MVP_id, 1, GL_FALSE, &cam.MVP[0][0]);
enableGLFloatBuffer(ro.vertex_buffer_id, 0); enableGLFloatBuffer(ro->vertex_buffer_id, 0);
enableGLFloatBuffer(ro.vertex_color_buffer_id, 1); enableGLFloatBuffer(ro->vertex_color_buffer_id, 1);
glDrawArrays(draw_mode, 0, ro.vertex_count); glDrawArrays(draw_mode, 0, ro->vertex_count);
glDisableVertexAttribArray(0); glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1); glDisableVertexAttribArray(1);
glUseProgram(0); glUseProgram(0);
} }
// internal // internal
void
drawSimple(render_objects* r_objs,
camera& cam,
shader_wrapper sw,
light_group* lights)
{
}
void
drawDefault(render_objects* r_objs,
camera& cam,
shader_wrapper sw,
light_group* lights)
{
default_shader_program* shader = sw.default_shader;
default_render_object* objects = (default_render_object*) r_objs->objects;
glUseProgram(shader->program_id);
updateMatrices(shader, cam, objects->node_xform);
if (lights->needs_update) lightsUpdate(lights, shader);
for (uint i = 0; i < r_objs->count; i++) {
enableGLFloatBuffer(objects[i].vertex_buffer_id, 0);
enableGLFloatBuffer(objects[i].normal_buffer_id, 1);
// TODO: could pass in a stride parameter here to enableGLFloatBuffer()
// could then use a 2d buffer for uv coords
enableGLFloatBuffer(objects[i].uv_buffer_id, 2);
glBindTexture(GL_TEXTURE_2D, objects[i].tex_id);
glUniform1i(shader->sampler_id, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objects[i].index_buffer_id);
glDrawElements(GL_TRIANGLES,
objects[i].index_buffer_count,
GL_UNSIGNED_INT,
0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
glUseProgram(0);
}
bool bool
initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id) initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id)
{ {
@ -170,21 +272,49 @@ initGLTexture(const util_image image, GLuint& tex_id)
return (glGetError() == GL_NO_ERROR); return (glGetError() == GL_NO_ERROR);
} }
bool
loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in)
{
assert(mi_in != nullptr && ro_out != nullptr);
if (initGLFloatBuffer(mi_in->vertices,
mi_in->num_vertices,
ro_out->vertex_buffer_id) &&
initGLFloatBuffer(mi_in->normals,
mi_in->num_vertices,
ro_out->normal_buffer_id) &&
initGLFloatBuffer(mi_in->texture_coords,
mi_in->num_vertices,
ro_out->uv_buffer_id) &&
initGLIndexBuffer(mi_in->indices,
mi_in->num_indices,
ro_out->index_buffer_id) &&
initGLTexture(mi_in->diffuse_texture, ro_out->tex_id))
{
ro_out->node_xform = mi_in->model_transform;
ro_out->index_buffer_count = mi_in->num_indices;
return true;
}
LOG(Error) << "Failed to initialize render_object\n";
return false;
}
// TODO: really only need to update the view and projection matrices once per // TODO: really only need to update the view and projection matrices once per
// frame, maybe add another interface function in render_object to call from // frame, maybe add another interface function in render_object to call from
// renRenderFrame // renRenderFrame
inline void inline void
updateMatrices(default_shader_program& shader, updateMatrices(default_shader_program* shader,
camera& cam, camera& cam,
glm::mat4 node_xform) glm::mat4 node_xform)
{ {
glUniformMatrix4fv(shader.model_matrix_id, 1, GL_FALSE, &node_xform[0][0]); glUniformMatrix4fv(shader->model_matrix_id, 1, GL_FALSE, &node_xform[0][0]);
glUniformMatrix4fv(shader.view_matrix_id, 1, GL_FALSE, &cam.view[0][0]); glUniformMatrix4fv(shader->view_matrix_id, 1, GL_FALSE, &cam.view[0][0]);
glUniformMatrix4fv(shader.projection_matrix_id, 1, GL_FALSE, glUniformMatrix4fv(shader->projection_matrix_id, 1, GL_FALSE,
&cam.projection[0][0]); &cam.projection[0][0]);
glm::mat3 normal_matrix = glm::transpose( glm::mat3 normal_matrix = glm::transpose(
glm::inverse(glm::mat3(cam.model))); glm::inverse(glm::mat3(cam.model)));
glUniformMatrix3fv(shader.normal_matrix_id, 1, GL_FALSE, glUniformMatrix3fv(shader->normal_matrix_id, 1, GL_FALSE,
&normal_matrix[0][0]); &normal_matrix[0][0]);
} }

8
src/renderer.cpp

@ -167,6 +167,14 @@ renRenderFrame(render_state* rs)
} }
} }
#endif #endif
if (rg.shader.shader_type == DEFAULT_SHADER) {
for (uint j = 0; j < rg.entity_count; j++) {
roDraw(rg.entities[j].render_objs,
rs->cam,
rg.shader,
rs->lights);
}
}
} }
} }

5
src/util.cpp

@ -80,10 +80,7 @@ utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int l
void utilSafeFree(const void* mem) void utilSafeFree(const void* mem)
{ {
if (mem != nullptr) { if (mem != nullptr) std::free((void *) mem);
std::free((void *) mem);
mem = nullptr;
}
} }
//----------------- //-----------------

Loading…
Cancel
Save