Browse Source

restructure high-lvel interface for new asset system

render_group_fix
cinnaboot 5 years ago
parent
commit
004e0539cf
  1. 6
      README
  2. 25
      examples/render_groups/main.cpp
  3. 5
      include/asset.h
  4. 2
      include/camera.h
  5. 25
      include/entity.h
  6. 11
      include/render_object.h
  7. 37
      include/renderer.h
  8. 2
      include/util.h
  9. 12
      src/asset.cpp
  10. 33
      src/camera.cpp
  11. 33
      src/entity.cpp
  12. 286
      src/render_object.cpp
  13. 86
      src/renderer.cpp
  14. 2
      src/util.cpp

6
README

@ -9,13 +9,15 @@ Features:
pixels
TODO:
fix lighting normal bugs (branch "normal_bug")
store meshes separately from entities for reuse
linear memory allocator for assets (branch "render_group_fix")
maybe update UTIL_ALLOC macro to use arena allocator?
fix lighting normal bugs (branch "normal_bug")
finish node animations from assimp
add input abstraction for SDL
store meshes separately from entities for reuse
add a function to update camera transforms only once per frame, per shader
update camera to use quaternions for rotation
re-combine simple/default meshes/render_objects
Dependencies:
glew

25
examples/render_groups/main.cpp

