|
|
|
|
@ -24,22 +24,113 @@
|
|
|
|
|
#define CLEAR_COL_G 55.f / 255.f |
|
|
|
|
#define CLEAR_COL_B 55.f / 255.f |
|
|
|
|
#define CLEAR_COL_A 1.f |
|
|
|
|
#define DEFAULT_WIDTH 1280 |
|
|
|
|
#define DEFAULT_HEIGHT 720 |
|
|
|
|
#define USE_SECOND_MONITOR 0 |
|
|
|
|
|
|
|
|
|
// TODO: add this to json scene properties and render_state
|
|
|
|
|
util_RGBA g_clear_col = {1.f,1.f,1.f,1.f}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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, v2i& viewport_dims); |
|
|
|
|
bool initContext(SDL_Handles& handles); |
|
|
|
|
bool initGL(); |
|
|
|
|
bool initShaders(render_state* rs); |
|
|
|
|
bool initPalette(uint palette_id, util_image& image); |
|
|
|
|
bool initDebugRenderGroup(render_state* rs); |
|
|
|
|
void setDefaults(render_state* rs); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// interface
|
|
|
|
|
|
|
|
|
|
render_state* |
|
|
|
|
renInit() |
|
|
|
|
{ |
|
|
|
|
render_state* rs = UTIL_ALLOC(1, render_state); |
|
|
|
|
setDefaults(rs); |
|
|
|
|
|
|
|
|
|
if (initSDL(rs->handles, rs->viewport_dims) && |
|
|
|
|
initContext(rs->handles) && |
|
|
|
|
initGL() && |
|
|
|
|
initShaders(rs) && |
|
|
|
|
initPalette(rs->palette_id, rs->palette_image) && |
|
|
|
|
initDebugRenderGroup(rs) ) |
|
|
|
|
{ |
|
|
|
|
return rs; |
|
|
|
|
} else { |
|
|
|
|
LOG(Error) << "renderer initialization failed, aborting\n"; |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
renFreeBuffers(render_state* rs) |
|
|
|
|
{ |
|
|
|
|
utilSafeFree(rs->lights); |
|
|
|
|
utilFreeImage(rs->palette_image); |
|
|
|
|
glDeleteTextures(1, &rs->palette_id); |
|
|
|
|
rgFree(rs->filled_hex_render_group); |
|
|
|
|
rgFree(rs->hex_line_render_group); |
|
|
|
|
rgFree(rs->debug_render_group); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
renRenderFrame(render_state* rs, Entity* entities, uint32 entity_count) |
|
|
|
|
{ |
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
//glm::mat4 m_model = rs->cam.model;
|
|
|
|
|
glm::mat4 m_view = rs->cam.view; |
|
|
|
|
glm::mat4 m_projection = rs->cam.projection; |
|
|
|
|
#if 0 |
|
|
|
|
// filled hexes
|
|
|
|
|
|
|
|
|
|
// get new colors every frame
|
|
|
|
|
hgUpdateUVBuffer(hg, rs->filled_hex_render_group); |
|
|
|
|
rgDraw(rs->filled_hex_render_group, m_model, m_view, m_projection, |
|
|
|
|
rs->lights, rs->num_lights); |
|
|
|
|
|
|
|
|
|
// hex lines
|
|
|
|
|
rgDraw(rs->hex_line_render_group, m_model, m_view, m_projection, |
|
|
|
|
rs->lights, rs->num_lights); |
|
|
|
|
#endif |
|
|
|
|
// entities
|
|
|
|
|
for (uint i = 0; i < entity_count; i++) { |
|
|
|
|
rgDraw(entities[i].ren_group, entities[i].world_transform , m_view, m_projection, |
|
|
|
|
rs->lights, rs->num_lights); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#if 0 |
|
|
|
|
void |
|
|
|
|
renRenderDebug(render_state* rs, std::vector<Point> &vertices) |
|
|
|
|
{ |
|
|
|
|
GLfloat* buf = rs->debug_render_group->render_objects[0]->vertex_buffer.buffer; |
|
|
|
|
buf[0] = vertices[0].x; buf[1] = vertices[0].y; buf[2] = 0; |
|
|
|
|
buf[3] = vertices[1].x; buf[4] = vertices[1].y; buf[2] = 0; |
|
|
|
|
buf[6] = vertices[2].x; buf[7] = vertices[2].y; buf[8] = 0; |
|
|
|
|
buf[9] = vertices[3].x; buf[10] = vertices[3].y; buf[11] = 0; |
|
|
|
|
|
|
|
|
|
rgDraw(rs->debug_render_group, rs->cam.model, rs->cam.view, |
|
|
|
|
rs->cam.projection, rs->lights, rs->num_lights, true); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// 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 |
|
|
|
|
renInit(render_state* rs) |
|
|
|
|
initSDL(SDL_Handles& handles, v2i& viewport_dims) |
|
|
|
|
{ |
|
|
|
|
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); |
|
|
|
|
@ -48,29 +139,35 @@ renInit(render_state* rs)
|
|
|
|
|
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, &rs->handles.currentDisplayMode); |
|
|
|
|
SDL_GetCurrentDisplayMode(0, &handles.currentDisplayMode); |
|
|
|
|
|
|
|
|
|
uint display_id = 0; |
|
|
|
|
if (USE_SECOND_MONITOR && SDL_GetNumVideoDisplays() > 1) |
|
|
|
|
display_id = 1; |
|
|
|
|
|
|
|
|
|
rs->handles.window = SDL_CreateWindow( |
|
|
|
|
handles.window = SDL_CreateWindow( |
|
|
|
|
"hexgame", |
|
|
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(display_id), |
|
|
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(display_id), |
|
|
|
|
rs->viewport_dims.x, |
|
|
|
|
rs->viewport_dims.y, |
|
|
|
|
viewport_dims.x, |
|
|
|
|
viewport_dims.y, |
|
|
|
|
SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if (!rs->handles.window) { |
|
|
|
|
if (!handles.window) { |
|
|
|
|
LOG(Error) << "Error creating window: " << SDL_GetError() << "\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rs->handles.glContext = SDL_GL_CreateContext(rs->handles.window); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!rs->handles.glContext) { |
|
|
|
|
bool |
|
|
|
|
initContext(SDL_Handles& handles) |
|
|
|
|
{ |
|
|
|
|
handles.glContext = SDL_GL_CreateContext(handles.window); |
|
|
|
|
|
|
|
|
|
if (!handles.glContext) { |
|
|
|
|
LOG(Error) << "Error creating glContext: " << SDL_GetError() << "\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
@ -80,6 +177,12 @@ renInit(render_state* rs)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initGL() |
|
|
|
|
{ |
|
|
|
|
if (glewInit()) { |
|
|
|
|
LOG(Error) << "failed to initialize OpenGL\n"; |
|
|
|
|
return false; |
|
|
|
|
@ -106,6 +209,12 @@ renInit(render_state* rs)
|
|
|
|
|
// hide VRAM debug messages
|
|
|
|
|
glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
initShaders(render_state* rs) |
|
|
|
|
{ |
|
|
|
|
const char* vs_code = utilDumpTextFile(DEFAULT_VERTEX_SHADER_FILE); |
|
|
|
|
const char* fs_code = utilDumpTextFile(DEFAULT_FRAGMENT_SHADER_FILE); |
|
|
|
|
|
|
|
|
|
@ -119,92 +228,20 @@ renInit(render_state* rs)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rs->max_lights = MAX_LIGHTS; |
|
|
|
|
rs->lights = UTIL_ALLOC(rs->max_lights, rg_point_light); |
|
|
|
|
rs->palette_image = utilLoadImage(DEFAULT_PALETTE_DIR, DEFAULT_PALETTE_FILE); |
|
|
|
|
|
|
|
|
|
if (!rgInitGLTexture(rs->palette_id, rs->palette_image)) { |
|
|
|
|
LOG(Error) << "Error creating texture\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!initDebugRenderGroup(rs)) { |
|
|
|
|
LOG(Error) << "Error initializing debug render group\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
g_clear_col.R = CLEAR_COL_R; |
|
|
|
|
g_clear_col.B = CLEAR_COL_B; |
|
|
|
|
g_clear_col.G = CLEAR_COL_G; |
|
|
|
|
g_clear_col.A = CLEAR_COL_A; |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
renFreeBuffers(render_state* rs) |
|
|
|
|
{ |
|
|
|
|
utilSafeFree(rs->lights); |
|
|
|
|
utilFreeImage(rs->palette_image); |
|
|
|
|
glDeleteTextures(1, &rs->palette_id); |
|
|
|
|
rgFree(rs->filled_hex_render_group); |
|
|
|
|
rgFree(rs->hex_line_render_group); |
|
|
|
|
rgFree(rs->debug_render_group); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
renRenderFrame(render_state* rs, Entity* entities, uint32 entity_count) |
|
|
|
|
bool |
|
|
|
|
initPalette(uint palette_id, util_image& image) |
|
|
|
|
{ |
|
|
|
|
glClearColor(g_clear_col.R, g_clear_col.G, g_clear_col.B, g_clear_col.A); |
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
|
|
|
|
image = utilLoadImage(DEFAULT_PALETTE_DIR, DEFAULT_PALETTE_FILE); |
|
|
|
|
|
|
|
|
|
//glm::mat4 m_model = rs->cam.model;
|
|
|
|
|
glm::mat4 m_view = rs->cam.view; |
|
|
|
|
glm::mat4 m_projection = rs->cam.projection; |
|
|
|
|
#if 0 |
|
|
|
|
// filled hexes
|
|
|
|
|
|
|
|
|
|
// get new colors every frame
|
|
|
|
|
hgUpdateUVBuffer(hg, rs->filled_hex_render_group); |
|
|
|
|
rgDraw(rs->filled_hex_render_group, m_model, m_view, m_projection, |
|
|
|
|
rs->lights, rs->num_lights); |
|
|
|
|
|
|
|
|
|
// hex lines
|
|
|
|
|
rgDraw(rs->hex_line_render_group, m_model, m_view, m_projection, |
|
|
|
|
rs->lights, rs->num_lights); |
|
|
|
|
#endif |
|
|
|
|
// entities
|
|
|
|
|
for (uint i = 0; i < entity_count; i++) { |
|
|
|
|
rgDraw(entities[i].ren_group, entities[i].world_transform , m_view, m_projection, |
|
|
|
|
rs->lights, rs->num_lights); |
|
|
|
|
if (!rgInitGLTexture(palette_id, image)) { |
|
|
|
|
LOG(Error) << "Error creating texture\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#if 0 |
|
|
|
|
void |
|
|
|
|
renRenderDebug(render_state* rs, std::vector<Point> &vertices) |
|
|
|
|
{ |
|
|
|
|
GLfloat* buf = rs->debug_render_group->render_objects[0]->vertex_buffer.buffer; |
|
|
|
|
buf[0] = vertices[0].x; buf[1] = vertices[0].y; buf[2] = 0; |
|
|
|
|
buf[3] = vertices[1].x; buf[4] = vertices[1].y; buf[2] = 0; |
|
|
|
|
buf[6] = vertices[2].x; buf[7] = vertices[2].y; buf[8] = 0; |
|
|
|
|
buf[9] = vertices[3].x; buf[10] = vertices[3].y; buf[11] = 0; |
|
|
|
|
|
|
|
|
|
rgDraw(rs->debug_render_group, rs->cam.model, rs->cam.view, |
|
|
|
|
rs->cam.projection, rs->lights, rs->num_lights, true); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// 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"; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
@ -213,8 +250,10 @@ initDebugRenderGroup(render_state* rs)
|
|
|
|
|
uint debug_buf_len = 12; // 4 vertices, 3 floats per vertex
|
|
|
|
|
rs->debug_render_group = rgInitSingle(rs->default_shader, debug_buf_len, true, 0, GL_LINE_LOOP); |
|
|
|
|
|
|
|
|
|
if (rs->debug_render_group == nullptr) |
|
|
|
|
if (rs->debug_render_group == nullptr) { |
|
|
|
|
LOG(Error) << "Error initializing debug render group\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gl_buffer& debug_vertex_buf = rs->debug_render_group->render_objects[0]->vertex_buffer; |
|
|
|
|
gl_buffer& debug_normal_buf = rs->debug_render_group->render_objects[0]->normal_buffer; |
|
|
|
|
@ -230,3 +269,16 @@ initDebugRenderGroup(render_state* rs)
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
setDefaults(render_state* rs) |
|
|
|
|
{ |
|
|
|
|
rs->viewport_dims = v2i(DEFAULT_WIDTH, DEFAULT_HEIGHT); |
|
|
|
|
rs->palette_id = UINT_MAX; |
|
|
|
|
rs->max_lights = MAX_LIGHTS; |
|
|
|
|
rs->lights = UTIL_ALLOC(rs->max_lights, rg_point_light); |
|
|
|
|
rs->clear_col.R = CLEAR_COL_R; |
|
|
|
|
rs->clear_col.B = CLEAR_COL_B; |
|
|
|
|
rs->clear_col.G = CLEAR_COL_G; |
|
|
|
|
rs->clear_col.A = CLEAR_COL_A; |
|
|
|
|
} |
|
|
|
|
|