Browse Source

completed entity changes to renderer/render_group

can now use rgInitSingle() to initializa a render_group with only one
group of buffers (render_object)
master
cinnaboot 8 years ago
parent
commit
49c562f6ed
  1. 88
      src/render_group.cpp
  2. 8
      src/render_group.h
  3. 590
      src/renderer.cpp
  4. 3
      src/util.cpp

88
src/render_group.cpp

@ -20,7 +20,6 @@
render_object * allocateRenderObject(uint buffer_len, uint index_len = 0);
void freeRenderObject(render_object* ro);
bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals);
void sendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target);
void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target);
void drawRenderObject(render_group* rg, render_object* ro,
glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix,
@ -29,6 +28,29 @@ void drawRenderObject(render_group* rg, render_object* ro,
// interface
render_group*
rgInitSingle(rg_shader_program& sp, uint vertex_buffer_len,
bool use_normals, uint index_buffer_len,
GLenum draw_mode)
{
render_group* rg = UTIL_ALLOC(1, render_group);
rg->shader = sp;
rg->use_normals = use_normals;
rg->draw_indexed = (index_buffer_len > 0);
rg->draw_mode = draw_mode;
rg->render_objects = UTIL_ALLOC(1, render_object*);
rg->render_objects[0] = allocateRenderObject(vertex_buffer_len, index_buffer_len);
rg->num_objects = 1;
if (rg->render_objects[0] == nullptr) {
LOG(ERROR) << "Allocation Error\n";
rgFree(rg);
}
return rg;
}
bool
rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char * frag_code)
{
@ -59,7 +81,6 @@ rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char
// TODO: quick hack to allow 'dynamic' stack allocation for msvc
// also remove INFO_LOG_MAX_LENGTH define
#if 1
GLint isLinked = 0;
glGetProgramiv(sp.program_id, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
@ -76,42 +97,19 @@ rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char
return false;
}
#endif
return true;
}
// TODO: should pass in a buffer of colors here instead of hexes, move to renderer.cpp
// we don't need to know about hexes here
#if 0
void
rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
{
int buf_idx;
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
GLfloat color_buf[3];
for (int i = 0; i < (int) hexes->size(); i++)
{
buf_idx = i * buf_len_per_hex;
hex_info hxi = (*hexes)[i];
utilConvertColor(color_buf, hxi.current_color);
for (int j = 0; j < buf_len_per_hex; j+=3)
{
buf[buf_idx + j] = color_buf[0];
buf[buf_idx + j + 1] = color_buf[1];
buf[buf_idx + j + 2] = color_buf[2];
}
}
}
#endif
// TODO: move Entity initialization to Entity.h/.cpp to fix circular dependancy
// then just call into convertMeshInfo directly
bool
rgInitEntity(Entity* e)
{
render_group* rg = UTIL_ALLOC(1, render_group);
e->ren_group = rg;
rg->draw_indexed = true;
rg->draw_mode = GL_TRIANGLES;
rg->use_normals = e->mesh_group.use_normals;
uint num_meshes = rg->num_objects = e->mesh_group.num_meshes;
@ -139,13 +137,21 @@ rgInitEntity(Entity* e)
return true;
}
void
rgBufferData(gl_buffer* buffer, GLenum usage, GLenum target)
{
glGenBuffers(1, &buffer->buffer_id);
glBindBuffer(target, buffer->buffer_id);
glBufferData(target, buffer->buffer_len * sizeof(GLfloat), buffer->buffer, usage);
}
void
rgDraw(render_group* rg, glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix,
glm::vec3 light_position, GLuint light_id, bool update_vertex_data)
{
for (uint i = 0; i < rg->num_objects; i++) {
drawRenderObject(rg, rg->render_objects[i], model_matrix, view_matrix, projection_matrix,
light_position, light_id, false);
light_position, light_id, update_vertex_data);
}
}
@ -160,6 +166,7 @@ rgFree(render_group* rg)
for (uint i = 0; i < rg->num_objects; i++)
freeRenderObject(rg->render_objects[i]);
utilSafeFree(rg->render_objects);
utilSafeFree(rg);
}
@ -208,14 +215,6 @@ freeRenderObject(render_object* ro)
utilSafeFree(ro);
}
void
sendBufferToGL(gl_buffer* buffer, GLenum usage, GLenum target)
{
glGenBuffers(1, &buffer->buffer_id);
glBindBuffer(target, buffer->buffer_id);
glBufferData(target, buffer->buffer_len * sizeof(GLfloat), buffer->buffer, usage);
}
void
sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target)
{
@ -271,10 +270,10 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals)
for (uint i = 0; i < mesh->num_indices; i++)
index_buf[i] = mesh->indices[i];
sendBufferToGL(&ro->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
sendBufferToGL(&ro->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
rgBufferData(&ro->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
rgBufferData(&ro->color_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
if (use_normals)
sendBufferToGL(&ro->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
rgBufferData(&ro->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
sendIndexBufferToGL(&ro->index_buffer, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER);
return true;
@ -314,7 +313,6 @@ drawRenderObject(render_group* rg, render_object* ro,
}
// 3rd attribute buffer: normals
#if 1
if (rg->use_normals) {
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, ro->normal_buffer.buffer_id);
@ -325,17 +323,13 @@ drawRenderObject(render_group* rg, render_object* ro,
glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix)));
glUniformMatrix3fv(rg->shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]);
}
#endif
// draw
if (rg->draw_indexed) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro->index_buffer.buffer_id);
// TODO: find out why rg->draw_mode isn't being preserved as GL_TRIANGLES
//glDrawElements(rg->draw_mode, ro->index_buffer.buffer_len, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, ro->index_buffer.buffer_len, GL_UNSIGNED_INT, 0);
glDrawElements(rg->draw_mode, ro->index_buffer.buffer_len, GL_UNSIGNED_INT, 0);
} else {
//glDrawArrays(rg->draw_mode, 0, ro->vertex_buffer.buffer_len / 3);
glDrawArrays(GL_TRIANGLES, 0, ro->vertex_buffer.buffer_len / 3);
glDrawArrays(rg->draw_mode, 0, ro->vertex_buffer.buffer_len / 3);
}
// cleanup

