Browse Source

clean up renderer to render_group implementation

master
cinnaboot 8 years ago
parent
commit
0aed6588f5
  1. 174
      src/render_group.cpp
  2. 13
      src/render_group.h
  3. 101
      src/renderer.cpp
  4. 2
      src/util.cpp
  5. 10
      src/util.h

174
src/render_group.cpp

@ -42,19 +42,14 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
// check for errors
GLint isLinked = 0;
glGetProgramiv(rg->program_id, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
GLint maxLength = 0;
glGetProgramiv(rg->program_id, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
GLchar infoLog[maxLength];
glGetProgramInfoLog(rg->program_id, maxLength, &maxLength, &infoLog[0]);
LOG(ERROR) << infoLog << "\n";
// The program is useless now. So delete it.
glDeleteProgram(rg->program_id);
return false;
@ -63,32 +58,44 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
return true;
}
void
rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[])
gl_buffer *
rgInitGLBuffer(gl_buffer* buffer, uint buffer_len)
{
// TODO: why not just assing the pointer to the render group instead of copying here?
buf_obj->buffer_len = len;
buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat));
buffer->buffer_len = buffer_len;
buffer->buffer = (GLfloat*) std::calloc(buffer_len, sizeof(GLfloat));
if (data)
{
for (uint i = 0; i < len; i++)
buf_obj->buffer[i] = data[i];
}
if (!buffer->buffer)
LOG(ERROR) << "Error allocating memory\n";
return buffer;
}
gl_index_buffer *
initGLIndexBuffer(gl_index_buffer* index_buffer, uint buffer_len)
{
index_buffer->buffer_len = buffer_len;
index_buffer->buffer = (uint*) std::calloc(buffer_len, sizeof(uint));
glGenBuffers(1, &buf_obj->buffer_id);
glBindBuffer(target, buf_obj->buffer_id);
glBufferData(target, len * sizeof(GLfloat), buf_obj->buffer, usage);
if (!index_buffer->buffer)
LOG(ERROR) << "Error allocating memory\n";
return index_buffer;
}
void
rgSendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target)
{
glGenBuffers(1, &buffer->buffer_id);
glBindBuffer(target, buffer->buffer_id);
glBufferData(target, buffer->buffer_len * sizeof(GLfloat), buffer->buffer, usage);
}
// NOTE: helper for fillColorBuffer() to convert uint32 color to GLfloat triplet
void
convertColor(GLfloat buf[3], uint32 color)
sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target)
{
// NOTE: not using the alpha values for now
buf[0] = (GLfloat) ((color >> 24) & 0xFF) / (GLfloat) 255;
buf[1] = (GLfloat) ((color >> 16) & 0xFF) / (GLfloat) 255;
buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255;
glGenBuffers(1, &index_buffer->buffer_id);
glBindBuffer(target, index_buffer->buffer_id);
glBufferData(target, index_buffer->buffer_len * sizeof(uint), index_buffer->buffer, usage);
}
void
@ -101,7 +108,7 @@ rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
{
buf_idx = i * buf_len_per_hex;
hex_info hxi = (*hexes)[i];
convertColor(color_buf, hxi.current_color);
utilConvertColor(color_buf, hxi.current_color);
for (int j = 0; j < buf_len_per_hex; j+=3)
{
@ -112,20 +119,23 @@ rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
}
}
// Copy assimp data to our structures for openGL
bool
rgInitEntity(gl_render_group* rg, Entity* e)
{
bool retVal = true;
bool useNormals = rg->use_normals = (e->mesh->normals != nullptr);
rg->draw_indexed = true;
rg->use_normals = (e->mesh->normals != nullptr);
uint vertex_buf_len = e->mesh->num_vertices * 3;
GLfloat* vertex_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat));
GLfloat* color_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat));
GLfloat* normal_buf;
if (useNormals)
normal_buf = (GLfloat*) std::calloc(vertex_buf_len, sizeof(GLfloat));
// dump vertices, colors, and normals into temporary buffers
GLfloat* vertex_buf = rgInitGLBuffer(&rg->vertex_buffer, vertex_buf_len)->buffer;
GLfloat* color_buf = rgInitGLBuffer(&rg->color_buffer, vertex_buf_len)->buffer;
GLfloat* normal_buf = rgInitGLBuffer(&rg->normal_buffer, vertex_buf_len)->buffer;
uint* index_buf = initGLIndexBuffer(&rg->index_buffer, e->mesh->num_indices)->buffer;
if (!vertex_buf || !color_buf || !normal_buf || !index_buf)
return false;
// dump vertices, colors, and normals into render_group buffers
uint vertex_index = 0;
uint vertex_prop_index = 0;
@ -139,7 +149,7 @@ rgInitEntity(gl_render_group* rg, Entity* e)
case 2: vertex_buf[i] = vertex.z; break;
}
if (useNormals) {
if (rg->use_normals) {
switch (vertex_prop_index) {
case 0: normal_buf[i] = normal.x; break;
case 1: normal_buf[i] = normal.y; break;
@ -156,41 +166,17 @@ rgInitEntity(gl_render_group* rg, Entity* e)
}
}
// send vertex and color data to OpenGL
rgInitGLBufferObject(&rg->vertex_buffer, vertex_buf_len,
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vertex_buf);
rgInitGLBufferObject(&rg->color_buffer, vertex_buf_len,
GL_STATIC_DRAW, GL_ARRAY_BUFFER, color_buf);
if (useNormals) {
rgInitGLBufferObject(&rg->vertex_normals, vertex_buf_len,
GL_STATIC_DRAW, GL_ARRAY_BUFFER, normal_buf);
}
// TODO: combine this somehow with rgInitGLBufferObject()
// dump indices into temp buffer
gl_index_buffer index_buffer;
index_buffer.buffer_len = e->mesh->num_indices;
index_buffer.indices = (uint *) std::calloc(e->mesh->num_indices, sizeof(uint));
// dump indices
for (uint i = 0; i < e->mesh->num_indices; i++)
index_buffer.indices[i] = e->mesh->indices[i];
rg->index_buffer = index_buffer;
glGenBuffers(1, &rg->index_buffer.buffer_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, e->mesh->num_indices * sizeof(uint),
rg->index_buffer.indices, GL_STATIC_DRAW);
index_buf[i] = e->mesh->indices[i];
// free temp buffers
std::free(vertex_buf);
if (useNormals) std::free(normal_buf);
std::free(color_buf);
vertex_buf = normal_buf = color_buf = nullptr;
rgSendBufferToGL(&rg->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
rgSendBufferToGL(&rg->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
if (rg->use_normals)
rgSendBufferToGL(&rg->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
sendIndexBufferToGL(&rg->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
return retVal;
return true;
}
void
@ -229,7 +215,7 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
// 3rd attribute buffer: normals
if (rg->use_normals) {
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, rg->normal_buffer.buffer_id);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// TODO: testing lighting
@ -239,52 +225,12 @@ rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
}
// draw
glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3);
// cleanup
glDisableVertexAttribArray(0);
if (rg->color_buffer.buffer)
glDisableVertexAttribArray(1);
}
void
rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id)
{
glUseProgram(rg->program_id);
glUniformMatrix4fv(rg->model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]);
glUniformMatrix4fv(rg->view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]);
glUniformMatrix4fv(rg->projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]);
// TODO: testing lighting
glUniform3f(light_id, light_position.x, light_position.y, light_position.z);
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix)));
glUniformMatrix3fv(rg->normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// 2nd attribute buffer : colors
if (rg->color_buffer.buffer)
{
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
}
// 3rd attribe buffer : normals
if (rg->use_normals) {
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_normals.buffer_id);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
}
// draw
if (rg->draw_indexed) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->index_buffer.buffer_id);
glDrawElements(draw_mode, rg->index_buffer.buffer_len, GL_UNSIGNED_INT, 0);
} else {
glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3);
}
// cleanup
glDisableVertexAttribArray(0);
@ -301,8 +247,8 @@ rgFree(gl_render_group* rg)
return;
utilSafeFree(rg->vertex_buffer.buffer);
utilSafeFree(rg->vertex_normals.buffer);
utilSafeFree(rg->index_buffer.indices);
utilSafeFree(rg->normal_buffer.buffer);
utilSafeFree(rg->index_buffer.buffer);
utilSafeFree(rg->color_buffer.buffer);
utilSafeFree(rg);
}

