|
|
|
|
@ -20,7 +20,8 @@
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
bool initGLTexture(render_object* ro, util_image image); |
|
|
|
|
bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture); |
|
|
|
|
void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -72,6 +73,7 @@ rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char
|
|
|
|
|
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); |
|
|
|
|
@ -121,17 +123,27 @@ rgInitEntity(Entity* e)
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
meMeshInfo* mesh = e->mesh_group.meshes[i]; |
|
|
|
|
uint buffer_len = mesh->num_vertices * 3; |
|
|
|
|
uint index_len = mesh->num_indices; |
|
|
|
|
rg->render_objects[i] = allocateRenderObject(buffer_len, index_len); |
|
|
|
|
render_object* ro = rg->render_objects[i]; |
|
|
|
|
|
|
|
|
|
if (rg->render_objects[i] == nullptr) |
|
|
|
|
if (ro == nullptr) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
if (!convertMeshInfo(e->mesh_group.meshes[i], rg->render_objects[i], rg->use_normals)) { |
|
|
|
|
if (!convertMeshInfo(mesh, ro, rg->use_normals, mesh->use_texture)) { |
|
|
|
|
rgFree(rg); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (mesh->use_texture) { |
|
|
|
|
ro->use_texture = true; |
|
|
|
|
if (!initGLTexture(ro, mesh->diffuse_texture)) { |
|
|
|
|
LOG(ERROR) << "Error initializing GL texture\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
@ -210,6 +222,14 @@ rgDraw(render_group* rg, glm::mat4 model_matrix,
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ro->use_texture) { |
|
|
|
|
glEnableVertexAttribArray(3); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, ro->uv_buffer.buffer_id); |
|
|
|
|
glVertexAttribPointer(3, 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); |
|
|
|
|
@ -224,6 +244,8 @@ rgDraw(render_group* rg, glm::mat4 model_matrix,
|
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
if (rg->use_normals) |
|
|
|
|
glDisableVertexAttribArray(2); |
|
|
|
|
if (ro->use_texture) |
|
|
|
|
glDisableVertexAttribArray(3); |
|
|
|
|
|
|
|
|
|
glUseProgram(0); |
|
|
|
|
} |
|
|
|
|
@ -261,6 +283,8 @@ allocateRenderObject(uint buffer_len, uint index_len)
|
|
|
|
|
ro->normal_buffer.buffer_len = buffer_len; |
|
|
|
|
ro->color_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat); |
|
|
|
|
ro->color_buffer.buffer_len = buffer_len; |
|
|
|
|
ro->uv_buffer.buffer = UTIL_ALLOC(buffer_len, GLfloat); |
|
|
|
|
ro->uv_buffer.buffer_len = buffer_len; |
|
|
|
|
|
|
|
|
|
if (index_len > 0) { |
|
|
|
|
ro->index_buffer.buffer = UTIL_ALLOC(index_len, uint); |
|
|
|
|
@ -282,40 +306,38 @@ allocateRenderObject(uint buffer_len, uint index_len)
|
|
|
|
|
void |
|
|
|
|
freeRenderObject(render_object* ro) |
|
|
|
|
{ |
|
|
|
|
if (ro == nullptr) { |
|
|
|
|
LOG(ERROR) << "Tried to free nullptr\n"; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
utilSafeFree(ro->vertex_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->normal_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->color_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->uv_buffer.buffer); |
|
|
|
|
utilSafeFree(ro->index_buffer.buffer); |
|
|
|
|
utilSafeFree(ro); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
sendIndexBufferToGL(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->buffer_len * sizeof(uint), index_buffer->buffer, usage); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) |
|
|
|
|
convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals, bool use_texture) |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
GLfloat* uv_buf = ro->uv_buffer.buffer; |
|
|
|
|
uint* index_buf = ro->index_buffer.buffer; |
|
|
|
|
|
|
|
|
|
if (!vertex_buf || !color_buf || !normal_buf || !index_buf) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
// dump vertices, colors, and normals into render_group buffers
|
|
|
|
|
// dump vertices, colors, normals, and texture coords into render_group buffers
|
|
|
|
|
uint vertex_index = 0; |
|
|
|
|
uint vertex_prop_index = 0; |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < vertex_buf_len; i++) { |
|
|
|
|
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; |
|
|
|
|
@ -324,6 +346,7 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (use_normals) { |
|
|
|
|
const glm::vec3& normal = mesh->normals[vertex_index]; |
|
|
|
|
switch (vertex_prop_index) { |
|
|
|
|
case 0: normal_buf[i] = normal.x; break; |
|
|
|
|
case 1: normal_buf[i] = normal.y; break; |
|
|
|
|
@ -331,6 +354,15 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (use_texture) { |
|
|
|
|
const glm::vec3& uv = mesh->texture_coords[vertex_index]; |
|
|
|
|
switch (vertex_prop_index) { |
|
|
|
|
case 0: uv_buf[i] = uv.x; break; |
|
|
|
|
case 1: uv_buf[i] = uv.y; break; |
|
|
|
|
case 2: uv_buf[i] = uv.z; break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
color_buf[i] = mesh->diffuse_color[vertex_prop_index]; |
|
|
|
|
vertex_prop_index++; |
|
|
|
|
|
|
|
|
|
@ -348,8 +380,34 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals)
|
|
|
|
|
rgBufferData(&ro->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
if (use_normals) |
|
|
|
|
rgBufferData(&ro->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
if (use_texture) |
|
|
|
|
rgBufferData(&ro->uv_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
sendIndexBufferToGL(&ro->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initGLTexture(render_object* ro, util_image image) |
|
|
|
|
{ |
|
|
|
|
glGenTextures(1, &ro->tex_id); |
|
|
|
|
glBindTexture(GL_TEXTURE_2D, ro->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 |
|
|
|
|
sendIndexBufferToGL(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->buffer_len * sizeof(uint), index_buffer->buffer, usage); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|