Browse Source

breaking even more renderer structures

testing
cinnaboot 6 years ago
parent
commit
51215d68e4
  1. 2
      include/animation.h
  2. 44
      include/entity.h
  3. 99
      include/render_group.h
  4. 28
      include/render_object.h
  5. 22
      include/renderer.h
  6. 22
      include/shader_program.h
  7. 20
      src/entity.cpp
  8. 277
      src/render_group.cpp
  9. 10
      src/render_object.cpp
  10. 61
      src/shader_program.cpp

2
include/animation.h

@ -4,7 +4,7 @@
#include <glm/glm.hpp>
#include "util.h"
#include "render_group.h"
#include "render_object.h"
struct node_animation

44
include/entity.h

@ -2,10 +2,16 @@
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "mesh.h"
#include "render_group.h"
#include "render_object.h"
struct render_objects
{
render_object* objs;
uint count;
};
// NOTE: an entity is the basic unit of the high level renderer interface
struct entity
@ -19,38 +25,16 @@ struct entity
// mesh_groups stored on the render_state object
meMeshGroup mesh_group;
// NOTE: an array of render objects with all the vertex, normal, and uv
// data loaded from assimp
render_object* ren_objects;
uint ren_object_count;
//render_group* ren_group;
render_objects render_objs;
};
// NOTE: an entity group is an array of entities rendered with the same shader
// program
struct entity_group
{
entity* entities;
uint entity_count;
rg_shader_program shader_prg;
};
bool entInit(entity& e, const char* model_path);
inline void
entTranslate(entity& e, glm::vec3 v)
{
e.world_transform = glm::translate(e.world_transform, v);
}
void entFree(entity& e);
inline void
entScale(entity& e, glm::vec3 v)
{
e.world_transform = glm::scale(e.world_transform, v);
}
void entSetWorldPosition(entity& e, float x, float y, float z);
bool entInit(entity& e, const char* model_path, rg_shader_program& shader);
void entTranslate(entity& e, glm::vec3 v);
void entFree(entity& e);
void entScale(entity& e, glm::vec3 v);
void entSetWorldPosition(entity& e, float x, float y, float z);

99
include/render_group.h

@ -1,99 +0,0 @@
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "util.h"
#include "util_image.h"
// TODO: can these structs be used as opaque pointers?
struct gl_buffer
{
GLuint buffer_id;
uint count; // NOTE: number of elements in buffer
uint max_count; // NOTE: maxium number of elements buffer can fit
GLfloat* buffer;
};
struct gl_index_buffer
{
GLuint buffer_id;
uint count; // NOTE: number of elements in buffer
uint max_count; // NOTE: maxium number of elements buffer can fit
uint* buffer;
};
struct render_object
{
glm::mat4 node_xform;
// TODO: can remove these once we're using the global color palatte for all textures
bool use_texture;
GLuint tex_id;
gl_buffer vertex_buffer;
gl_buffer normal_buffer;
gl_buffer uv_buffer;
gl_index_buffer index_buffer;
};
struct rg_shader_program
{
GLuint program_id;
GLuint model_matrix_id;
GLuint view_matrix_id;
GLuint projection_matrix_id;
GLuint normal_matrix_id;
GLuint vertex_array_id;
GLuint sampler_id;
GLuint num_lights_id;
};
struct render_group
{
uint num_objects;
render_object** render_objects;
rg_shader_program shader;
bool use_normals;
bool draw_indexed;
GLenum draw_mode = GL_TRIANGLES;
char name[64];
};
// TODO: maybe pull out to seperate header
struct rg_point_light
{
uint light_ID;
glm::vec3 position;
glm::vec3 color;
float intensity;
};
render_object * rgAllocateRenderObject(uint buffer_len, uint index_len = 0);
// NOTE: initializes a render_group with 1 render_object allocated
render_group* rgInitSingle(rg_shader_program& sp, uint vertex_buffer_len,
bool use_normals = false, uint index_buffer_len = 0,
GLenum draw_mode = GL_TRIANGLES);
bool rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char * frag_code);
bool rgInitGLTexture(GLuint& tex_id, util_image image);
void rgInitGLFloatBuffer(gl_buffer* buffer, GLenum usage, GLenum target);
void rgInitGLIndexBuffer(gl_index_buffer* index_buffer, GLenum usage, GLenum target);
void rgUpdateGLBuffer(gl_buffer& buffer);
void rgDraw(render_group* rg, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix,
rg_point_light* lights, uint num_lights,
bool update_vertex_data = false);
void rgFree(render_group* rg);

28
include/render_object.h