13
src/render_group.h

@ -15,13 +15,13 @@ struct gl_index_buffer
{
GLuint buffer_id = 0;
size_t buffer_len = 0;
uint* indices = nullptr;
uint* buffer = nullptr;
};
struct gl_render_group
{
gl_buffer vertex_buffer;
gl_buffer vertex_normals;
gl_buffer normal_buffer;
gl_buffer color_buffer;
gl_index_buffer index_buffer;
GLuint program_id = 0;
@ -31,6 +31,7 @@ struct gl_render_group
GLuint normal_matrix_id = 0;
GLuint vertex_array_id = 0;
bool use_normals = false;
bool draw_indexed = false;
};
typedef struct gl_buffer gl_buffer;
@ -39,7 +40,9 @@ typedef struct gl_render_group gl_render_group;
bool rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * frag_code);
void rgInitGLBufferObject(gl_buffer* buf_obj, uint len, GLenum usage, GLenum target, GLfloat data[]);
gl_buffer * rgInitGLBuffer(gl_buffer* buffer, uint buffer_len);
void rgSendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target);
bool rgInitEntity(gl_render_group* rg, Entity* e);
@ -49,9 +52,5 @@ void rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id, bool update_vertex_data = false);
void rgDrawIndexed(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix,
glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id);
void rgFree(gl_render_group* rg);

