|
|
|
|
@ -25,14 +25,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// forward declarations
|
|
|
|
|
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
|
GLsizei length, const GLchar* message, const void* userParam); |
|
|
|
|
bool initSDL(SDL_Handles& handles); |
|
|
|
|
bool createWindow(const char* title, |
|
|
|
|
SDL_Handles& handles, |
|
|
|
|
glm::vec2& viewport_dims); |
|
|
|
|
bool initContext(SDL_Handles& handles); |
|
|
|
|
bool initGlOptions(); |
|
|
|
|
bool initSDL(SDL_Handles& handles); |
|
|
|
|
bool initShaders(render_state* rs); |
|
|
|
|
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
|
GLsizei length, const GLchar* message, const void* userParam); |
|
|
|
|
void setDefaults(render_state* rs, glm::vec2 viewport_dims); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -48,17 +49,10 @@ renInit(const char* title, glm::vec2 viewport_dims)
|
|
|
|
|
createWindow(title, rs->handles, rs->viewport_dims) && |
|
|
|
|
initContext(rs->handles) && |
|
|
|
|
initGlOptions() && |
|
|
|
|
initShaders(rs) && |
|
|
|
|
meInitAssimp()) |
|
|
|
|
{ |
|
|
|
|
rs->default_shader = |
|
|
|
|
shaderInit(DEFAULT_VERTEX_SHADER, DEFAULT_FRAGMENT_SHADER); |
|
|
|
|
|
|
|
|
|
if (rs->default_shader != nullptr) { |
|
|
|
|
return rs; |
|
|
|
|
} else { |
|
|
|
|
LOG(Error) << "shader loading failed\n"; |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
return rs; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LOG(Error) << "renderer initialization failed, aborting\n"; |
|
|
|
|
@ -68,23 +62,15 @@ 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(e.render_objs); |
|
|
|
|
} |
|
|
|
|
for (uint j = 0; j < rs->render_groups[i].entity_count; j++) |
|
|
|
|
entFree(rs->render_groups[i].entities[j]); |
|
|
|
|
|
|
|
|
|
utilSafeFree(rg.entities); |
|
|
|
|
utilSafeFree(rs->render_groups[i].entities); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
shaderFree(rs->default_shader); |
|
|
|
|
shaderFree(rs->default_shader->program_id); |
|
|
|
|
shaderFree(rs->simple_shader->program_id); |
|
|
|
|
lightsOut(rs->lights); |
|
|
|
|
utilSafeFree(rs->render_groups); |
|
|
|
|
utilSafeFree(rs->default_shader); |
|
|
|
|
@ -95,7 +81,7 @@ renShutdown(render_state* rs)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
render_group* |
|
|
|
|
renAllocateGroup(uint entity_count, shader_program shader) |
|
|
|
|
renAllocateGroup(uint entity_count, shader_wrapper shader) |
|
|
|
|
{ |
|
|
|
|
assert(entity_count > 0); |
|
|
|
|
render_group* rg = UTIL_ALLOC(1, render_group); |
|
|
|
|
@ -137,20 +123,34 @@ renDoRenderLoop(render_state* rs, uint framerate, frame_callback_fn cb_func)
|
|
|
|
|
void |
|
|
|
|
renRenderFrame(render_state* rs) |
|
|
|
|
{ |
|
|
|
|
glClearColor(rs->clear_col.R, rs->clear_col.G, rs->clear_col.B, rs->clear_col.A); |
|
|
|
|
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: need a nicer way to loop over entities and render_objects
|
|
|
|
|
// eg) entDraw()
|
|
|
|
|
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], |
|
|
|
|
if (rg.shader.type == SIMPLE_SHADER) { |
|
|
|
|
roDrawSimple(e.simple_ro, |
|
|
|
|
rs->cam, |
|
|
|
|
rg.shader, |
|
|
|
|
rs->lights); |
|
|
|
|
*rg.shader.simple_shader, |
|
|
|
|
e.draw_mode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (rg.shader.type == DEFAULT_SHADER) { |
|
|
|
|
for (uint k = 0; k < e.ro_count; k++) { |
|
|
|
|
roDraw(e.render_objs[k], |
|
|
|
|
rs->cam, |
|
|
|
|
*rg.shader.default_shader, |
|
|
|
|
rs->lights); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -170,37 +170,6 @@ renAddLight(render_state* rs, glm::vec3 pos, glm::vec3 color, float intensity)
|
|
|
|
|
|
|
|
|
|
// internal
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
|
GLsizei length, const GLchar* message, const void* userParam) |
|
|
|
|
{ |
|
|
|
|
LOG((type == GL_DEBUG_TYPE_ERROR) ? Error : Debug) |
|
|
|
|
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "") |
|
|
|
|
<< ", type: " << type |
|
|
|
|
<< ", severity: " << severity |
|
|
|
|
<< ", message: " << message << "\n"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initSDL(SDL_Handles& handles) |
|
|
|
|
{ |
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO) != 0) { |
|
|
|
|
LOG(Error) << "Error, SDL_Init: " << SDL_GetError() << "\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); |
|
|
|
|
SDL_GetCurrentDisplayMode(0, &handles.currentDisplayMode); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
createWindow(const char* title, SDL_Handles& handles, glm::vec2& viewport_dims) |
|
|
|
|
{ |
|
|
|
|
@ -275,6 +244,55 @@ initGlOptions()
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initSDL(SDL_Handles& handles) |
|
|
|
|
{ |
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO) != 0) { |
|
|
|
|
LOG(Error) << "Error, SDL_Init: " << SDL_GetError() << "\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); |
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); |
|
|
|
|
SDL_GetCurrentDisplayMode(0, &handles.currentDisplayMode); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initShaders(render_state* rs) |
|
|
|
|
{ |
|
|
|
|
rs->default_shader = |
|
|
|
|
shaderInitDefault(DEFAULT_VERTEX_SHADER, DEFAULT_FRAGMENT_SHADER); |
|
|
|
|
rs->simple_shader = |
|
|
|
|
shaderInitSimple(SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER); |
|
|
|
|
|
|
|
|
|
if (rs->default_shader == nullptr || |
|
|
|
|
rs->simple_shader == nullptr) |
|
|
|
|
{ |
|
|
|
|
LOG(Error) << "shader loading failed\n"; |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
|
GLsizei length, const GLchar* message, const void* userParam) |
|
|
|
|
{ |
|
|
|
|
LOG((type == GL_DEBUG_TYPE_ERROR) ? Error : Debug) |
|
|
|
|
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL Error **" : "") |
|
|
|
|
<< ", type: " << type |
|
|
|
|
<< ", severity: " << severity |
|
|
|
|
<< ", message: " << message << "\n"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
setDefaults(render_state* rs, glm::vec2 viewport_dims) |
|
|
|
|
{ |
|
|
|
|
|