@ -0,0 +1,28 @@
#pragma once
#include <GL/glew.h>
#include <glm/glm.hpp>
struct 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;
};
struct point_light
{
uint light_ID;
glm::vec3 position;
glm::vec3 color;
float intensity;
};
void roFree(render_object* ro);

22
include/renderer.h

@ -11,8 +11,8 @@
#include "camera.h"
#include "entity.h"
#include "render_group.h"
#include "util.h"
#include "shader_program.h"
struct SDL_Handles
@ -22,7 +22,16 @@ struct SDL_Handles
SDL_DisplayMode currentDisplayMode;
};
struct rg_point_light;
struct point_light;
// NOTE: array of entities rendered with the same shader program
struct render_group
{
entity* entities;
uint entity_count;
shader_program shader;
};
struct render_state
{
@ -32,11 +41,10 @@ struct render_state
camera cam;
util_RGBA clear_col;
//rg_shader_program default_shader;
entity_group* entity_groups;
uint entity_group_count;
render_group* render_groups;
uint render_group_count;
rg_point_light* lights;
point_light* lights;
uint num_lights;
uint max_lights;
};
@ -47,5 +55,3 @@ void renShutdown(render_state* rs);
void renRenderFrame(render_state* rs, Entity* entities, uint32 entity_count);
//void renRenderDebug(render_state* rs, std::vector<Point> &vertices);

22
include/shader_program.h

@ -0,0 +1,22 @@
#pragma once
#include <GL/glew.h>
struct shader_program
{
GLuint program_id;
GLuint model_matrix_id;
GLuint view_matrix_id;
GLuint projection_matrix_id;
GLuint normal_matrix_id;
GLuint vertex_array_id;
GLuint sampler_id;
GLuint num_lights_id;
};
shader_program* initShaderProgram(const char* vertex_code, const char* frag_code);

20
src/entity.cpp