@ -53,6 +53,7 @@ createModelEntities(render_group* rg,
glm::vec3 max_pos,
glm::vec3 scaling)
{
#if 0
assert(rg != nullptr);
for (uint i = 0; i < item_count; i++) {
@ -72,11 +73,14 @@ createModelEntities(render_group* rg,
}
return true;
#endif
return false;
}
void
doFrameCallbackPre(render_state* rs)
{
#if 0
static input_state is = {};
inputProcessEvents(&is);
@ -89,9 +93,11 @@ doFrameCallbackPre(render_state* rs)
static float angle = 1.2 / 60; // NOTE: 60 FPS
static glm::vec3 axis(0, 0, 1);
for (uint i = 0; i < rs->render_group_count; i++) {
for (uint j = 0; j < rs->render_groups[i]->entity_count; j++) {
entity& e = rs->render_groups[i]->entities[j];
for (uint i = 0; i < rs->render_groups->count; i++) {
render_group* rg = &rs->render_groups->groups[i];
for (uint j = 0; j < rg->count; j++) {
entity* e = &rg->entities[j];
entRotate(e, angle, axis);
}
}
@ -105,6 +111,7 @@ doFrameCallbackPre(render_state* rs)
l2.position = glm::vec3(
square.world_transform * glm::vec4(10000, 0, -1000, 1));
rs->lights->needs_update = true;
#endif
}
int
@ -177,10 +184,22 @@ main()
renDoRenderLoop(rs, 60, doFrameCallbackPre);
#endif
#if 0
model* ret = assetLoadFromFile(rs->assets,
rs->arena,
"../data/blender/spaceship.gltf");
assert(ret != nullptr);
#endif
// NOTE: testing entity system with new asset structures
// FIXME: wtf is this?
shader_wrapper sw = { DEFAULT_SHADER, rs->default_shader, nullptr };
render_group* rg = rgAlloc(rs->render_groups, 64, sw);
entity* e =
rgAppend(rg, rs->assets, rs->arena, "../data/blender/spaceship.gltf");
assert(e != nullptr);
renDoRenderLoop(rs, 60);
renShutdown(rs);
return 0;

5
include/asset.h

@ -20,11 +20,11 @@ struct mesh
uint num_indices;
glm::vec3* vertices;
glm::vec3* normals;
uint* indices;
// FIXME: will have to use vec2 here to be able to use memcpy
// this will break render_object::initGLFLoatBuffer logic which expects
// vec3
glm::vec2* texture_coords;
uint* indices;
glm::mat4* xform;
};
@ -57,3 +57,6 @@ assetLoadFromFile(model_assets* assets,
memory_arena* arena,
const char* filename);
model*
assetGetCached(model_assets* assets, uint64_t path_hash);

2
include/camera.h

@ -44,7 +44,7 @@ cameraIntersectPlane(camera& cam,
v3f& intersection);
void
cameraInitPerspective(camera& cam,
cameraInitPerspective(camera* cam,
glm::vec3 position,
glm::vec3 target,
glm::vec3 world_up,

25
include/entity.h

@ -3,34 +3,23 @@
#include <glm/glm.hpp>
#include "mesh.h"
#include "asset.h"
#include "render_object.h"
#include "types.h"
// TODO: having a separate code path for each shader is annoying and error
// prone. could try using opaque pointers at high level (renderer, entity),
// and then cast to the appropriate render_object/mesh/shader type in the lower
// level functions based on the mesh_type property
struct entity
{
glm::mat4 world_transform;
// TODO: hide simple_mesh/mesh_group pointer behind abstraction
simple_mesh* mesh;
// TODO: should be a pointer into a global array of mesh_info(s) or
// mesh_groups stored on the render_state object
mesh_group meshes;
//mesh_group meshes;
uint64_t model_id; // NOTE: filepath hash
render_objects* render_objs;
};
bool entInitModel(entity& e, const char* model_path);
bool entInitMesh(entity& e, simple_mesh* mesh, GLenum draw_mode);
void entUpdateSimpleMesh(entity& e, simple_mesh* mesh, GLenum draw_mode);
bool entInitModel(entity* e, model* mdl);
void entFree(entity& e);
// FIXME: might as well stay consistent and make all these pointers
void entFree(entity* e);
void entSetWorldPosition(entity& e, glm::vec3 v);
@ -38,5 +27,5 @@ void entTranslate(entity& e, glm::vec3 v);
void entScale(entity& e, glm::vec3 v);
void entRotate(entity& e, float angle, glm::vec3 axis);
void entRotate(entity* e, float angle, glm::vec3 axis);

11
include/render_object.h

@ -4,19 +4,16 @@
#include <GL/glew.h>
#include <glm/glm.hpp>
#include "asset.h"
#include "camera.h"
#include "lights.h"
#include "mesh.h"
#include "shader_program.h"
struct render_objects;
render_objects*
roInitModel(mesh_group meshes);
render_objects*
roInitSimpleMesh(simple_mesh& mesh_in, GLenum draw_mode);
roInitModel(model* mdl);
void
roFree(render_objects* r_objs);
@ -24,9 +21,7 @@ roFree(render_objects* r_objs);
void
roDraw(render_objects* r_ojbs,
glm::mat4 world_transform,
camera& cam,
camera* cam,
shader_wrapper sw,
light_group* lights);
void
roUpdateSimpleMesh(render_objects* r_objs, simple_mesh* mesh, GLenum draw_mode);

37
include/renderer.h

@ -22,19 +22,27 @@ struct render_group
{
// TODO: also needs to be resizable
entity* entities;
uint entity_count;
uint count;
uint max_size;
shader_wrapper shader;
};
// TODO: does it makes sense to have the mesh_type stored on the
// render_group? can then easily pass to roDraw() along with the entity
// render_objects...
// only the mesh object and render object really need to know about the
// mesh_type...
//
//mesh_t mesh_type;
struct rg_info
{
render_group* groups;
uint count;
uint max_size;
};
render_group*
rgAlloc(rg_info* rgi, uint num_entites, shader_wrapper shader);
entity*
rgAppend(render_group* rg,
model_assets* assets,
memory_arena* arena,
const char* model_path);
struct SDL_Handles
{
SDL_Window *window;
@ -42,18 +50,16 @@ struct SDL_Handles
SDL_DisplayMode currentDisplayMode;
};
#define DEFAULT_RG_COUNT 256
struct render_state
{
glm::vec2 viewport_dims;
camera cam;
camera* cam;
util_RGBA clear_col;
SDL_Handles* handles;
bool running;
// TODO: this really needs to be a resizable array, or linked list, or
// ...gasp, std::vector
render_group** render_groups;
uint render_group_count;
rg_info* render_groups;
// WIP
model_assets* assets;
@ -79,9 +85,6 @@ renInit(const char* title = "Tangerine",
void renShutdown(render_state* rs);
render_group*
renAllocateGroup(uint entity_count, shader_wrapper shader);
// NOTE: callback function signature to use with renDoRenderLoop()
typedef void (*frame_callback_fn) (render_state*);

2
include/util.h

@ -89,7 +89,7 @@ bool utilMatchPrefix(const char* lhs, const char* rhs, int sz);
#define FNV1_64_INIT ((uint64_t) 0xcbf29ce484222325ULL)
#define FNV_64_PRIME ((uint64_t) 0x100000001b3ULL)
uint64_t
utilFNV64a_str(char *str, uint64_t hval = FNV1_64_INIT);
utilFNV64a_str(const char *str, uint64_t hval = FNV1_64_INIT);
//-----------------
// Memory allocation

12
src/asset.cpp

@ -244,3 +244,15 @@ assetLoadFromFile(model_assets* assets,
return mdl;
}
// FIXME: reorganize asset.cpp, put interface at the top
model*
assetGetCached(model_assets* assets, uint64_t path_hash)
{
for (uint i = 0; i < assets->count; i++) {
if (assets->models[i].filepath_hash == path_hash)
return &assets->models[i];
}
LOG(Debug) << "asset not cached: " << path_hash << "\n";
return nullptr;
}

33
src/camera.cpp

@ -20,7 +20,7 @@ inline glm::vec3 convertv3f(v3f v);
// interface
void
cameraInitPerspective(camera& cam,
cameraInitPerspective(camera* cam,
glm::vec3 position,
glm::vec3 target,
glm::vec3 world_up,
@ -28,26 +28,27 @@ cameraInitPerspective(camera& cam,
{
assert(aspect_ratio > 0);
cam.position = position;
cam.target = target;
cam.world_up = world_up;
cam.projection = glm::infinitePerspective(glm::radians(FOV),
cam->position = position;
cam->target = target;
cam->world_up = world_up;
cam->projection = glm::infinitePerspective(glm::radians(FOV),
aspect_ratio,
NEAR_CLIP_PLANE);
cam.forward = glm::normalize(target - position);
cam.left = glm::normalize(glm::cross(cam.world_up, cam.forward));
cam.up = glm::normalize(glm::cross(cam.forward, cam.left));
cam->forward = glm::normalize(target - position);
cam->left = glm::normalize(glm::cross(cam->world_up, cam->forward));
cam->up = glm::normalize(glm::cross(cam->forward, cam->left));
cam.hAngle = glm::atan(cam.forward.x, cam.forward.y);
cam->hAngle = glm::atan(cam->forward.x, cam->forward.y);
// NOTE: get absolute value of relative axis for vAngle component
real32 len = glm::sqrt(glm::pow(cam.forward.y, 2) +
glm::pow(cam.forward.x, 2));
cam.vAngle = glm::atan(cam.forward.z, len);
cam.view = glm::lookAt(cam.position, cam.position + cam.forward, cam.up);
cam.model = glm::mat4(1.0f);
cam.MVP = cam.projection * cam.view * cam.model;
real32 len = glm::sqrt(glm::pow(cam->forward.y, 2) +
glm::pow(cam->forward.x, 2));
cam->vAngle = glm::atan(cam->forward.z, len);
cam->view =
glm::lookAt(cam->position, cam->position + cam->forward, cam->up);
cam->model = glm::mat4(1.0f);
cam->MVP = cam->projection * cam->view * cam->model;
}
void

33
src/entity.cpp

@ -14,7 +14,7 @@ void initDefaults(entity& e);
// interface
#if 0
bool
entInitModel(entity& e, const char* model_path)
{
@ -31,35 +31,26 @@ entInitModel(entity& e, const char* model_path)
entFree(e);
return false;
}
#endif
bool
entInitMesh(entity& e, simple_mesh* mesh, GLenum draw_mode)
entInitModel(entity* e, model* mdl)
{
initDefaults(e);
e.mesh = mesh;
e.render_objs = roInitSimpleMesh(*e.mesh, draw_mode);
e->render_objs = roInitModel(mdl);
if (e.render_objs == nullptr)
if (e->render_objs == nullptr) {
entFree(e);
return false;
}
return true;
}
void
entUpdateSimpleMesh(entity& e, simple_mesh* mesh, GLenum draw_mode)
{
roUpdateSimpleMesh(e.render_objs, mesh, draw_mode);
}
void
entFree(entity& e)
entFree(entity* e)
{
roFree(e.render_objs);
e.render_objs = nullptr;
meFreeMeshGroup(e.meshes);
if (e.mesh != nullptr) meFreeSimpleMesh(e.mesh);
e.mesh = nullptr;
roFree(e->render_objs);
e->render_objs = nullptr;
}
void
@ -83,9 +74,9 @@ entScale(entity& e, glm::vec3 v)
}
void
entRotate(entity& e, float angle, glm::vec3 axis)
entRotate(entity*& e, float angle, glm::vec3 axis)
{
e.world_transform = glm::rotate(e.world_transform, angle, axis);
e->world_transform = glm::rotate(e->world_transform, angle, axis);
}

286
src/render_object.cpp

@ -5,8 +5,6 @@
#include "render_object.h"
// forward declarations
struct default_render_object
{
glm::mat4 node_xform;
@ -19,52 +17,30 @@ struct default_render_object
uint index_buffer_count;
};
struct simple_render_object
{
glm::mat4 model_transform;
GLuint vertex_buffer_id;
GLuint vertex_color_buffer_id;
uint vertex_count;
GLenum draw_mode;
};
struct render_objects
{
void* objects;
default_render_object* objects;
uint count;
mesh_t mesh_type;
};
// forward declarations
void drawDefault(render_objects* r_objs,
glm::mat4 world_transform,
camera& cam,
shader_wrapper sw,
light_group* lights);
void drawSimple(render_objects* r_objs,
glm::mat4 world_transform,
camera& cam,
camera* cam,
shader_wrapper sw,
light_group* lights);
inline void enableGLFloatBuffer(uint buffer_id, uint location);
bool initGLFloatBuffer(glm::vec3* buffer,
uint count,
GLuint& buffer_id,
GLenum usage = GL_STATIC_DRAW);
bool initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id);
bool initGLTexture(const util_image image, GLuint& tex_id);
bool loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in);
inline void updateMatrices(default_shader_program* shader,
camera& cam,
glm::mat4 world_xform,
glm::mat4 node_xform);
bool loadMeshIntoGL(default_render_object* ro_out, mesh* me_in);
// interface
render_objects*
roInitModel(mesh_group mg)
roInitModel(model* mdl)
{
uint count = mg.num_meshes;
uint count = mdl->num_meshes;
assert(count > 0);
render_objects* r_objs = UTIL_ALLOC(1, render_objects);
@ -75,7 +51,7 @@ roInitModel(mesh_group mg)
default_render_object* objects = (default_render_object*) r_objs->objects;
for (uint i = 0; i < count; i++) {
if (!loadMeshIntoGL(&objects[i], mg.meshes[i])) {
if (!loadMeshIntoGL(&objects[i], &mdl->meshes[i])) {
roFree(r_objs);
return nullptr;
}
@ -84,44 +60,13 @@ roInitModel(mesh_group mg)
return r_objs;
}
render_objects*
roInitSimpleMesh(simple_mesh& mesh_in, GLenum draw_mode)
{
render_objects* r_objs = UTIL_ALLOC(1, render_objects);
r_objs->count = 1;
r_objs->mesh_type = SIMPLE_MESH;
r_objs->objects = UTIL_ALLOC(1, simple_render_object);
simple_render_object* objects = (simple_render_object*) r_objs->objects;
if (initGLFloatBuffer(mesh_in.vertices,
mesh_in.num_vertices,
objects->vertex_buffer_id,
GL_DYNAMIC_DRAW) &&
initGLFloatBuffer(mesh_in.vert_colors,
mesh_in.num_vertices,
objects->vertex_color_buffer_id,
GL_DYNAMIC_DRAW))
{
objects->model_transform = mesh_in.model_transform;
objects->vertex_count = mesh_in.num_vertices;
objects->draw_mode = draw_mode;
return r_objs;
}
LOG(Error) << "Failed to initialize render_object\n";
roFree(r_objs);
return nullptr;
}
void
roFree(render_objects* r_objs)
{
if (r_objs->mesh_type == SIMPLE_MESH) {
//
} else if (r_objs->mesh_type == DEFAULT_MESHES) {
default_render_object* objects =
(default_render_object*) r_objs->objects;
default_render_object* objects = r_objs->objects;
for (uint i = 0; i < r_objs->count; i++) {
glDeleteBuffers(1, &objects[i].vertex_buffer_id);
@ -140,98 +85,39 @@ roFree(render_objects* r_objs)
void
roDraw(render_objects* r_objs,
glm::mat4 world_transform,
camera& cam,
camera* cam,
shader_wrapper sw,
light_group* lights)
{
if (r_objs->mesh_type == SIMPLE_MESH)
drawSimple(r_objs, world_transform, cam, sw, lights);
else if (r_objs->mesh_type == DEFAULT_MESHES)
drawDefault(r_objs, world_transform, cam, sw, lights);
assert(r_objs->mesh_type == DEFAULT_MESHES);
drawDefault(r_objs, world_transform, cam, sw, lights);
}
void
roUpdateSimpleMesh(render_objects* r_objs, simple_mesh* mesh, GLenum draw_mode)
{
assert(r_objs != nullptr && r_objs->objects != nullptr);
assert(mesh != nullptr && mesh->vertices != nullptr);
simple_render_object* sro = (simple_render_object*) r_objs->objects;
assert(sro->vertex_count == mesh->num_vertices);
sro->draw_mode = draw_mode;
glBindBuffer(GL_ARRAY_BUFFER, sro->vertex_buffer_id);
glBufferSubData(
GL_ARRAY_BUFFER,
0,
3 * sro->vertex_count * sizeof(GLfloat),
mesh->vertices);
glBindBuffer(GL_ARRAY_BUFFER, sro->vertex_color_buffer_id);
glBufferSubData(
GL_ARRAY_BUFFER,
0,
3 * sro->vertex_count * sizeof(GLfloat),
mesh->vert_colors);
}
// internal
void
drawDefault(render_objects* r_objs,
glm::mat4 world_transform,
camera& cam,
shader_wrapper sw,
light_group* lights)
bool
initGLBuffer(void* buffer,
uint count,
GLuint* buffer_id,
uint el_count = 3,
uint el_size = sizeof(float),
GLenum target = GL_ARRAY_BUFFER,
GLenum usage = GL_STATIC_DRAW)
{
default_shader_program* shader = sw.default_shader;
default_render_object* objects = (default_render_object*) r_objs->objects;
glUseProgram(shader->program_id);
updateMatrices(shader, cam, world_transform, objects->node_xform);
if (lights->needs_update) lightsUpdate(lights, shader);
for (uint i = 0; i < r_objs->count; i++) {
enableGLFloatBuffer(objects[i].vertex_buffer_id, 0);
enableGLFloatBuffer(objects[i].normal_buffer_id, 1);
// TODO: could pass in a stride parameter here to enableGLFloatBuffer()
// could then use a 2d buffer for uv coords
enableGLFloatBuffer(objects[i].uv_buffer_id, 2);
glBindTexture(GL_TEXTURE_2D, objects[i].tex_id);
glUniform1i(shader->sampler_id, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objects[i].index_buffer_id);
glDrawElements(GL_TRIANGLES,
objects[i].index_buffer_count,
GL_UNSIGNED_INT,
0);
if ((el_count == 3 && el_size == sizeof(float))
|| (el_count == 2 && el_size == sizeof(float))
|| (el_count == 1 && el_size == sizeof(unsigned short)))
{
glGenBuffers(1, buffer_id);
glBindBuffer(target, *buffer_id);
glBufferData(target, count * el_count * el_size, buffer, usage);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
return (glGetError() == GL_NO_ERROR);
}
glUseProgram(0);
}
void
drawSimple(render_objects* r_objs,
glm::mat4 world_transform,
camera& cam,
shader_wrapper sw,
light_group* lights)
{
simple_render_object* ro = (simple_render_object*) r_objs->objects;
simple_shader_program* shader =
(simple_shader_program*) sw.simple_shader;
glUseProgram(shader->program_id);
cam.MVP = cam.projection * cam.view * ro->model_transform;
glUniformMatrix4fv(
shader->world_transform_id, 1, GL_FALSE, &world_transform[0][0]);
glUniformMatrix4fv(shader->MVP_id, 1, GL_FALSE, &cam.MVP[0][0]);
enableGLFloatBuffer(ro->vertex_buffer_id, 0);
enableGLFloatBuffer(ro->vertex_color_buffer_id, 1);
glDrawArrays(ro->draw_mode, 0, ro->vertex_count);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glUseProgram(0);
return false;
}
inline void
@ -242,35 +128,6 @@ enableGLFloatBuffer(uint buffer_id, uint location)
glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
}
bool
initGLFloatBuffer(glm::vec3* buffer,
uint count,
GLuint& buffer_id,
GLenum usage)
{
glGenBuffers(1, &buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
glBufferData(GL_ARRAY_BUFFER,
count * 3 * sizeof(GLfloat), // NOTE: 3 floats per vertex prop
buffer,
usage);
return (glGetError() == GL_NO_ERROR);
}
bool
initGLIndexBuffer(uint* buffer, uint num_indices, GLuint& buffer_id)
{
glGenBuffers(1, &buffer_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
num_indices * sizeof(uint),
buffer,
GL_STATIC_DRAW);
return (glGetError() == GL_NO_ERROR);
}
bool
initGLTexture(const util_image image, GLuint& tex_id)
{
@ -287,27 +144,26 @@ initGLTexture(const util_image image, GLuint& tex_id)
}
bool
loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in)
{
assert(mi_in != nullptr && ro_out != nullptr);
if (initGLFloatBuffer(mi_in->vertices,
mi_in->num_vertices,
ro_out->vertex_buffer_id) &&
initGLFloatBuffer(mi_in->normals,
mi_in->num_vertices,
ro_out->normal_buffer_id) &&
// FIXME: this is broken now with tinygltf, need to use vec2
initGLFloatBuffer(mi_in->texture_coords,
mi_in->num_vertices,
ro_out->uv_buffer_id) &&
initGLIndexBuffer(mi_in->indices,
mi_in->num_indices,
ro_out->index_buffer_id) &&
initGLTexture(mi_in->diffuse_texture, ro_out->tex_id))
loadMeshIntoGL(default_render_object* ro_out, mesh* mesh_in)
{
assert(mesh_in != nullptr && ro_out != nullptr);
if (initGLBuffer(mesh_in->vertices, mesh_in->num_vertices,
&ro_out->vertex_buffer_id)
&& initGLBuffer(mesh_in->normals, mesh_in->num_vertices,
&ro_out->normal_buffer_id)
&& initGLBuffer(mesh_in->texture_coords, mesh_in->num_vertices,
&ro_out->uv_buffer_id, 2)
&& initGLBuffer(mesh_in->indices, mesh_in->num_indices,
&ro_out->index_buffer_id, 1, sizeof(unsigned short),
GL_ELEMENT_ARRAY_BUFFER)
// FIXME: re-implement diffuse texture, but with index into an array
// on render_state
//&& initGLTexture(mesh_in->diffuse_texture, ro_out->tex_id))
)
{
ro_out->node_xform = mi_in->model_transform;
ro_out->index_buffer_count = mi_in->num_indices;
ro_out->node_xform = *mesh_in->xform;
ro_out->index_buffer_count = mesh_in->num_indices;
return true;
}
@ -320,19 +176,55 @@ loadMeshIntoGL(default_render_object* ro_out, mesh_info* mi_in)
// renRenderFrame
inline void
updateMatrices(default_shader_program* shader,
camera& cam,
camera* cam,
glm::mat4 world_xform,
glm::mat4 node_xform)
{
glUniformMatrix4fv(
shader->world_transform_id, 1, GL_FALSE, &world_xform[0][0]);
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->view_matrix_id, 1, GL_FALSE, &cam->view[0][0]);
glUniformMatrix4fv(shader->projection_matrix_id, 1, GL_FALSE,
&cam.projection[0][0]);
&cam->projection[0][0]);
glm::mat3 normal_matrix = glm::transpose(
glm::inverse(glm::mat3(cam.model)));
glm::inverse(glm::mat3(cam->model)));
glUniformMatrix3fv(shader->normal_matrix_id, 1, GL_FALSE,
&normal_matrix[0][0]);
}
void
drawDefault(render_objects* r_objs,
glm::mat4 world_transform,
camera* cam,
shader_wrapper sw,
light_group* lights)
{
default_shader_program* shader = sw.default_shader;
default_render_object* objects = r_objs->objects;
glUseProgram(shader->program_id);
updateMatrices(shader, cam, world_transform, objects->node_xform);
if (lights->needs_update) lightsUpdate(lights, shader);
for (uint i = 0; i < r_objs->count; i++) {
enableGLFloatBuffer(objects[i].vertex_buffer_id, 0);
enableGLFloatBuffer(objects[i].normal_buffer_id, 1);
// TODO: could pass in a stride parameter here to enableGLFloatBuffer()
// could then use a 2d buffer for uv coords
enableGLFloatBuffer(objects[i].uv_buffer_id, 2);
glBindTexture(GL_TEXTURE_2D, objects[i].tex_id);
glUniform1i(shader->sampler_id, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objects[i].index_buffer_id);
glDrawElements(GL_TRIANGLES,
objects[i].index_buffer_count,
GL_UNSIGNED_INT,
0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
glUseProgram(0);
}

86
src/renderer.cpp

@ -37,6 +37,53 @@ void setDefaults(render_state* rs, glm::vec2 viewport_dims);
// interface
render_group*
rgAlloc(rg_info* rgi, uint num_entites, shader_wrapper shader)
{
assert(rgi != nullptr);
if (rgi->count < rgi->max_size) {
render_group* rg = &rgi->groups[rgi->count];
rgi->count++;
rg->entities = UTIL_ALLOC(num_entites, entity);
rg->max_size = num_entites;
rg->shader = shader;
return rg;
}
LOG(Error) << "no free render_group\n";
return nullptr;
}
entity*
rgAppend(render_group* rg,
model_assets* assets,
memory_arena* arena,
const char* model_path)
{
assert(rg != nullptr);
if (rg->count < rg->max_size) {
entity* e = &rg->entities[rg->count];
rg->count++;
// FIXME: maybe actually load the model here...
// get path hash
// check for hash in rs->assets->models[i]->filepath_hash
// load new model if not found
model* mdl = assetGetCached(assets, utilFNV64a_str(model_path));
if (mdl == nullptr)
mdl = assetLoadFromFile(assets, arena, model_path);
// load model into gl, entInitModel(e, model)
if (entInitModel(e, mdl))
return e;
}
LOG(Error) << "no free entity in render_group\n";
return nullptr;
}
render_state*
renInit(const char* title,
glm::vec2 viewport_dims,
@ -46,8 +93,14 @@ renInit(const char* title,
{
render_state* rs = UTIL_ALLOC(1, render_state);
rs->handles = UTIL_ALLOC(1, SDL_Handles);
rs->cam = UTIL_ALLOC(1, camera);
// TODO: add parameter for custom render_group count
rs->render_groups = UTIL_ALLOC(1, rg_info);
rs->render_groups->groups = UTIL_ALLOC(DEFAULT_RG_COUNT, render_group);
rs->render_groups->max_size = DEFAULT_RG_COUNT;
rs->arena = arenaInit(arena_size);
rs->assets = assetInitBlock(rs->arena, asset_size);
rs->lights = lightsInit();
setDefaults(rs, viewport_dims);
if (initSDL(rs->handles, SDL_init_flags) &&
@ -66,11 +119,11 @@ renInit(const char* title,
void
renShutdown(render_state* rs)
{
for (uint i = 0; i < rs->render_group_count; i++) {
for (uint j = 0; j < rs->render_groups[i]->entity_count; j++)
entFree(rs->render_groups[i]->entities[j]);
for (uint i = 0; i < rs->render_groups->count; i++) {
render_group* rg = &rs->render_groups->groups[i];
utilSafeFree(rs->render_groups[i]->entities);
for (uint j = 0; j < rg->count; j++)
entFree(&rg->entities[j]);
}
shaderFree(rs->default_shader->program_id);
@ -84,24 +137,12 @@ renShutdown(render_state* rs)
utilSafeFree(rs->render_groups);
rs->render_groups = nullptr;
arenaFree(rs->arena);
meShutdownAssimp();
SDL_GL_DeleteContext(rs->handles->glContext);
SDL_DestroyWindow(rs->handles->window);
SDL_Quit();
utilSafeFree(rs->handles);
}
render_group*
renAllocateGroup(uint entity_count, shader_wrapper 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;
}
void
renDoRenderLoop(render_state* rs,
uint framerate,
@ -146,13 +187,13 @@ renRenderFrame(render_state* rs)
rs->clear_col.A);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
for (uint i = 0; i < rs->render_group_count; i++) {
render_group* rg = rs->render_groups[i];
for (uint i = 0; i < rs->render_groups->count; i++) {
render_group* rg = &rs->render_groups->groups[i];
for (uint j = 0; j < rg->entity_count; j++) {
entity& e = rg->entities[j];
roDraw(e.render_objs,
e.world_transform,
for (uint j = 0; j < rg->count; j++) {
entity* e = &rg->entities[j];
roDraw(e->render_objs,
e->world_transform,
rs->cam,
rg->shader,
rs->lights);
@ -312,7 +353,6 @@ setDefaults(render_state* rs, glm::vec2 viewport_dims)
{
rs->running = true;
rs->viewport_dims = viewport_dims;
rs->lights = lightsInit();
rs->clear_col.R = CLEAR_COL_R;
rs->clear_col.B = CLEAR_COL_B;
rs->clear_col.G = CLEAR_COL_G;

2
src/util.cpp

@ -62,7 +62,7 @@ utilMatchPrefix(const char* lhs, const char* rhs, int sz)
// Hashing
uint64_t
utilFNV64a_str(char* str, uint64_t hval)
utilFNV64a_str(const char* str, uint64_t hval)
{
unsigned char* s = (unsigned char *)str; // unsigned string

Loading…
Cancel
Save