Browse Source

re-add draw calls for new renderer structure

testing
cinnaboot 6 years ago
parent
commit
62d78c4765
  1. 25
      examples/assimp_loading/main.cpp
  2. 11
      include/lights.h
  3. 11
      include/render_object.h
  4. 13
      include/renderer.h
  5. 7
      src/entity.cpp
  6. 4
      src/mesh.cpp
  7. 99
      src/render_object.cpp
  8. 41
      src/renderer.cpp

25
examples/assimp_loading/main.cpp

@ -59,16 +59,10 @@ main()
render_state* rs = renInit("assimp loading");
meInitAssimp();
// TODO: entInit() doesn't allocate memory because we want to do the
// allocation in one big block, but this is really clunky to use
render_group* group_1 = renAllocateGroup(1, *rs->default_shader);
entity spaceship = group_1->entities[0];
// TODO: this should be handled in entInit
entSetWorldPosition(spaceship, glm::vec3(0, 0, 0));
entScale(spaceship, glm::vec3(20, 20, 20));
// TODO: implement setting rotation from entity
//spaceship.rotation = glm::vec4(0, 0, 0, 0);
// TODO: this needs to be more convenient
rs->render_groups = renAllocateGroup(1, *rs->default_shader);
rs->render_group_count = 1;
entity& spaceship = rs->render_groups->entities[0];
// setup camera
cameraInitPerspective(
@ -92,10 +86,17 @@ main()
// NOTE: testing assimp animation info
logDebugAnimationInfo("../data/spaceship.glb");
if (entInit(spaceship, "../data/spaceship.glb"))
if (entInit(spaceship, "../data/spaceship.glb")) {
// TODO: this should be handled in entInit
entSetWorldPosition(spaceship, glm::vec3(0, 0, 0));
entScale(spaceship, glm::vec3(20, 20, 20));
// TODO: implement setting rotation from entity
//spaceship.rotation = glm::vec4(0, 0, 0, 0);
doRenderLoop(rs, doFrameCallback);
else
} else {
LOG(Error) << "Error initializing entity, exiting\n";
}
renShutdown(rs);
meShutdownAssimp();

11
include/lights.h

@ -0,0 +1,11 @@
#pragma once
struct point_light
{
uint light_ID;
glm::vec3 position;
glm::vec3 color;
float intensity;
};

11
include/render_object.h

@ -4,7 +4,10 @@
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "camera.h"
#include "lights.h"
#include "mesh.h"
#include "shader_program.h"
struct render_object
@ -16,6 +19,7 @@ struct render_object
GLuint normal_buffer_id;
GLuint uv_buffer_id;
GLuint index_buffer_id;
GLuint index_buffer_count;
};
bool roInit(meMeshInfo* mi_in, render_object& ro_out);
@ -23,5 +27,8 @@ bool roInit(meMeshInfo* mi_in, render_object& ro_out);
// TODO: make use of glIsBuffer/glDeleteBuffers
void roFree(render_object& ro);
// TODO: implement me!
void roDraw(render_object& ro);
void roDraw(render_object& ro,
camera& cam,
shader_program& shader,
point_light* lights,
uint num_lights);

13
include/renderer.h

@ -11,6 +11,7 @@
#include "camera.h"
#include "entity.h"
#include "lights.h"
#include "util.h"
#include "shader_program.h"
@ -22,14 +23,6 @@ struct SDL_Handles
SDL_DisplayMode currentDisplayMode;
};
struct point_light
{
uint light_ID;
glm::vec3 position;
glm::vec3 color;
float intensity;
};
// NOTE: array of entities rendered with the same shader program
struct render_group
{
@ -47,7 +40,9 @@ struct render_state
camera cam;
util_RGBA clear_col;
render_group** render_groups;
// TODO: this really needs to be a resizable array, or linked list, or
// ...gasp, std::vector
render_group* render_groups;
uint render_group_count;
shader_program* default_shader;

7
src/entity.cpp

@ -65,6 +65,11 @@ void
entScale(entity& e, glm::vec3 v)
{
e.world_transform = glm::scale(e.world_transform, v);
for (uint i = 0; i < e.mesh_group.num_meshes; i++) {
render_object& ro = e.render_objs[i];
ro.node_xform = glm::scale(ro.node_xform, v);
}
}
@ -75,7 +80,7 @@ loadMeshIntoGL(entity& e)
{
for (uint i = 0; i < e.mesh_group.num_meshes; i++) {
assert(e.render_objs != nullptr);
render_object ro = e.render_objs[i];
render_object& ro = e.render_objs[i];
meMeshInfo* mi = e.mesh_group.meshes[i];
assert(mi != nullptr);

4
src/mesh.cpp

@ -51,8 +51,8 @@ meLoadFromFile(meMeshGroup& mesh_group, const char* filepath)
aiMesh* mesh = scene->mMeshes[i];
meMeshInfo* mi = copyMeshInfo(scene, mesh);
if (!mesh->HasTextureCoords(0)
|| !loadDiffuseTexture(scene, mesh, mi))
if (!mesh->HasTextureCoords(0) ||
!loadDiffuseTexture(scene, mesh, mi))
{
LOG(Error) << "Error loading texture, cleaning up import\n";
freeMesh(mi);

99
src/render_object.cpp

@ -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);
}

41
src/renderer.cpp

@ -12,6 +12,7 @@
#include <glm/gtc/matrix_transform.hpp>
#include "dumbLog.h"
#include "render_object.h"
#include "renderer.h"
#include "default_shaders.cpp"
@ -66,6 +67,18 @@ renInit(const char* title, glm::vec2 viewport_dims)
void
renShutdown(render_state* rs)
{
// TODO: need a nicer way to loop over entities and render_objects
for (uint i = 0; i < rs->render_group_count; i++) {
render_group& rg = rs->render_groups[i];
for (uint j = 0; j < rg.entity_count; j++) {
entity& e = rg.entities[j];
for (uint k = 0; k < e.ro_count; k++)
roFree(e.render_objs[k]);
}
}
utilSafeFree(rs->lights);
SDL_GL_DeleteContext(rs->handles.glContext);
SDL_DestroyWindow(rs->handles.window);
@ -78,6 +91,7 @@ renAllocateGroup(uint entity_count, shader_program shader)
assert(entity_count > 0);
render_group* rg = UTIL_ALLOC(1, render_group);
rg->entities = UTIL_ALLOC(entity_count, entity);
rg->entity_count = entity_count;
rg->shader = shader;
return rg;
}
@ -88,20 +102,21 @@ renRenderFrame(render_state* rs)
glClearColor(rs->clear_col.R, rs->clear_col.G, rs->clear_col.B, rs->clear_col.A);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// TODO: loop over new render_groups on render_state
// make call to roDraw for each render_object in each entity
#if 0
// entities
for (uint i = 0; i < entity_count; i++) {
rgDraw(entities[i].ren_group,
entities[i].world_transform,
rs->cam.view,
rs->cam.projection,
rs->lights,
rs->num_lights
);
for (uint i = 0; i < rs->render_group_count; i++) {
render_group& rg = rs->render_groups[i];
for (uint j = 0; j < rg.entity_count; j++) {
entity& e = rg.entities[j];
for (uint k = 0; k < e.ro_count; k++) {
roDraw(e.render_objs[k],
rs->cam,
rg.shader,
rs->lights,
rs->num_lights);
}
}
}
#endif
}

Loading…
Cancel
Save