@ -1,4 +1,6 @@
#include <glm/gtc/matrix_transform.hpp>
#include "dumbLog.h"
#include "entity.h"
@ -8,7 +10,7 @@ bool initEntityROs(entity& e);
bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture);
bool
entInit(entity& e, const char* model_path, rg_shader_program& shader)
entInit(entity& e, const char* model_path)
{
e.world_transform = glm::mat4(1.0);
entScale(e, glm::vec3(1.0));
@ -34,7 +36,9 @@ void
entFree(entity& e)
{
meFreeMeshGroup(e.mesh_group);
rgFree(e.ren_group);
for (uint i = 0; i < e.render_objs.count; i++)
roFree(&e.render_objs.objs[i]);
}
void
@ -45,6 +49,18 @@ entSetWorldPosition(entity& e, float x, float y, float z)
e.world_transform[3][2] = z;
}
void
entTranslate(entity& e, glm::vec3 v)
{
e.world_transform = glm::translate(e.world_transform, v);
}
void
entScale(entity& e, glm::vec3 v)
{
e.world_transform = glm::scale(e.world_transform, v);
}
void
initEntityRG(entity& e, rg_shader_program& shader, bool use_normals)
{

277
src/render_group.cpp

@ -1,277 +0,0 @@
#include <sstream> // TODO: remove this and make something in util.h
#include <cassert>
#include <glm/glm.hpp>
#include <glm/geometric.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "dumbLog.h"
#include "render_group.h"
#include "util.h"
#define INFO_LOG_MAX_LENGTH 312
// forward declarations
void freeRenderObject(render_object* ro);
void rgInitGLIndexBuffer(gl_index_buffer* index_buffer, GLenum usage, GLenum target);
// interface
render_object *
rgAllocateRenderObject(uint buffer_len, uint index_len)
{
render_object* ro = UTIL_ALLOC(1, render_object);
if (ro == nullptr)
return nullptr;
ro->vertex_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat);
ro->vertex_buffer.count = ro->vertex_buffer.max_count = buffer_len;
ro->normal_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat);
ro->normal_buffer.count = ro->normal_buffer.max_count = buffer_len;
ro->uv_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat);
ro->uv_buffer.count = ro->uv_buffer.max_count = buffer_len;
if (index_len > 0) {
ro->index_buffer.buffer = UTIL_ALLOC(index_len, uint);
ro->index_buffer.count = index_len;
}
if (ro->vertex_buffer.buffer == nullptr ||
ro->normal_buffer.buffer == nullptr ||
((index_len > 0) && (ro->vertex_buffer.buffer == nullptr)))
{
freeRenderObject(ro);
return nullptr;
}
return ro;
}
render_group*
rgInitSingle(rg_shader_program& sp, uint vertex_buffer_len,
bool use_normals, uint index_buffer_len,
GLenum draw_mode)
{
render_group* rg = UTIL_ALLOC(1, render_group);
rg->shader = sp;
rg->use_normals = use_normals;
rg->draw_indexed = (index_buffer_len > 0);
rg->draw_mode = draw_mode;
rg->render_objects = UTIL_ALLOC(1, render_object*);
rg->render_objects[0] = rgAllocateRenderObject(vertex_buffer_len, index_buffer_len);
rg->num_objects = 1;
if (rg->render_objects[0] == nullptr) {
LOG(Error) << "Allocation Error\n";
rgFree(rg);
}
return rg;
}
bool
rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char * frag_code)
{
glGenVertexArrays(1, &sp.vertex_array_id);
glBindVertexArray(sp.vertex_array_id);
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertex_shader_id, 1, &vertex_code, NULL);
glShaderSource(fragment_shader_id, 1, &frag_code, NULL);
glCompileShader(vertex_shader_id);
glCompileShader(fragment_shader_id);
sp.program_id = glCreateProgram();
glAttachShader(sp.program_id, vertex_shader_id);
glAttachShader(sp.program_id, fragment_shader_id);
glLinkProgram(sp.program_id);
sp.model_matrix_id = glGetUniformLocation(sp.program_id, "model");
sp.view_matrix_id = glGetUniformLocation(sp.program_id, "view");
sp.projection_matrix_id = glGetUniformLocation(sp.program_id, "projection");
sp.normal_matrix_id = glGetUniformLocation(sp.program_id, "normal_matrix");
sp.num_lights_id = glGetUniformLocation(sp.program_id, "num_lights");
sp.sampler_id = glGetUniformLocation(sp.program_id, "sampler");
glDetachShader(sp.program_id, vertex_shader_id);
glDetachShader(sp.program_id, fragment_shader_id);
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
// TODO: quick hack to allow 'dynamic' stack allocation for msvc
// also remove INFO_LOG_MAX_LENGTH define
GLint isLinked = 0;
glGetProgramiv(sp.program_id, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
GLint maxLength = INFO_LOG_MAX_LENGTH;
glGetProgramiv(sp.program_id, GL_INFO_LOG_LENGTH, &maxLength);
#ifdef _WIN32
GLchar infoLog[312] = { 0 };
#else
GLchar infoLog[maxLength] = { 0 };
#endif
glGetProgramInfoLog(sp.program_id, maxLength, &maxLength, &infoLog[0]);
LOG(Error) << infoLog << "\n";
glDeleteProgram(sp.program_id);
return false;
}
return true;
}
bool
rgInitGLTexture(GLuint& tex_id, util_image image)
{
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GLenum pixel_format = (image.num_channels == 3) ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, pixel_format, image.w, image.h, 0,
pixel_format, GL_UNSIGNED_BYTE, image.pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return (glGetError() == GL_NO_ERROR);
}
void
rgInitGLFloatBuffer(gl_buffer* buffer, GLenum usage, GLenum target)
{
glGenBuffers(1, &buffer->buffer_id);
glBindBuffer(target, buffer->buffer_id);
glBufferData(target, buffer->max_count * sizeof(GLfloat), buffer->buffer, usage);
}
void
rgInitGLIndexBuffer(gl_index_buffer* index_buffer, GLenum usage, GLenum target)
{
glGenBuffers(1, &index_buffer->buffer_id);
glBindBuffer(target, index_buffer->buffer_id);
glBufferData(target, index_buffer->count * sizeof(uint), index_buffer->buffer, usage);
}
void
rgUpdateGLBuffer(gl_buffer& buffer)
{
glBindBuffer(GL_ARRAY_BUFFER, buffer.buffer_id);
glBufferSubData(GL_ARRAY_BUFFER, 0, buffer.count * sizeof(GLfloat), buffer.buffer);
}
void
rgDraw(render_group* rg, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix,
rg_point_light* lights, uint num_lights, bool update_vertex_data)
{
for (uint i = 0; i < rg->num_objects; i++) {
render_object* ro = rg->render_objects[i];
glUseProgram(rg->shader.program_id);
glUniformMatrix4fv(rg->shader.model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]);
glUniformMatrix4fv(rg->shader.view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]);
glUniformMatrix4fv(rg->shader.projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, ro->vertex_buffer.buffer_id);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
if (update_vertex_data)
{
glBufferSubData(GL_ARRAY_BUFFER, 0, ro->vertex_buffer.count * sizeof(GLfloat),
ro->vertex_buffer.buffer);
}
// 2rd attribute buffer: normals
if (rg->use_normals) {
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, ro->normal_buffer.buffer_id);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix)));
glUniformMatrix3fv(rg->shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]);
// TODO: use Uniform Buffer Objects to update light data
// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt
// https://www.khronos.org/opengl/wiki/Uniform_Buffer_Objects
glUniform1ui(rg->shader.num_lights_id, num_lights);
for (uint i = 0; i < num_lights; i++) {
// TODO: don't do this every frame * every render_group
std::stringstream ss;
ss << "lights[" << i << "].position";
int light_pos_loc = glGetUniformLocation(rg->shader.program_id, ss.str().c_str());
glUniform3fv(light_pos_loc, 1, &lights[i].position[0]);
}
}
// 3rd attribute buffer: UV coordinates
if (ro->use_texture) {
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, ro->uv_buffer.buffer_id);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glBindTexture(GL_TEXTURE_2D, ro->tex_id);
glUniform1i(rg->shader.sampler_id, 0);
}
// draw
if (rg->draw_indexed) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro->index_buffer.buffer_id);
glDrawElements(rg->draw_mode, ro->index_buffer.count, GL_UNSIGNED_INT, 0);
} else {
glDrawArrays(rg->draw_mode, 0, ro->vertex_buffer.count / 3);
}
// cleanup
glDisableVertexAttribArray(0);
if (rg->use_normals)
glDisableVertexAttribArray(1);
if (ro->use_texture)
glDisableVertexAttribArray(2);
glUseProgram(0);
}
}
void
rgFree(render_group* rg)
{
if (rg == nullptr) {
LOG(Error) << "tried to free nullptr\n";
return;
}
for (uint i = 0; i < rg->num_objects; i++)
freeRenderObject(rg->render_objects[i]);
utilSafeFree(rg->render_objects);
utilSafeFree(rg);
}
// internal
void
freeRenderObject(render_object* ro)
{
if (ro == nullptr) {
LOG(Error) << "Tried to free nullptr\n";
return;
}
glDeleteTextures(1, &ro->tex_id);
utilSafeFree(ro->vertex_buffer.buffer);
utilSafeFree(ro->normal_buffer.buffer);
utilSafeFree(ro->uv_buffer.buffer);
utilSafeFree(ro->index_buffer.buffer);
utilSafeFree(ro);
}

