|
|
|
|
@ -2,9 +2,6 @@
|
|
|
|
|
#include <cassert> |
|
|
|
|
#include <cstdlib> // calloc |
|
|
|
|
|
|
|
|
|
// TODO: decide on extension library
|
|
|
|
|
//#include <GL/glew.h>
|
|
|
|
|
#include <GL/gl3w.h> |
|
|
|
|
#include <glm/glm.hpp> |
|
|
|
|
#include <glm/geometric.hpp> |
|
|
|
|
#include <glm/gtc/matrix_transform.hpp> |
|
|
|
|
@ -13,14 +10,30 @@
|
|
|
|
|
|
|
|
|
|
#include "render_group.h" |
|
|
|
|
#include "mesh.h" |
|
|
|
|
#include "util.h" |
|
|
|
|
|
|
|
|
|
#define INFO_LOG_MAX_LENGTH 312; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// forward declarations
|
|
|
|
|
|
|
|
|
|
render_object * allocateRenderObject(uint buffer_len, uint index_len = 0); |
|
|
|
|
void freeRenderObject(render_object* ro); |
|
|
|
|
bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals); |
|
|
|
|
void sendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target); |
|
|
|
|
void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target); |
|
|
|
|
void drawRenderObject(render_group* rg, render_object* ro, |
|
|
|
|
glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix, |
|
|
|
|
glm::vec3 light_position, GLuint light_id, bool update_vertex_data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// interface
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char * frag_code) |
|
|
|
|
rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char * frag_code) |
|
|
|
|
{ |
|
|
|
|
glGenVertexArrays(1, &rg->vertex_array_id); |
|
|
|
|
glBindVertexArray(rg->vertex_array_id); |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
@ -29,18 +42,18 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
|
|
|
|
|
glCompileShader(vertex_shader_id); |
|
|
|
|
glCompileShader(fragment_shader_id); |
|
|
|
|
|
|
|
|
|
rg->program_id = glCreateProgram(); |
|
|
|
|
glAttachShader(rg->program_id, vertex_shader_id); |
|
|
|
|
glAttachShader(rg->program_id, fragment_shader_id); |
|
|
|
|
glLinkProgram(rg->program_id); |
|
|
|
|
sp.program_id = glCreateProgram(); |
|
|
|
|
glAttachShader(sp.program_id, vertex_shader_id); |
|
|
|
|
glAttachShader(sp.program_id, fragment_shader_id); |
|
|
|
|
glLinkProgram(sp.program_id); |
|
|
|
|
|
|
|
|
|
rg->model_matrix_id = glGetUniformLocation(rg->program_id, "model"); |
|
|
|
|
rg->view_matrix_id = glGetUniformLocation(rg->program_id, "view"); |
|
|
|
|
rg->projection_matrix_id = glGetUniformLocation(rg->program_id, "projection"); |
|
|
|
|
rg->normal_matrix_id = glGetUniformLocation(rg->program_id, "normal_matrix"); |
|
|
|
|
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"); |
|
|
|
|
|
|
|
|
|
glDetachShader(rg->program_id, vertex_shader_id); |
|
|
|
|
glDetachShader(rg->program_id, fragment_shader_id); |
|
|
|
|
glDetachShader(sp.program_id, vertex_shader_id); |
|
|
|
|
glDetachShader(sp.program_id, fragment_shader_id); |
|
|
|
|
glDeleteShader(vertex_shader_id); |
|
|
|
|
glDeleteShader(fragment_shader_id); |
|
|
|
|
|
|
|
|
|
@ -48,18 +61,18 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
|
|
|
|
|
// also remove INFO_LOG_MAX_LENGTH define
|
|
|
|
|
#if 1 |
|
|
|
|
GLint isLinked = 0; |
|
|
|
|
glGetProgramiv(rg->program_id, GL_LINK_STATUS, &isLinked); |
|
|
|
|
glGetProgramiv(sp.program_id, GL_LINK_STATUS, &isLinked); |
|
|
|
|
if (isLinked == GL_FALSE) { |
|
|
|
|
GLint maxLength = INFO_LOG_MAX_LENGTH; |
|
|
|
|
glGetProgramiv(rg->program_id, GL_INFO_LOG_LENGTH, &maxLength); |
|
|
|
|
glGetProgramiv(sp.program_id, GL_INFO_LOG_LENGTH, &maxLength); |
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
GLchar infoLog[312] = { 0 }; |
|
|
|
|
#else |
|
|
|
|
GLchar infoLog[maxLength] = { 0 }; |
|
|
|
|
#endif |
|
|
|
|
glGetProgramInfoLog(rg->program_id, maxLength, &maxLength, &infoLog[0]); |
|
|
|
|
glGetProgramInfoLog(sp.program_id, maxLength, &maxLength, &infoLog[0]); |
|
|
|
|
LOG(ERROR) << infoLog << "\n"; |
|
|
|
|
glDeleteProgram(rg->program_id); |
|
|
|
|
glDeleteProgram(sp.program_id); |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
@ -68,32 +81,130 @@ rgInitShaderProgram(gl_render_group* rg, const char * vertex_code, const char *
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gl_buffer * |
|
|
|
|
rgInitGLBuffer(gl_buffer* buffer, uint buffer_len) |
|
|
|
|
// TODO: should pass in a buffer of colors here instead of hexes, move to renderer.cpp
|
|
|
|
|
// we don't need to know about hexes here
|
|
|
|
|
#if 0 |
|
|
|
|
void |
|
|
|
|
rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
|
{ |
|
|
|
|
int buf_idx; |
|
|
|
|
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
|
|
|
|
|
GLfloat color_buf[3]; |
|
|
|
|
for (int i = 0; i < (int) hexes->size(); i++) |
|
|
|
|
{ |
|
|
|
|
buf_idx = i * buf_len_per_hex; |
|
|
|
|
hex_info hxi = (*hexes)[i]; |
|
|
|
|
utilConvertColor(color_buf, hxi.current_color); |
|
|
|
|
|
|
|
|
|
for (int j = 0; j < buf_len_per_hex; j+=3) |
|
|
|
|
{ |
|
|
|
|
buf[buf_idx + j] = color_buf[0]; |
|
|
|
|
buf[buf_idx + j + 1] = color_buf[1]; |
|
|
|
|
buf[buf_idx + j + 2] = color_buf[2]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
rgInitEntity(Entity* e) |
|
|
|
|
{ |
|
|
|
|
buffer->buffer_len = buffer_len; |
|
|
|
|
buffer->buffer = (GLfloat*) std::calloc(buffer_len, sizeof(GLfloat)); |
|
|
|
|
render_group* rg = UTIL_ALLOC(1, render_group); |
|
|
|
|
e->ren_group = rg; |
|
|
|
|
rg->draw_indexed = true; |
|
|
|
|
rg->use_normals = e->mesh_group.use_normals; |
|
|
|
|
uint num_meshes = rg->num_objects = e->mesh_group.num_meshes; |
|
|
|
|
|
|
|
|
|
if (!buffer->buffer) |
|
|
|
|
LOG(ERROR) << "Error allocating memory\n"; |
|
|
|
|
rg->render_objects = (render_object**) std::calloc(num_meshes, sizeof(render_object*)); |
|
|
|
|
|
|
|
|
|
return buffer; |
|
|
|
|
for (uint i = 0; i < num_meshes; i++) |
|
|
|
|
{ |
|
|
|
|
uint buffer_len = e->mesh_group.meshes[i]->num_vertices * 3; |
|
|
|
|
uint index_len = e->mesh_group.meshes[i]->num_indices; |
|
|
|
|
rg->render_objects[i] = allocateRenderObject(buffer_len, index_len); |
|
|
|
|
|
|
|
|
|
if (rg->render_objects[i] == nullptr) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
// TODO: safely free memory here when convertMeshInfo returns false
|
|
|
|
|
if (!convertMeshInfo(e->mesh_group.meshes[i], rg->render_objects[i], rg->use_normals)) |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gl_index_buffer * |
|
|
|
|
initGLIndexBuffer(gl_index_buffer* index_buffer, uint buffer_len) |
|
|
|
|
void |
|
|
|
|
rgDraw(render_group* rg, glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix, |
|
|
|
|
glm::vec3 light_position, GLuint light_id, bool update_vertex_data) |
|
|
|
|
{ |
|
|
|
|
for (uint i = 0; i < rg->num_objects; i++) { |
|
|
|
|
drawRenderObject(rg, rg->render_objects[i], model_matrix, view_matrix, projection_matrix, |
|
|
|
|
light_position, light_id, false); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
rgFree(render_group* rg) |
|
|
|
|
{ |
|
|
|
|
index_buffer->buffer_len = buffer_len; |
|
|
|
|
index_buffer->buffer = (uint*) std::calloc(buffer_len, sizeof(uint)); |
|
|
|
|
if (rg == nullptr) { |
|
|
|
|
LOG(ERROR) << "tried to free nullptr\n"; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!index_buffer->buffer) |
|
|
|
|
LOG(ERROR) << "Error allocating memory\n"; |
|
|
|
|
for (uint i = 0; i < rg->num_objects; i++) |
|
|
|
|
freeRenderObject(rg->render_objects[i]); |
|
|
|
|
|
|
|
|
|
return index_buffer; |
|
|
|
|
utilSafeFree(rg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
|
|
|
|
|
render_object * |
|
|
|
|
allocateRenderObject(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.buffer_len = buffer_len; |
|
|
|
|
ro->normal_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat); |
|
|
|
|
ro->normal_buffer.buffer_len = buffer_len; |
|
|
|
|
ro->color_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat); |
|
|
|
|
ro->color_buffer.buffer_len = buffer_len; |
|
|
|
|
|
|
|
|
|
if (index_len > 0) { |
|
|
|
|
ro->index_buffer.buffer = UTIL_ALLOC(index_len, uint); |
|
|
|
|
ro->index_buffer.buffer_len = index_len; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ro->vertex_buffer.buffer == nullptr || |
|
|
|
|
ro->normal_buffer.buffer == nullptr || |
|
|
|
|
ro->color_buffer.buffer == nullptr || |
|
|
|
|
((index_len > 0) && (ro->vertex_buffer.buffer == nullptr))) |
|
|
|
|
{ |
|
|
|
|
freeRenderObject(ro); |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ro; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
rgSendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target) |
|
|
|
|
freeRenderObject(render_object* ro) |
|
|
|
|
{ |
|
|
|
|
utilSafeFree(ro->vertex_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->normal_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->color_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->index_buffer.buffer); |
|
|
|
|
utilSafeFree(ro); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
sendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target) |
|
|
|
|
{ |
|
|
|
|
glGenBuffers(1, &buffer->buffer_id); |
|
|
|
|
glBindBuffer(target, buffer->buffer_id); |
|
|
|
|
@ -108,39 +219,14 @@ sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target)
|
|
|
|
|
glBufferData(target, index_buffer->buffer_len * sizeof(uint), index_buffer->buffer, usage); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
|
{ |
|
|
|
|
int buf_idx; |
|
|
|
|
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
|
|
|
|
|
GLfloat color_buf[3]; |
|
|
|
|
for (int i = 0; i < (int) hexes->size(); i++) |
|
|
|
|
{ |
|
|
|
|
buf_idx = i * buf_len_per_hex; |
|
|
|
|
hex_info hxi = (*hexes)[i]; |
|
|
|
|
utilConvertColor(color_buf, hxi.current_color); |
|
|
|
|
|
|
|
|
|
for (int j = 0; j < buf_len_per_hex; j+=3) |
|
|
|
|
{ |
|
|
|
|
buf[buf_idx + j] = color_buf[0]; |
|
|
|
|
buf[buf_idx + j + 1] = color_buf[1]; |
|
|
|
|
buf[buf_idx + j + 2] = color_buf[2]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NOTE: Copy assimp data to our structures for openGL
|
|
|
|
|
bool |
|
|
|
|
rgInitEntity(gl_render_group* rg, Entity* e) |
|
|
|
|
convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) |
|
|
|
|
{ |
|
|
|
|
rg->draw_indexed = true; |
|
|
|
|
rg->use_normals = (e->mesh->normals != nullptr); |
|
|
|
|
uint vertex_buf_len = e->mesh->num_vertices * 3; |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
uint vertex_buf_len = mesh->num_vertices * 3; |
|
|
|
|
GLfloat* vertex_buf = ro->vertex_buffer.buffer; |
|
|
|
|
GLfloat* color_buf = ro->color_buffer.buffer; |
|
|
|
|
GLfloat* normal_buf = ro->normal_buffer.buffer; |
|
|
|
|
uint* index_buf = ro->index_buffer.buffer; |
|
|
|
|
|
|
|
|
|
if (!vertex_buf || !color_buf || !normal_buf || !index_buf) |
|
|
|
|
return false; |
|
|
|
|
@ -150,8 +236,8 @@ rgInitEntity(gl_render_group* rg, Entity* e)
|
|
|
|
|
uint vertex_prop_index = 0; |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < vertex_buf_len; i++) { |
|
|
|
|
const glm::vec3& vertex = e->mesh->vertices[vertex_index]; |
|
|
|
|
const glm::vec3& normal = e->mesh->normals[vertex_index]; |
|
|
|
|
const glm::vec3& vertex = mesh->vertices[vertex_index]; |
|
|
|
|
const glm::vec3& normal = mesh->normals[vertex_index]; |
|
|
|
|
|
|
|
|
|
switch (vertex_prop_index) { |
|
|
|
|
case 0: vertex_buf[i] = vertex.x; break; |
|
|
|
|
@ -159,7 +245,7 @@ rgInitEntity(gl_render_group* rg, Entity* e)
|
|
|
|
|
case 2: vertex_buf[i] = vertex.z; break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (rg->use_normals) { |
|
|
|
|
if (use_normals) { |
|
|
|
|
switch (vertex_prop_index) { |
|
|
|
|
case 0: normal_buf[i] = normal.x; break; |
|
|
|
|
case 1: normal_buf[i] = normal.y; break; |
|
|
|
|
@ -167,7 +253,7 @@ rgInitEntity(gl_render_group* rg, Entity* e)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
color_buf[i] = e->mesh->diffuse_color[vertex_prop_index]; |
|
|
|
|
color_buf[i] = mesh->diffuse_color[vertex_prop_index]; |
|
|
|
|
vertex_prop_index++; |
|
|
|
|
|
|
|
|
|
if (vertex_prop_index == 3) { |
|
|
|
|
@ -177,89 +263,77 @@ rgInitEntity(gl_render_group* rg, Entity* e)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// dump indices
|
|
|
|
|
for (uint i = 0; i < e->mesh->num_indices; i++) |
|
|
|
|
index_buf[i] = e->mesh->indices[i]; |
|
|
|
|
for (uint i = 0; i < mesh->num_indices; i++) |
|
|
|
|
index_buf[i] = mesh->indices[i]; |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
sendBufferToGL(&ro->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
sendBufferToGL(&ro->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
if (use_normals) |
|
|
|
|
sendBufferToGL(&ro->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
sendIndexBufferToGL(&ro->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
rgDraw(gl_render_group* rg, GLenum draw_mode, glm::mat4 model_matrix, |
|
|
|
|
glm::mat4 view_matrix, glm::mat4 projection_matrix, |
|
|
|
|
drawRenderObject(render_group* rg, render_object* ro, |
|
|
|
|
glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix, |
|
|
|
|
glm::vec3 light_position, GLuint light_id, bool update_vertex_data) |
|
|
|
|
{ |
|
|
|
|
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]); |
|
|
|
|
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, rg->vertex_buffer.buffer_id); |
|
|
|
|
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, rg->vertex_buffer.buffer_len * sizeof(GLfloat), |
|
|
|
|
rg->vertex_buffer.buffer); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ro->vertex_buffer.buffer_len * sizeof(GLfloat), |
|
|
|
|
ro->vertex_buffer.buffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 2nd attribute buffer : colors
|
|
|
|
|
if (rg->color_buffer.buffer) |
|
|
|
|
if (ro->color_buffer.buffer) |
|
|
|
|
{ |
|
|
|
|
glEnableVertexAttribArray(1); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, ro->color_buffer.buffer_id); |
|
|
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
|
|
// TODO: maybe add an option to not send color data every frame?
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), |
|
|
|
|
rg->color_buffer.buffer); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ro->color_buffer.buffer_len * sizeof(GLfloat), |
|
|
|
|
ro->color_buffer.buffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3rd attribute buffer: normals
|
|
|
|
|
#if 1 |
|
|
|
|
if (rg->use_normals) { |
|
|
|
|
glEnableVertexAttribArray(2); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->normal_buffer.buffer_id); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, ro->normal_buffer.buffer_id); |
|
|
|
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 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]); |
|
|
|
|
glUniformMatrix3fv(rg->shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// 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); |
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro->index_buffer.buffer_id); |
|
|
|
|
glDrawElements(GL_TRIANGLES, ro->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); |
|
|
|
|
} else { |
|
|
|
|
glDrawArrays(draw_mode, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
|
glDrawArrays(rg->draw_mode, 0, ro->vertex_buffer.buffer_len / 3); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
if (rg->color_buffer.buffer) |
|
|
|
|
if (ro->color_buffer.buffer) |
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
if (rg->use_normals) |
|
|
|
|
glDisableVertexAttribArray(2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
rgFree(gl_render_group* rg) |
|
|
|
|
{ |
|
|
|
|
if (rg == nullptr) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
utilSafeFree(rg->vertex_buffer.buffer); |
|
|
|
|
utilSafeFree(rg->normal_buffer.buffer); |
|
|
|
|
utilSafeFree(rg->index_buffer.buffer); |
|
|
|
|
utilSafeFree(rg->color_buffer.buffer); |
|
|
|
|
utilSafeFree(rg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|