Browse Source

feature parity with immediade mode opengl woo

also added some helper functions for the renderer createScene()
master
cinnaboot 9 years ago
parent
commit
fb98faf835
  1. 9
      src/gooey.h
  2. 103
      src/hexgame.cpp
  3. 394
      src/renderer.h

9
src/gooey.h

@ -15,9 +15,6 @@ void shutdownGooey();
bool gooeyProcessEvent(SDL_Event &event); bool gooeyProcessEvent(SDL_Event &event);
void renderGooey(SDL_Handles &handles, HexDrawMode &mode); void renderGooey(SDL_Handles &handles, HexDrawMode &mode);
// TODO: replace with game state
bool is_debug_render = true;
bool bool
initGooey(SDL_Handles &handles, v2i vp_dims /*TODO: pass in game state*/) initGooey(SDL_Handles &handles, v2i vp_dims /*TODO: pass in game state*/)
{ {
@ -45,7 +42,7 @@ gooeyProcessEvent(SDL_Event &event)
} }
void void
renderGooey(SDL_Handles &handles, HexDrawMode &mode) renderGooey(SDL_Handles &handles, HexDrawMode &mode, bool &is_debug)
{ {
ImGui_ImplSdlGL3_NewFrame(handles.window); ImGui_ImplSdlGL3_NewFrame(handles.window);
@ -74,8 +71,8 @@ renderGooey(SDL_Handles &handles, HexDrawMode &mode)
if (ImGui::Button("Cone Fill")) if (ImGui::Button("Cone Fill"))
mode = CONE_FILL; mode = CONE_FILL;
ImGui::Checkbox("Debug Render", &is_debug_render); ImGui::Checkbox("Debug Render", &is_debug);
ImGui::SameLine(); ImGui::TextUnformatted(is_debug_render ? "true" : "false"); ImGui::SameLine(); ImGui::TextUnformatted(is_debug ? "true" : "false");
ImGui::Render(); ImGui::Render();
} }

103
src/hexgame.cpp

@ -331,65 +331,52 @@ handleMouseUp(SDL_MouseButtonEvent &e)
} }
} }
// TODO: use timer in render loop, and call SDL event handler
// per frame with event pump
bool bool
enterLoop(SDL_Handles &handles) processSDLEvents(SDL_Handles &handles)
{ {
SDL_Event e; SDL_Event e;
bool quit = false; bool run = true;
while(!quit)
while (SDL_PollEvent(&e))
{ {
// TODO: remove hack to not peg CPU. replace with an actual frame timer // let gooey have event
SDL_Delay(16); // ~60hz // TODO: need to check for both io.WantCaptureKeyboard and io.WantCaptureMouse
// to fix bug with 'ESC' not passing through while in imgui
bool gooey_wants = gooeyProcessEvent(e);
while (SDL_PollEvent(&e)) switch (e.type)
{ {
// let gooey have event case SDL_QUIT:
// TODO: need to check for both io.WantCaptureKeyboard and io.WantCaptureMouse run = false;
// to fix bug with 'ESC' not passing through while in imgui break;
bool gooey_wants = gooeyProcessEvent(e); case SDL_KEYDOWN:
if ( e.key.keysym.sym == SDLK_ESCAPE)
switch (e.type) run = false;
{ break;
case SDL_QUIT: case SDL_MOUSEBUTTONDOWN:
quit = true; if (!gooey_wants)
break; {
case SDL_KEYDOWN: g_game_state->is_selecting = true;
if ( e.key.keysym.sym == SDLK_ESCAPE) handleMouseDown(e.button);
quit = true; }
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
if (!gooey_wants) if (!gooey_wants)
{ {
g_game_state->is_selecting = true; g_game_state->is_selecting = false;
handleMouseDown(e.button); handleMouseUp(e.button);
} }
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEMOTION:
if (!gooey_wants) if (!gooey_wants)
{ handleMouseMove(e.motion);
g_game_state->is_selecting = false; break;
handleMouseUp(e.button); default:
} break;
break;
case SDL_MOUSEMOTION:
if (!gooey_wants)
handleMouseMove(e.motion);
break;
default:
break;
}
} }
// TODO: move loop to main() and condense all these SDL event functions?
// something like a large processSDLEvents()
renderFrame(g_game_state->hex_array /* TODO: pass in game state*/);
renderGooey(handles, g_game_state->draw_mode);
SDL_GL_SwapWindow(handles.window);
} }
return true; return run;
} }
bool bool
@ -466,9 +453,19 @@ int main(int argc, char* argv[])
LOG(ERROR) << "Fooey, No Gooey!\n"; LOG(ERROR) << "Fooey, No Gooey!\n";
return 1; return 1;
} }
// main loop
while (processSDLEvents(handles))
{
// TODO: remove hack to not peg CPU. replace with an actual frame timer
SDL_Delay(16); // ~60hz
renderFrame(g_game_state->hex_array);
if (g_render_state->is_debug_draw && g_game_state->draw_mode == CONE_FILL)
renderDebug(g_game_state->start_hex, g_game_state->current_hex);
renderGooey(handles, g_game_state->draw_mode, g_render_state->is_debug_draw);
SDL_GL_SwapWindow(handles.window);
}
// TODO: condense main loop
enterLoop(handles);
cleanUp(handles); cleanUp(handles);
return 0; return 0;
} }