8
src/render_group.h

@ -53,10 +53,18 @@ struct render_group
GLenum draw_mode = GL_TRIANGLES;
};
// NOTE: initializes a render_group with 1 render_object allocated
render_group* rgInitSingle(rg_shader_program& sp, uint vertex_buffer_len,
bool use_normals = false, uint index_buffer_len = 0,
GLenum draw_mode = GL_TRIANGLES);
bool rgInitShaderProgram(rg_shader_program& sp, const char * vertex_code, const char * frag_code);
bool rgInitEntity(Entity* e);
void
rgBufferData(gl_buffer* buffer, GLenum usage, GLenum target);
// TODO: fix this function to use just buffers instead of hexes
//void rgFillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes);

590
src/renderer.cpp

@ -83,11 +83,23 @@ struct camera
};
// forward declarations
void initMatrices(projection_type p);
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam);
bool initHexGridBuffers(std::vector<hex_info>* hexes);
void fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex);
void fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes);
void fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes);
// globals
static gl_matrix_info g_scene_matrices;
static render_group* g_filled_hex_render_group;
static render_group* g_hex_line_render_group;
static render_group* g_debug_render_group;
static rg_shader_program g_default_shader;
static rg_shader_program g_line_shader;
// NOTE: entity render_group pointers are kept in the entity struct
static camera g_camera;
@ -95,125 +107,7 @@ static camera g_camera;
static renPointLight g_test_light;
bool
addTexture(SDL_Handles &handles, const char * path)
{
// testing
LOG(INFO) << "Loading image: " << path << "\n";
SDL_Surface* image = IMG_Load(path);
if (!image)
{
LOG(ERROR) << "IMG_Load: " << IMG_GetError() << "\n";
return false;
}
GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, 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);
// store opengl id in SDL_Surface.userdat
image->userdata = (void*)(intptr_t) tex_id;
handles.texSurfaces.push_back(image);
return true;
}
v2f
getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height)
{
// NOTE: using depth buffer may not be as accurate as doing ray-cast
GLfloat depth;
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
glm::vec4 viewport = glm::vec4(0, 0, vp_width, vp_height);
glm::vec3 wincoord = glm::vec3(x, y, depth);
glm::vec3 vU = glm::unProject(wincoord, g_scene_matrices.view, g_scene_matrices.projection, viewport);
v2f v(vU.x, vU.y);
return v;
}
v3f
getCameraPosition()
{
return v3f(g_camera.position.x, g_camera.position.y, g_camera.position.z);
}
void
initMatrices(projection_type p)
{
// TODO: many constants used here should be passed as args
if (p == PERSPECTIVE)
{
g_scene_matrices.projection = glm::infinitePerspective(
glm::radians(60.f), // FoV
16.f / 9.f, // ascpect ratio
0.1f // near clip plane
);
g_camera.position = glm::vec3(640,0,100);
g_camera.target = glm::vec3(640,500,0);
//g_camera.target = glm::vec3(0,0,0);
// inital rotation should match target direction
glm::vec3 &p = g_camera.position;
glm::vec3 &t = g_camera.target;
g_camera.hAngle = 0;
g_camera.vAngle = glm::atan((t.z - p.z) / (t.y - p.y));
//////
// TODO: add call to rotate camera here to remove duplicate code
camera &c = g_camera;
float &h = c.hAngle;
float &v = c.vAngle;
c.forward = glm::vec3(
glm::cos(v) * glm::sin(h),
glm::cos(v) * glm::cos(h),
glm::sin(v)
);
glm::normalize(c.forward);
//////
g_camera.up = glm::vec3(0,1,0);
g_camera.left = glm::normalize(glm::cross(g_camera.up, g_camera.forward));
g_camera.up = glm::normalize(glm::cross(g_camera.forward, g_camera.left));
g_scene_matrices.view = glm::lookAt(
g_camera.position, // camera position
g_camera.position + g_camera.forward,
g_camera.up // "up" vector
);
}
else // ORTHO
{
// left, right, bottom, top, zNear, zFar
g_scene_matrices.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f);
g_scene_matrices.view = glm::lookAt(
glm::vec3(0.0f, 0.0f, 1.0f), // camera position
glm::vec3(0.0f, 0.0f, 0.0f), // look at position
glm::vec3(0,1,0) // "up" vector
);
}
g_scene_matrices.model = glm::mat4(1.0f);
g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model;
}
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";
}
// interface
bool
initRenderer(SDL_Handles &handles, v2i vpDims)
@ -258,15 +152,10 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
glEnable(GL_DEPTH_TEST);
glEnable(GL_LINE_SMOOTH);
// TODO: blending, these options break the http://www.opengl-tutorial.org tutorials atm
// Setup render state: alpha-blending enabled, polygon fill
#if 1
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// TODO: glDebugMessageCallback is only availabe from >v4.3
// check and warn if context doesn't support this function here
@ -275,16 +164,10 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
// hide VRAM debug messages
glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE);
g_filled_hex_render_group = UTIL_ALLOC(1, render_group);
g_hex_line_render_group = UTIL_ALLOC(1, render_group);
g_debug_render_group = UTIL_ALLOC(1, render_group);
#if 0
const char* vs_code = utilDumpTextFile(DEFAULT_VERTEX_SHADER_FILE);
const char* fs_code = utilDumpTextFile(DEFAULT_FRAGMENT_SHADER_FILE);
bool shader_error = (!rgInitShaderProgram(&g_filled_hex_render_group, vs_code, fs_code)
|| !rgInitShaderProgram(&g_hex_line_render_group, vs_code, LINE_FRAGMENT_SHADER_CODE)
|| !rgInitShaderProgram(&g_debug_render_group, vs_code, DEBUG_FRAGMENT_SHADER_CODE));
bool shader_error = !rgInitShaderProgram(g_default_shader, vs_code, fs_code);
utilSafeFree(vs_code);
utilSafeFree(fs_code);
@ -292,167 +175,102 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
if (shader_error) {
LOG(ERROR) << "Error initializing shader program\n";
return false;
} else {
return true;
}
#else
return true;
#endif
}
void
fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex)
bool
addTexture(SDL_Handles &handles, const char * path)
{
// triangles
for (int i = 0; i < 6; i++)
// testing
LOG(INFO) << "Loading image: " << path << "\n";
SDL_Surface* image = IMG_Load(path);
if (!image)
{
// vertex 0
buf[idx + 0] = (GLfloat) hex.XPos;
buf[idx + 1] = (GLfloat) hex.YPos;
buf[idx + 2] = (GLfloat) 0.f;
LOG(ERROR) << "IMG_Load: " << IMG_GetError() << "\n";
return false;
}
// vertex 1
buf[idx + 3] = (GLfloat) hex.vertices[i].x;
buf[idx + 4] = (GLfloat) hex.vertices[i].y;
buf[idx + 5] = (GLfloat) 0.f;
GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, 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);
if (i == 5) // re-use the first point for the last triangle
{
// vertex 2
buf[idx + 6] = (GLfloat) hex.vertices[0].x;
buf[idx + 7] = (GLfloat) hex.vertices[0].y;
buf[idx + 8] = (GLfloat) 0.f;
}
else
{
// vertex 2
buf[idx + 6] = (GLfloat) hex.vertices[i + 1].x;
buf[idx + 7] = (GLfloat) hex.vertices[i + 1].y;
buf[idx + 8] = (GLfloat) 0.f;
}
// store opengl id in SDL_Surface.userdat
image->userdata = (void*)(intptr_t) tex_id;
handles.texSurfaces.push_back(image);
// we've added 9 GLfloats per loop
idx += 9;
}
return true;
}
void
fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
v2f
getUnprojectedCoords(int32 x, int32 y, int32 vp_width, int32 vp_height)
{
Point p1, p2;
int idx = 0;
for (int i = 0; i < (int) hexes->size(); i++)
{
hex_info hxi = (*hexes)[i];
for (int j = 0; j < 6; j ++)
{
if (j == 5) // wrap
{
p1 = hxi.vertices[j];
p2 = hxi.vertices[0];
}
else
{
p1 = hxi.vertices[j];
p2 = hxi.vertices[j + 1];
}
// NOTE: using depth buffer may not be as accurate as doing ray-cast
GLfloat depth;
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
glm::vec4 viewport = glm::vec4(0, 0, vp_width, vp_height);
glm::vec3 wincoord = glm::vec3(x, y, depth);
glm::vec3 vU = glm::unProject(wincoord, g_scene_matrices.view, g_scene_matrices.projection, viewport);
v2f v(vU.x, vU.y);
buf[idx + 0] = p1.x;
buf[idx + 1] = p1.y;
buf[idx + 2] = 0.f;
buf[idx + 3] = p2.x;
buf[idx + 4] = p2.y;
buf[idx + 5] = 0.f;
idx += 6;
}
}
return v;
}
bool
initHexGridBuffers(std::vector<hex_info>* hexes)
v3f
getCameraPosition()
{
#if 0
// TODO: index duplicate vertices
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
uint vbuf_len = hexes->size() * 6 * 3 * 3;
uint line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
uint line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
gl_buffer& vbuf = * rgInitGLBuffer(&g_filled_hex_render_group.vertex_buffer, vbuf_len);
gl_buffer& cbuf = * rgInitGLBuffer(&g_filled_hex_render_group.color_buffer, vbuf_len);
gl_buffer& normal_buf = * rgInitGLBuffer(&g_filled_hex_render_group.normal_buffer, vbuf_len);
gl_buffer& line_buf = * rgInitGLBuffer(&g_hex_line_render_group.vertex_buffer, line_buf_len);
if (!vbuf.buffer || !cbuf.buffer || !line_buf.buffer || !normal_buf.buffer)
return false;
for (uint i = 0; i < hexes->size(); i++)
fillTriangleBufferFromHex(vbuf.buffer, 54 * i, (*hexes)[i]);
rgSendBufferToGL(&vbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
// color data for hex vertices
rgFillColorBuffer(cbuf.buffer, vbuf_len, hexes);
rgSendBufferToGL(&cbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
// cheat at vertex normals since all hexes lay flat on z-axis
for (uint i = 0; i < vbuf_len; i += 3) {
normal_buf.buffer[i] = 0;
normal_buf.buffer[i + 1] = 0;
normal_buf.buffer[i + 2] = 1;
}
rgSendBufferToGL(&normal_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
g_filled_hex_render_group->use_normals = true;
// hex line vertex data
fillHexLineBuffer(line_buf.buffer, line_buf_len, hexes);
g_hex_line_render_group->vertex_buffer.buffer_len = line_buf_len;
rgSendBufferToGL(&line_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
// TODO: add a color buffer to hex_line and debug render groups to re-use
// fragment shaders and simplify draw rgDraw()
#endif
return true;
return v3f(g_camera.position.x, g_camera.position.y, g_camera.position.z);
}
bool
createScene(std::vector<hex_info>* hexes, Entity* entities, uint32 entity_count)
{
// entities
for (uint i = 0; i < entity_count; i++) {
rgInitEntity(&entities[i]);
entities[i].ren_group->shader = g_default_shader;
}
initMatrices(PROJ_TYPE);
if (!initHexGridBuffers(hexes))
return false;
// debug draw vertices
#if 0
rgInitGLBuffer(&g_debug_render_group->vertex_buffer, 4 * 3); // 4 vertices * 3 floats per vertex
if (!g_debug_render_group->vertex_buffer.buffer)
return false;
rgSendBufferToGL(&g_debug_render_group->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
#endif
// entities
uint debug_buf_len = 12; // 4 vertices, 3 floats per vertex
g_debug_render_group = rgInitSingle(g_default_shader, debug_buf_len, true, 0, GL_LINE_LOOP);
const char* vs_code = utilDumpTextFile(DEFAULT_VERTEX_SHADER_FILE);
const char* fs_code = utilDumpTextFile(DEFAULT_FRAGMENT_SHADER_FILE);
rg_shader_program sp;
if (g_debug_render_group == nullptr)
return false;
bool shader_errors = !rgInitShaderProgram(sp, vs_code, fs_code);
utilSafeFree(vs_code);
utilSafeFree(fs_code);
gl_buffer& debug_vertex_buf = g_debug_render_group->render_objects[0]->vertex_buffer;
gl_buffer& debug_color_buf = g_debug_render_group->render_objects[0]->color_buffer;
gl_buffer& debug_normal_buf = g_debug_render_group->render_objects[0]->normal_buffer;
if (shader_errors)
return false;
for (uint i = 0; i < debug_buf_len; i += 3) {
debug_color_buf.buffer[i] = 1.f;
debug_color_buf.buffer[i + 1] = 0.f;
debug_color_buf.buffer[i + 2] = 0.f;
for (uint i = 0; i < entity_count; i++) {
rgInitEntity(&entities[i]);
entities[i].ren_group->shader = sp;
debug_normal_buf.buffer[i] = 0.f;
debug_normal_buf.buffer[i + 1] = 0.f;
debug_normal_buf.buffer[i + 2] = 1.f;
}
rgBufferData(&debug_vertex_buf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
rgBufferData(&debug_color_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
rgBufferData(&debug_normal_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
// lights
// TODO: load light properties from scene/level files
//g_test_light.light_ID = glGetUniformLocation(g_entity_render_group.program_id, "light_position");
@ -558,49 +376,41 @@ renderFrame(std::vector<hex_info> *hexes, Entity* entities, uint32 entity_count)
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);
//glm::mat4 m_model = g_scene_matrices.model;
glm::mat4 m_model = g_scene_matrices.model;
glm::mat4 m_view = g_scene_matrices.view;
glm::mat4 m_projection = g_scene_matrices.projection;
// filled hexes
#if 0
// get new colors every frame
gl_render_group* rg = g_filled_hex_render_group;
rgFillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes);
rgDraw(rg, GL_TRIANGLES, m_model, m_view, m_projection,
render_group* rg = g_filled_hex_render_group;
gl_buffer& color_buf = rg->render_objects[0]->color_buffer;
fillColorBuffer(color_buf.buffer, color_buf.buffer_len, hexes);
rgDraw(rg, m_model, m_view, m_projection,
g_test_light.position, g_test_light.light_ID);
// hex lines
rgDraw(g_hex_line_render_group, GL_LINES, m_model, m_view, m_projection,
g_test_light.position, g_test_light.light_ID);
#endif
rgDraw(g_hex_line_render_group, m_model, m_view, m_projection,
g_test_light.position, g_test_light.light_ID);
// entities
for (uint i = 0; i < entity_count; i++) {
rgDraw(
entities[i].ren_group, entities[i].world_transform , m_view, m_projection,
g_test_light.position, g_test_light.light_ID
);
rgDraw(entities[i].ren_group, entities[i].world_transform , m_view, m_projection,
g_test_light.position, g_test_light.light_ID);
}
}
void
renderDebug(std::vector<Point> &vertices)
{
#if 0
// TODO: indexed line drawing
// copy vertices to render group
GLfloat* buf = g_debug_render_group->vertex_buffer.buffer;
GLfloat* buf = g_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(g_debug_render_group, GL_LINE_LOOP, g_scene_matrices.model, g_scene_matrices.view,
rgDraw(g_debug_render_group, g_scene_matrices.model, g_scene_matrices.view,
g_scene_matrices.projection, g_test_light.position, g_test_light.light_ID, true);
#endif
}
void
@ -616,3 +426,231 @@ freeBuffers()
rgFree(group);
}
// internal
void
initMatrices(projection_type p)
{
// TODO: many constants used here should be passed as args
if (p == PERSPECTIVE)
{
g_scene_matrices.projection = glm::infinitePerspective(
glm::radians(60.f), // FoV
16.f / 9.f, // ascpect ratio
0.1f // near clip plane
);
g_camera.position = glm::vec3(640,0,100);
g_camera.target = glm::vec3(640,500,0);
//g_camera.target = glm::vec3(0,0,0);
// inital rotation should match target direction
glm::vec3 &p = g_camera.position;
glm::vec3 &t = g_camera.target;
g_camera.hAngle = 0;
g_camera.vAngle = glm::atan((t.z - p.z) / (t.y - p.y));
//////
// TODO: add call to rotate camera here to remove duplicate code
camera &c = g_camera;
float &h = c.hAngle;
float &v = c.vAngle;
c.forward = glm::vec3(
glm::cos(v) * glm::sin(h),
glm::cos(v) * glm::cos(h),
glm::sin(v)
);
glm::normalize(c.forward);
//////
g_camera.up = glm::vec3(0,1,0);
g_camera.left = glm::normalize(glm::cross(g_camera.up, g_camera.forward));
g_camera.up = glm::normalize(glm::cross(g_camera.forward, g_camera.left));
g_scene_matrices.view = glm::lookAt(
g_camera.position, // camera position
g_camera.position + g_camera.forward,
g_camera.up // "up" vector
);
}
else // ORTHO
{
// left, right, bottom, top, zNear, zFar
g_scene_matrices.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f);
g_scene_matrices.view = glm::lookAt(
glm::vec3(0.0f, 0.0f, 1.0f), // camera position
glm::vec3(0.0f, 0.0f, 0.0f), // look at position
glm::vec3(0,1,0) // "up" vector
);
}
g_scene_matrices.model = glm::mat4(1.0f);
g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model;
}
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
initHexGridBuffers(std::vector<hex_info>* hexes)
{
// TODO: index duplicate vertices
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
uint line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
uint line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
uint vbuf_len = hexes->size() * 6 * 3 * 3;
g_filled_hex_render_group = rgInitSingle(g_default_shader, vbuf_len, true);
if (g_filled_hex_render_group == nullptr)
return false;
gl_buffer& vbuf = g_filled_hex_render_group->render_objects[0]->vertex_buffer;
gl_buffer& cbuf = g_filled_hex_render_group->render_objects[0]->color_buffer;
gl_buffer& normal_buf = g_filled_hex_render_group->render_objects[0]->normal_buffer;
for (uint i = 0; i < hexes->size(); i++)
fillTriangleBufferFromHex(vbuf.buffer, i * 54, (*hexes)[i]);
rgBufferData(&vbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
fillColorBuffer(cbuf.buffer, vbuf_len, hexes);
rgBufferData(&cbuf, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER);
// cheat at vertex normals since all hexes lay flat on z-axis
for (uint i = 0; i < vbuf_len; i += 3) {
normal_buf.buffer[i] = 0.f;
normal_buf.buffer[i + 1] = 0.f;
normal_buf.buffer[i + 2] = 1.f;
}
rgBufferData(&normal_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
// hex lines
g_hex_line_render_group = rgInitSingle(g_default_shader, line_buf_len, true, 0, GL_LINES);
if (g_hex_line_render_group == nullptr)
return false;
gl_buffer& line_buf = g_hex_line_render_group->render_objects[0]->vertex_buffer;
gl_buffer& line_color_buf = g_hex_line_render_group->render_objects[0]->color_buffer;
gl_buffer& line_normal_buf = g_hex_line_render_group->render_objects[0]->normal_buffer;
fillHexLineBuffer(line_buf.buffer, line_buf_len, hexes);
rgBufferData(&line_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
for (uint i = 0; i < line_buf_len; i++)
line_color_buf.buffer[i] = 0.f;
rgBufferData(&line_color_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
for (uint i = 0; i < line_buf_len; i += 3) {
line_normal_buf.buffer[i] = 0.f;
line_normal_buf.buffer[i + 1] = 0.f;
line_normal_buf.buffer[i + 2] = 1.f;
}
rgBufferData(&line_normal_buf, GL_STATIC_DRAW, GL_ARRAY_BUFFER);
return true;
}
void
fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex)
{
// triangles
for (int i = 0; i < 6; i++)
{
// vertex 0
buf[idx + 0] = (GLfloat) hex.XPos;
buf[idx + 1] = (GLfloat) hex.YPos;
buf[idx + 2] = (GLfloat) 0.f;
// vertex 1
buf[idx + 3] = (GLfloat) hex.vertices[i].x;
buf[idx + 4] = (GLfloat) hex.vertices[i].y;
buf[idx + 5] = (GLfloat) 0.f;
if (i == 5) // re-use the first point for the last triangle
{
// vertex 2
buf[idx + 6] = (GLfloat) hex.vertices[0].x;
buf[idx + 7] = (GLfloat) hex.vertices[0].y;
buf[idx + 8] = (GLfloat) 0.f;
}
else
{
// vertex 2
buf[idx + 6] = (GLfloat) hex.vertices[i + 1].x;
buf[idx + 7] = (GLfloat) hex.vertices[i + 1].y;
buf[idx + 8] = (GLfloat) 0.f;
}
// we've added 9 GLfloats per loop
idx += 9;
}
}
void
fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
{
int buf_idx;
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
GLfloat color_buf[3];
for (int i = 0; i < (int) hexes->size(); i++)
{
buf_idx = i * buf_len_per_hex;
hex_info hxi = (*hexes)[i];
// TODO: check performance of this since we call multiple times per frame
// maybe can cache glfloat triplets somewhere
utilConvertColor(color_buf, hxi.current_color);
for (int j = 0; j < buf_len_per_hex; j+=3)
{
buf[buf_idx + j] = color_buf[0];
buf[buf_idx + j + 1] = color_buf[1];
buf[buf_idx + j + 2] = color_buf[2];
}
}
}
void
fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
{
Point p1, p2;
int idx = 0;
for (int i = 0; i < (int) hexes->size(); i++)
{
hex_info hxi = (*hexes)[i];
for (int j = 0; j < 6; j ++)
{
if (j == 5) // wrap
{
p1 = hxi.vertices[j];
p2 = hxi.vertices[0];
}
else
{
p1 = hxi.vertices[j];
p2 = hxi.vertices[j + 1];
}
buf[idx + 0] = p1.x;
buf[idx + 1] = p1.y;
buf[idx + 2] = 0.f;
buf[idx + 3] = p2.x;
buf[idx + 4] = p2.y;
buf[idx + 5] = 0.f;
idx += 6;
}
}
}

3
src/util.cpp

@ -1,4 +1,5 @@
#include <cassert>
#include <cstdlib>
#include <cstdio>
@ -41,6 +42,8 @@ utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int l
<< file_name << ":" << line;
}
assert(mem != nullptr); // might as well stop execution here
return mem;
}

Loading…
Cancel
Save