|
|
|
|
@ -1,4 +1,6 @@
|
|
|
|
|
|
|
|
|
|
#include <glm/gtc/matrix_transform.hpp> |
|
|
|
|
|
|
|
|
|
#include "dumbLog.h" |
|
|
|
|
#include "render_object.h" |
|
|
|
|
|
|
|
|
|
@ -7,6 +9,7 @@
|
|
|
|
|
|
|
|
|
|
bool initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id); |
|
|
|
|
bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id); |
|
|
|
|
bool initGLTexture(const util_image image, GLuint& tex_id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// interface
|
|
|
|
|
@ -25,8 +28,11 @@ roInit(meMeshInfo* mi_in, render_object& ro_out)
|
|
|
|
|
ro_out.uv_buffer_id) && |
|
|
|
|
initGLIndexBuffer(mi_in->indices, |
|
|
|
|
mi_in->num_indices, |
|
|
|
|
ro_out.index_buffer_id)) |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -41,6 +47,76 @@ roFree(render_object& ro)
|
|
|
|
|
LOG(Debug) << "TODO: release GL buffers from render_object\n"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//----------- WIP --------------
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
// renRenderFrame
|
|
|
|
|
inline void |
|
|
|
|
updateMatrices(shader_program& shader, camera& cam, glm::mat4 node_xform) |
|
|
|
|
{ |
|
|
|
|
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.projection_matrix_id, 1, GL_FALSE, &cam.projection[0][0]); |
|
|
|
|
|
|
|
|
|
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(cam.model))); |
|
|
|
|
glUniformMatrix3fv(shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
inline void |
|
|
|
|
enableGLFloatBuffer(uint buffer_id, uint location) |
|
|
|
|
{ |
|
|
|
|
glEnableVertexAttribArray(location); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer_id); |
|
|
|
|
glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#include <sstream> // TODO: remove this and make something in util.h |
|
|
|
|
|
|
|
|
|
inline void |
|
|
|
|
updateLights(shader_program& shader, point_light* lights, uint num_lights) |
|
|
|
|
{ |
|
|
|
|
// 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(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(shader.program_id, ss.str().c_str()); |
|
|
|
|
glUniform3fv(light_pos_loc, 1, &lights[i].position[0]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//----------- WIP --------------
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
roDraw(render_object& ro, |
|
|
|
|
camera& cam, |
|
|
|
|
shader_program& shader, |
|
|
|
|
point_light* lights, |
|
|
|
|
uint num_lights) |
|
|
|
|
{ |
|
|
|
|
glUseProgram(shader.program_id); |
|
|
|
|
updateMatrices(shader, cam, ro.node_xform); |
|
|
|
|
enableGLFloatBuffer(ro.vertex_buffer_id, 0); |
|
|
|
|
enableGLFloatBuffer(ro.normal_buffer_id, 1); |
|
|
|
|
updateLights(shader, lights, num_lights); |
|
|
|
|
// 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); |
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro.index_buffer_id); |
|
|
|
|
glDrawElements(GL_TRIANGLES, ro.index_buffer_count, GL_UNSIGNED_INT, 0); |
|
|
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
glDisableVertexAttribArray(2); |
|
|
|
|
glUseProgram(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
|
|
|
|
|
@ -54,8 +130,7 @@ initGLFloatBuffer(glm::vec3* buffer, uint count, GLuint& buffer_id)
|
|
|
|
|
buffer, |
|
|
|
|
GL_STATIC_DRAW); |
|
|
|
|
|
|
|
|
|
// TODO: check for errors after buffering
|
|
|
|
|
return true; |
|
|
|
|
return (glGetError() == GL_NO_ERROR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
@ -68,6 +143,20 @@ initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id)
|
|
|
|
|
buffer, |
|
|
|
|
GL_STATIC_DRAW); |
|
|
|
|
|
|
|
|
|
// TODO: check for errors after buffering
|
|
|
|
|
return true; |
|
|
|
|
return (glGetError() == GL_NO_ERROR); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initGLTexture(const util_image image, GLuint& tex_id) |
|
|
|
|
{ |
|
|
|
|
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); |
|
|
|
|
} |
|
|
|
|
|