394
src/renderer.h

@ -3,12 +3,13 @@
#define RENDERER_H #define RENDERER_H
#include <vector> #include <vector>
#include <cmath> // trig functions
#include <cstdlib> // calloc
// TODO: decide on extension library // TODO: decide on extension library
//#include <GL/glew.h> //#include <GL/glew.h>
#include <GL/gl3w.h> #include <GL/gl3w.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
@ -17,16 +18,6 @@
#include "hexgame.h" #include "hexgame.h"
// Interface
bool initRenderer(SDL_Handles &handles, v2i vpDims);
bool createScene(std::vector<hex_info>* hexes);
// TODO: re-implement debug renderer
void debugRender(HexDrawMode mode, hex_info *startHex, hex_info *currentHex);
void renderFrame(const std::vector<hex_info> *hexes);
void freeBuffers();
const char * VERTEX_SHADER_CODE = const char * VERTEX_SHADER_CODE =
"#version 330 core\n" "#version 330 core\n"
"in vec3 vertexPosition_modelspace;\n" "in vec3 vertexPosition_modelspace;\n"
@ -56,6 +47,13 @@ const char * LINE_FRAGMENT_SHADER_CODE =
" color = vec3(0,0,0);\n" " color = vec3(0,0,0);\n"
"}"; "}";
const char * DEBUG_FRAGMENT_SHADER_CODE =
"#version 330 core\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" color = vec3(1,0,0);\n"
"}";
typedef struct clear_col typedef struct clear_col
{ {
@ -91,22 +89,30 @@ typedef struct gl_render_group
GLuint vertex_array_id; GLuint vertex_array_id;
} gl_render_group; } gl_render_group;
gl_matrix_info g_scene_matrices; gl_matrix_info g_scene_matrices;
gl_render_group g_filled_hex_render_group; gl_render_group g_filled_hex_render_group;
gl_render_group g_hex_line_render_group; gl_render_group g_hex_line_render_group;
gl_render_group g_debug_render_group;
// Interface
bool initRenderer(SDL_Handles &handles, v2i vpDims);
bool createScene(std::vector<hex_info>* hexes);
void renderFrame(const std::vector<hex_info> *hexes);
void renderDebug(hex_info *start_hex, hex_info * current_hex);
void freeBuffers();
// forward declarations // forward declarations
bool initShaders(GLuint &programID1, GLuint &programID2);
bool initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, const char * mat_id); bool initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, const char * mat_id);
// enable debug output https://www.khronos.org/opengl/wiki/OpenGL_Error // enable debug output https://www.khronos.org/opengl/wiki/OpenGL_Error
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam); GLsizei length, const GLchar* message, const void* userParam);
void parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex); void fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex);
bool fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes); void fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes);
void fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes);
bool checkGLBufferSize(GLenum buf_type, int expected_size, int line_num); bool checkGLBufferSize(GLenum buf_type, int expected_size, int line_num);
bool initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]);
bool bool
initRenderer(SDL_Handles &handles, v2i vpDims) initRenderer(SDL_Handles &handles, v2i vpDims)
@ -132,11 +138,13 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
handles.glContext = SDL_GL_CreateContext(handles.window); handles.glContext = SDL_GL_CreateContext(handles.window);
// TODO: decide on extension library
gl3wInit();
#if 0
// Initialize GLEW // Initialize GLEW
// glewExperimental is only needed in GLEW <= 1.13.0 // glewExperimental is only needed in GLEW <= 1.13.0
// we can require version 2.0.0+ // we can require version 2.0.0+
//glewExperimental = true; // Needed for core profile //glewExperimental = true; // Needed for core profile
#if 0
GLenum err = glewInit(); GLenum err = glewInit();
if (err != GLEW_OK) { if (err != GLEW_OK) {
LOG(ERROR) << "Failed to initilize GLEW" << glewGetErrorString(err) << "\n"; LOG(ERROR) << "Failed to initilize GLEW" << glewGetErrorString(err) << "\n";
@ -144,11 +152,6 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
} }
#endif #endif
// TODO: remove for glew?
#if 1
gl3wInit();
#endif
LOG(INFO) << "opengl vendor: " << glGetString(GL_VENDOR) << "\n"; LOG(INFO) << "opengl vendor: " << glGetString(GL_VENDOR) << "\n";
LOG(INFO)<< "opengl renderer: " << glGetString(GL_RENDERER) << "\n"; LOG(INFO)<< "opengl renderer: " << glGetString(GL_RENDERER) << "\n";
LOG(INFO) << "opengl version: " << glGetString(GL_VERSION) << "\n"; LOG(INFO) << "opengl version: " << glGetString(GL_VERSION) << "\n";
@ -169,8 +172,10 @@ initRenderer(SDL_Handles &handles, v2i vpDims)
// hide VRAM debug messages // hide VRAM debug messages
glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE);
// TODO: check for errors when compiling shaders
initShaderProgram(g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "MVP"); initShaderProgram(g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "MVP");
initShaderProgram(g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "MVP"); initShaderProgram(g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "MVP");
initShaderProgram(g_debug_render_group, VERTEX_SHADER_CODE, DEBUG_FRAGMENT_SHADER_CODE, "MVP");
return true; return true;
} }
@ -201,13 +206,13 @@ initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * fr
glDeleteShader(vertex_shader_id); glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id); glDeleteShader(fragment_shader_id);
// TODO: check for errors when compiling shaders
return true; return true;
} }
bool bool
createScene(std::vector<hex_info>* hexes) createScene(std::vector<hex_info>* hexes)
{ {
////////////////////
// Model, View, Projection Matrices // Model, View, Projection Matrices
// left, right, bottom, top, zNear, zFar // left, right, bottom, top, zNear, zFar
@ -222,46 +227,26 @@ createScene(std::vector<hex_info>* hexes)
g_scene_matrices.model = glm::mat4(1.0f); g_scene_matrices.model = glm::mat4(1.0f);
g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model; g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model;
////////////////////
// Vertex Data // Vertex Data
// TODO: index duplicate vertices // TODO: index duplicate vertices
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/ // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
int hex_count = (int) hexes->size(); int hex_count = (int) hexes->size();
gl_buffer *vertex_buffer = &g_filled_hex_render_group.vertex_buffer;
vertex_buffer->buffer_len = hex_count * 6 * 3 * 3;
vertex_buffer->buffer = (GLfloat*) std::calloc(vertex_buffer->buffer_len, sizeof(GLfloat));
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54 // 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
int buf_index = 54; int vbuf_len = hex_count * 6 * 3 * 3;
GLfloat vbuf[vbuf_len];
for (int i = 0; i < hex_count; i++) for (int i = 0; i < hex_count; i++)
{ fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]);
parseHexToGLBuffer(vertex_buffer->buffer, buf_index * i, (*hexes)[i]);
} if (!initGLBufferObject(&g_filled_hex_render_group.vertex_buffer, vbuf_len, GL_DYNAMIC_DRAW, vbuf))
glGenBuffers(1, &g_filled_hex_render_group.vertex_buffer.buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, g_filled_hex_render_group.vertex_buffer.buffer_id);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), vertex_buffer->buffer, GL_DYNAMIC_DRAW);
if (!checkGLBufferSize(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), __LINE__))
return false; return false;
// color data for hex vertices // color data for hex vertices
gl_buffer *color_buffer = &g_filled_hex_render_group.color_buffer; GLfloat cbuf[vbuf_len];
color_buffer->buffer_len = vertex_buffer->buffer_len; fillColorBuffer(cbuf, vbuf_len, hexes);
color_buffer->buffer = (GLfloat*) std::calloc(color_buffer->buffer_len, sizeof(GLfloat));
if (!fillColorBuffer(color_buffer->buffer, color_buffer->buffer_len, hexes))
return false;
glGenBuffers(1, &color_buffer->buffer_id); if (!initGLBufferObject(&g_filled_hex_render_group.color_buffer, vbuf_len, GL_DYNAMIC_DRAW, cbuf))
glBindBuffer(GL_ARRAY_BUFFER, color_buffer->buffer_id);
glBufferData(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), color_buffer->buffer, GL_DYNAMIC_DRAW);
if (!checkGLBufferSize(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), __LINE__))
return false; return false;
// hex line vertex data // hex line vertex data
@ -270,51 +255,25 @@ createScene(std::vector<hex_info>* hexes)
// and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements? // and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements?
// https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index // https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index
int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer; //gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer;
line_vertex_buffer->buffer_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex int line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
line_vertex_buffer->buffer = (GLfloat*) std::calloc(line_vertex_buffer->buffer_len, sizeof(GLfloat)); GLfloat line_buf[line_buf_len];
fillHexLineBuffer(line_buf, line_buf_len, hexes);
Point p1, p2; if (!initGLBufferObject(&g_hex_line_render_group.vertex_buffer, line_buf_len, GL_STATIC_DRAW, line_buf))
int line_buf_idx = 0; return false;
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];
}
line_vertex_buffer->buffer[line_buf_idx + 0] = p1.x;
line_vertex_buffer->buffer[line_buf_idx + 1] = p1.y;
line_vertex_buffer->buffer[line_buf_idx + 2] = 0.f;
line_vertex_buffer->buffer[line_buf_idx + 3] = p2.x;
line_vertex_buffer->buffer[line_buf_idx + 4] = p2.y;
line_vertex_buffer->buffer[line_buf_idx + 5] = 0.f;
line_buf_idx += 6;
}
}
glGenBuffers(1, &line_vertex_buffer->buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_id);
glBufferData(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), line_vertex_buffer->buffer, GL_STATIC_DRAW);
if (!checkGLBufferSize(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), __LINE__)) // debug draw vertexes
// 4 vertices, 3 floats per vertex
int len = 4 * 3;
if (!initGLBufferObject(&g_debug_render_group.vertex_buffer, len, GL_DYNAMIC_DRAW, 0))
return false; return false;
return true; return true;
} }
void void
parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex)
{ {
// triangles // triangles
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@ -359,28 +318,9 @@ parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex)
} }
} }
bool void
fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes) fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes)
{ {
if (!buf || len < 1)
{
LOG(ERROR) << "buffer length mismatch\n";
return false;
}
if (!hexes || hexes->size() == 0)
{
LOG(ERROR) << "hex_info input error\n";
return false;
}
// 3 floats per vertex, 3 vertexes per triangle, 6 triangles per hex
if (len != (int) hexes->size() * 3 * 3 * 6)
{
LOG(ERROR) << "hex_info input error\n";
return false;
}
int buf_idx; int buf_idx;
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6 int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
for (int i = 0; i < (int) hexes->size(); i++) for (int i = 0; i < (int) hexes->size(); i++)
@ -390,12 +330,40 @@ fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes)
GLfloat color = (GLfloat) hxi.current_color / (GLfloat) UINT32_MAX; GLfloat color = (GLfloat) hxi.current_color / (GLfloat) UINT32_MAX;
for (int j = 0; j < buf_len_per_hex; j++) for (int j = 0; j < buf_len_per_hex; j++)
{
buf[buf_idx + j] = color; buf[buf_idx + j] = color;
}
} }
}
return true; 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;
}
}
} }
// NOTE: this will only work after a call to glBindBuffer // NOTE: this will only work after a call to glBindBuffer
@ -414,6 +382,28 @@ checkGLBufferSize(GLenum buf_type, int expected_size, int line_num)
return true; return true;
} }
bool
initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[])
{
buf_obj->buffer_len = (size_t) len;
buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat));
if (data)
{
for (int i = 0; i < len; i++)
buf_obj->buffer[i] = data[i];
}
glGenBuffers(1, &buf_obj->buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, buf_obj->buffer_id);
glBufferData(GL_ARRAY_BUFFER, len * sizeof(GLfloat), buf_obj->buffer, usage);
if (!checkGLBufferSize(GL_ARRAY_BUFFER, len * sizeof(GLfloat), __LINE__))
return false;
return true;
}
void void
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, const void* userParam) GLsizei length, const GLchar* message, const void* userParam)
@ -431,99 +421,117 @@ renderFrame(std::vector<hex_info> *hexes)
glClearColor(g_clear_col.R, g_clear_col.G, g_clear_col.B, g_clear_col.A); 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); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// filled hexes
// TODO: learn how to use VAOs instead of these calls to glVertexAttribPointer {
// https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object // TODO: learn how to use VAOs instead of these calls to glVertexAttribPointer
gl_render_group* rg = &g_filled_hex_render_group; // https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object
glUseProgram(rg->program_id); gl_render_group* rg = &g_filled_hex_render_group;
// Send our transformation to the currently bound shader, in the "g_MVP" uniform glUseProgram(rg->program_id);
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); // Send our transformation to the currently bound shader, in the "g_MVP" uniform
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0); // 1st attribute buffer : vertices
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1); // 2nd attribute buffer : colors
glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id);
// get new colors every frame glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes);
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), rg->color_buffer.buffer); // get new colors every frame
fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes);
// draw glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat),
glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3); rg->color_buffer.buffer);
// draw
// cleanup glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1); // cleanup
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
// hex lines // hex lines
// TODO: conpress these calls into helper function
{
gl_render_group* rg = &g_hex_line_render_group;
glUseProgram(rg->program_id);
// Send our transformation to the currently bound shader, in the "g_MVP" uniform
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]);
// 1st attribute buffer : vertices
GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0
glEnableVertexAttribArray(attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3);
glDisableVertexAttribArray(0);
}
}
rg = &g_hex_line_render_group; void
renderDebug(hex_info *start_hex, hex_info *current_hex)
{
if (!start_hex || !current_hex)
return;
// fill vertex buffer
Point p1(start_hex->XPos, start_hex->YPos);
Point p2(current_hex->XPos, current_hex->YPos);
real64 angle = std::atan2(p2.y - p1.y, p2.x - p1.x);
real64 len = std::hypot(p2.y - p1.y, p2.x - p1.x);
real64 coneAngle = 24.5f * M_PI / 180; // M_PI is non-standard and may not be portable
// TODO: add matrix math library for rotation transform?
// |x| | cos(a + b) -sin(a + b) 0 |
// |y| * | sin(a + b) cos(a + b) 0 |
// |0| | 0 0 1 |
//
real64 x1 = len * std::cos(angle);
real64 y1 = len * std::sin(angle);
// top of cone
real64 topX = x1 * std::cos(coneAngle) - y1 * std::sin(coneAngle) + p1.x;
real64 topY = x1 * std::sin(coneAngle) + y1 * std::cos(coneAngle) + p1.y;
// bottom of cone
real64 botX = x1 * std::cos(coneAngle) + y1 * std::sin(coneAngle) + p1.x;
real64 botY = x1 * std::sin(-1 * coneAngle) + y1 * std::cos(coneAngle) + p1.y;
// TODO: indexed line drawing
real64 buf[4 * 3] = {
p1.x, p1.y, 0,
botX, botY, 0,
p2.x, p2.y, 0,
topX, topY, 0,
};
// copy vertexes to render group
gl_render_group* rg = &g_debug_render_group;
for (int i = 0; i < 12; i++)
rg->vertex_buffer.buffer[i] = buf[i];
// TODO: conpress these calls into helper function
glUseProgram(rg->program_id); glUseProgram(rg->program_id);
// Send our transformation to the currently bound shader, in the "g_MVP" uniform // Send our transformation to the currently bound shader, in the "g_MVP" uniform
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]);
// 1st attribute buffer : vertices glEnableVertexAttribArray(0);
GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0
glEnableVertexAttribArray(attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3); // send new vertex data
} glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat),
rg->vertex_buffer.buffer);
#if 0 glDrawArrays(GL_LINE_LOOP, 0, rg->vertex_buffer.buffer_len / 3);
// TODO: many globals used here glDisableVertexAttribArray(0);
void
debugRender()
{
if (globalDrawMode == CONE_FILL)
{
if (startHex && currentHex)
{
Point p1 = hex_to_pixel(global_layout, startHex->hex);
Point p2 = hex_to_pixel(global_layout, currentHex->hex);
// NOTE: some cone drawing shenanigans
real32 angle = (real32) atan2(p2.y - p1.y, p2.x - p1.x);
real32 len = (real32) hypot(p2.y - p1.y, p2.x - p1.x);
real32 coneAngle = 24.5f * (real32) M_PI / 180;
// TODO: add matrix math library for rotation transform?
// |x| | cos(a + b) -sin(a + b) 0 |
// |y| * | sin(a + b) cos(a + b) 0 |
// |0| | 0 0 1 |
//
real32 x1 = len * cosf(angle);
real32 y1 = len * sinf(angle);
// top of cone
real32 topX = x1 * cosf(coneAngle) - y1 * sinf(coneAngle) + (real32) p1.x;
real32 topY = x1 * sinf(coneAngle) + y1 * cosf(coneAngle) + (real32) p1.y;
// bottom of cone
real32 botX = x1 * cosf(coneAngle) + y1 * sinf(coneAngle) + (real32) p1.x;
real32 botY = x1 * sinf(-1 * coneAngle) + y1 * cosf(coneAngle) + (real32) p1.y;
glColor4f(1.0f, 1.0f, 0.5f, 1.0f);
glLineWidth(1.0f);
glBegin(GL_LINE_LOOP);
glVertex3d(p1.x, p1.y, 0);
glVertex3f(botX, botY, 0);
glVertex3d(p2.x, p2.y, 0);
glVertex3f(topX, topY, 0);
glEnd();
}
}
} }
#endif
void void
freeBuffers() freeBuffers()
{ {
std::vector<gl_render_group> groups = {g_filled_hex_render_group, g_hex_line_render_group}; std::vector<gl_render_group> groups = {
g_filled_hex_render_group,
g_hex_line_render_group,
g_debug_render_group
};
for (gl_render_group group : groups) for (gl_render_group group : groups)
{ {

Loading…
Cancel
Save