101
src/renderer.cpp

@ -355,72 +355,68 @@ fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
}
bool
createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
initHexGridBuffers(std::vector<hex_info>* hexes)
{
initMatrices(PROJ_TYPE);
// Vertex Data
// TODO: index duplicate vertices
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
int hex_count = (int) hexes->size();
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
int vbuf_len = hex_count * 6 * 3 * 3;
uint vbuf_len = hexes->size() * 6 * 3 * 3;
uint line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
uint line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
// TODO: surely there's a way to use indexed drawing for line vertices eg) line_loop
// and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements?
// https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index
int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
int line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
gl_buffer& vbuf = * rgInitGLBuffer(&g_filled_hex_render_group->vertex_buffer, vbuf_len);
gl_buffer& cbuf = * rgInitGLBuffer(&g_filled_hex_render_group->color_buffer, vbuf_len);
gl_buffer& normal_buf = * rgInitGLBuffer(&g_filled_hex_render_group->normal_buffer, vbuf_len);
gl_buffer& line_buf = * rgInitGLBuffer(&g_hex_line_render_group->vertex_buffer, line_buf_len);
// temporary buffers
GLfloat* vbuf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat));
GLfloat* cbuf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat));
GLfloat* line_buf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat));
for (int i = 0; i < hex_count; i++)
fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]);
if (!vbuf.buffer || !cbuf.buffer || !line_buf.buffer || !normal_buf.buffer)
return false;
for (uint i = 0; i < hexes->size(); i++)
fillTriangleBufferFromHex(vbuf.buffer, 54 * i, (*hexes)[i]);
rgInitGLBufferObject(&g_filled_hex_render_group->vertex_buffer, vbuf_len,
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, vbuf);
rgSendBufferToGL(&vbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
// color data for hex vertices
rgFillColorBuffer(cbuf, vbuf_len, hexes);
rgInitGLBufferObject(&g_filled_hex_render_group->color_buffer, vbuf_len,
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, cbuf);
rgFillColorBuffer(cbuf.buffer, vbuf_len, hexes);
rgSendBufferToGL(&cbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
// cheat at vertex normals since all hexes lay flat on z-axis
GLfloat* normal_buf = (GLfloat*) std::calloc(vbuf_len, sizeof(GLfloat));
for (int i = 0; i < vbuf_len; i += 3) {
normal_buf[i] = 0;
normal_buf[i + 1] = 0;
normal_buf[i + 2] = 1;
for (uint i = 0; i < vbuf_len; i += 3) {
normal_buf.buffer[i] = 0;
normal_buf.buffer[i + 1] = 0;
normal_buf.buffer[i + 2] = 1;
}
rgInitGLBufferObject(&g_filled_hex_render_group->vertex_normals, vbuf_len,
GL_STATIC_DRAW, GL_ARRAY_BUFFER, normal_buf);
rgSendBufferToGL(&normal_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
g_filled_hex_render_group->use_normals = true;
// hex line vertex data
fillHexLineBuffer(line_buf, line_buf_len, hexes);
rgInitGLBufferObject(&g_hex_line_render_group->vertex_buffer, line_buf_len,
GL_STATIC_DRAW, GL_ARRAY_BUFFER, line_buf);
fillHexLineBuffer(line_buf.buffer, line_buf_len, hexes);
g_hex_line_render_group->vertex_buffer.buffer_len = line_buf_len;
rgSendBufferToGL(&line_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
// TODO: add a color buffer to hex_line and debug render groups to re-use
// fragment shaders and simplify draw rgDraw()
return true;
}
// free temporary buffers
std::free(vbuf);
std::free(cbuf);
std::free(line_buf);
std::free(normal_buf);
vbuf = cbuf = line_buf = normal_buf = nullptr;
bool
createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
{
initMatrices(PROJ_TYPE);
if (!initHexGridBuffers(hexes))
return false;
// debug draw vertexes
int len = 4 * 3; // 4 vertices, 3 floats per vertex
rgInitGLBufferObject(&g_debug_render_group->vertex_buffer, len,
GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER, 0);
rgInitGLBuffer(&g_debug_render_group->vertex_buffer, 4 * 3); // 4 vertices * 3 floats per vertex
if (!g_debug_render_group->vertex_buffer.buffer)
return false;
rgSendBufferToGL(&g_debug_render_group->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
// entities
@ -553,7 +549,7 @@ renderFrame(std::vector<hex_info> *hexes, Entity* entities, uint32 entity_count)
// every frame through rgDrawIndexed()
// entities
for (uint i = 0; i < entity_count; i++) {
rgDrawIndexed(
rgDraw(
g_entity_render_group, GL_TRIANGLES,
entities[i].mesh->model_transform, m_view, m_projection,
g_test_light.position, g_test_light.light_ID
@ -565,19 +561,14 @@ void
renderDebug(std::vector<Point> &vertices)
{
// TODO: indexed line drawing
real64 buf[4 * 3] = {
vertices[0].x, vertices[0].y, 0,
vertices[1].x, vertices[1].y, 0,
vertices[2].x, vertices[2].y, 0,
vertices[3].x, vertices[3].y, 0,
};
// copy vertexes to render group
gl_render_group* rg = g_debug_render_group;
for (int i = 0; i < 12; i++)
rg->vertex_buffer.buffer[i] = buf[i];
GLfloat* buf = g_debug_render_group->vertex_buffer.buffer;
buf[0] = vertices[0].x; buf[1] = vertices[0].y; buf[2] = 0;
buf[3] = vertices[1].x; buf[4] = vertices[1].y; buf[2] = 0;
buf[6] = vertices[2].x; buf[7] = vertices[2].y; buf[8] = 0;
buf[9] = vertices[3].x; buf[10] = vertices[3].y; buf[11] = 0;
rgDraw(rg, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view,
rgDraw(g_debug_render_group, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view,
g_scene_matrices.projection, g_test_light.position, g_test_light.light_ID, true);
}

2
src/util.cpp

@ -2,7 +2,7 @@
#include <cstdlib>
#include <cstdio>
#include "aixlog.hpp"
//#include "aixlog.hpp"
#include "util.h"

10
src/util.h

@ -6,6 +6,7 @@
typedef float real32;
typedef float GLfloat;
typedef double real64;
typedef int32_t bool32;
typedef int32_t int32;
@ -64,6 +65,15 @@ SafeTruncateToInt32(int64 val)
return (int32) val;
}
inline void
utilConvertColor(GLfloat buf[3], uint32 color)
{
// NOTE: not using the alpha values
buf[0] = (GLfloat) ((color >> 24) & 0xFF) / (GLfloat) 255;
buf[1] = (GLfloat) ((color >> 16) & 0xFF) / (GLfloat) 255;
buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255;
}
char * utilDumpTextFile(const char* filename);
void utilSafeFree(void* mem);

Loading…
Cancel
Save