10
src/render_object.cpp

@ -0,0 +1,10 @@
#include "dumbLog.h"
#include "render_object.h"
void
roFree(render_object* ro)
{
LOG(Debug) << "TODO: release GL buffers from render_object\n";
}

61
src/shader_program.cpp

@ -0,0 +1,61 @@
#include "dumbLog.h"
#include "shader_program.h"
#include "util.h"
// TODO: remove and fix hack for dynamic stack allocation
#define INFO_LOG_MAX_LENGTH 312
shader_program*
initShaderProgram(const char* vertex_code, const char* frag_code)
{
shader_program* sp = UTIL_ALLOC(1, shader_program);
glGenVertexArrays(1, &sp->vertex_array_id);
glBindVertexArray(sp->vertex_array_id);
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertex_shader_id, 1, &vertex_code, NULL);
glShaderSource(fragment_shader_id, 1, &frag_code, NULL);
glCompileShader(vertex_shader_id);
glCompileShader(fragment_shader_id);
sp->program_id = glCreateProgram();
glAttachShader(sp->program_id, vertex_shader_id);
glAttachShader(sp->program_id, fragment_shader_id);
glLinkProgram(sp->program_id);
sp->model_matrix_id = glGetUniformLocation(sp->program_id, "model");
sp->view_matrix_id = glGetUniformLocation(sp->program_id, "view");
sp->projection_matrix_id = glGetUniformLocation(sp->program_id, "projection");
sp->normal_matrix_id = glGetUniformLocation(sp->program_id, "normal_matrix");
sp->num_lights_id = glGetUniformLocation(sp->program_id, "num_lights");
sp->sampler_id = glGetUniformLocation(sp->program_id, "sampler");
glDetachShader(sp->program_id, vertex_shader_id);
glDetachShader(sp->program_id, fragment_shader_id);
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
GLint isLinked = 0;
glGetProgramiv(sp->program_id, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
GLint maxLength = INFO_LOG_MAX_LENGTH;
glGetProgramiv(sp->program_id, GL_INFO_LOG_LENGTH, &maxLength);
#ifdef _WIN32
GLchar infoLog[312] = { 0 };
#else
GLchar infoLog[maxLength] = { 0 };
#endif
glGetProgramInfoLog(sp->program_id, maxLength, &maxLength, &infoLog[0]);
LOG(Error) << infoLog << "\n";
glDeleteProgram(sp->program_id);
return nullptr;
}
return sp;
}
Loading…
Cancel
Save