Browse Source

cleaned up shader code in renderer.h

master
dummy 9 years ago
parent
commit
4f6884526c
  1. 4
      src/hexgame.cpp
  2. 2
      src/hexgame.h
  3. 304
      src/renderer.h

4
src/hexgame.cpp

@ -7,10 +7,7 @@
#include <Winuser.h> #include <Winuser.h>
#endif #endif
#include <GL/glew.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include "aixlog.hpp"
#include "hexgame.h" #include "hexgame.h"
#include "hexlib.h" #include "hexlib.h"
@ -460,7 +457,6 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
int main(int argc, char* argv[]) int main(int argc, char* argv[])
#endif #endif
{ {
// init fancy new logger
AixLog::Log::init<AixLog::SinkCout>(AixLog::Severity::trace, AixLog::Type::normal); AixLog::Log::init<AixLog::SinkCout>(AixLog::Severity::trace, AixLog::Type::normal);
LOG(INFO) << "Application started\n"; LOG(INFO) << "Application started\n";

2
src/hexgame.h

@ -6,6 +6,8 @@
#include <cassert> #include <cassert>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include "aixlog.hpp"
#include "hexlib.h" #include "hexlib.h"
typedef float real32; typedef float real32;

304
src/renderer.h

@ -22,9 +22,70 @@ void renderFrame(const std::vector<hex_info> *hexes);
void freeBuffers(); void freeBuffers();
const char * VERTEX_SHADER_CODE =
"#version 330 core\n"
"in vec3 vertexPosition_modelspace;\n"
"in vec3 vertexColor;\n"
"out vec3 fragmentColor;\n"
"uniform mat4 MVP;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vertexPosition_modelspace, 1);\n"
" fragmentColor = vertexColor;\n"
"}";
const char * FRAGMENT_SHADER_CODE =
"#version 330 core\n"
"in vec3 fragmentColor;\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" color = fragmentColor;\n"
"}";
const char * LINE_FRAGMENT_SHADER_CODE =
"#version 330 core\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" color = vec3(0,0,0);\n"
"}";
typedef struct gl_matrix_info
{
glm::mat4 projection;
glm::mat4 view;
glm::mat4 model;
glm::mat4 MVP;
} gl_matrix_info;
typedef struct gl_buffer
{
GLuint buffer_id;
size_t buffer_len; // NOTE: number of elements in buffer
GLfloat* buffer;
} gl_buffer;
typedef struct gl_render_group
{
// NOTE: For now the renderFrame function will assume these are the same size
gl_buffer vertex_buffer;
gl_buffer color_buffer;
GLuint program_id;
GLuint matrix_id; // NOTE: reference to a vertex shader's MVP matrix uniform
GLuint vertex_array_id;
} gl_render_group;
gl_matrix_info g_scene_matrices;
gl_render_group g_filled_hex_render_group;
gl_render_group g_hex_line_render_group;
// forward declarations // forward declarations
bool initShaders(GLuint &programID1, GLuint &programID2); bool initShaders(GLuint &programID1, GLuint &programID2);
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);
@ -32,23 +93,6 @@ void createScene(std::vector<hex_info>* hexes);
void parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex); void parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex);
bool fillColorBuffer(GLfloat* buf, int len, std::vector<hex_info> *hexes); bool fillColorBuffer(GLfloat* buf, int len, std::vector<hex_info> *hexes);
// TODO: organize these into a struct/structs since we're using at least 2 now
glm::mat4 g_projection_matrix;
glm::mat4 g_view_matrix;
glm::mat4 g_model_matrix;
glm::mat4 g_MVP;
GLuint g_vertexbuffer;
GLuint g_vertex_buffer_triangle_count;
GLuint g_color_buffer;
size_t g_buf_size;
GLfloat *g_color_buf_data;
GLuint g_hex_programID;
GLuint g_matrixID;
GLuint g_hex_line_vertexbuffer;
size_t g_line_buf_size;
GLuint g_line_programID;
GLuint g_line_matrixID;
bool bool
initRenderer(SDL_Handles &handles, v2i vpDims) initRenderer(SDL_Handles &handles, v2i vpDims)
@ -104,80 +148,38 @@ 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);
initShaders(g_hex_programID, g_line_programID); initShaderProgram(g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "MVP");
g_matrixID = glGetUniformLocation(g_hex_programID, "g_MVP"); // shader variables for mvp xform initShaderProgram(g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "MVP");
g_line_matrixID = glGetUniformLocation(g_line_programID, "g_MVP");
return true; return true;
} }
// TODO: figure out how to keep track of shader state, and pass in struct here // NOTE: mat_id should match the matrix variable name in the shader source
// TODO: make reusable by creating 1 program at a time
bool bool
initShaders(GLuint &programID1, GLuint &programID2) initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, const char * mat_id)
{ {
GLuint VertexArrayID; glGenVertexArrays(1, &rg.vertex_array_id);
glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(rg.vertex_array_id);
glBindVertexArray(VertexArrayID); GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
const char * VertexShaderCode =
"#version 330 core\n" glShaderSource(vertex_shader_id, 1, &vertex_code, NULL);
"in vec3 vertexPosition_modelspace;\n" glShaderSource(fragment_shader_id, 1, &frag_code, NULL);
"in vec3 vertexColor;\n" glCompileShader(vertex_shader_id);
"out vec3 fragmentColor;\n" glCompileShader(fragment_shader_id);
"uniform mat4 g_MVP;\n"
"void main()\n" rg.program_id = glCreateProgram();
"{\n" glAttachShader(rg.program_id, vertex_shader_id);
" gl_Position = g_MVP * vec4(vertexPosition_modelspace, 1);\n" glAttachShader(rg.program_id, fragment_shader_id);
" fragmentColor = vertexColor;\n" glLinkProgram(rg.program_id);
"}";
rg.matrix_id = glGetUniformLocation(rg.program_id, mat_id);
const char * FragmentShaderCode =
"#version 330 core\n" glDetachShader(rg.program_id, vertex_shader_id);
"in vec3 fragmentColor;\n" glDetachShader(rg.program_id, fragment_shader_id);
"out vec3 color;\n" glDeleteShader(vertex_shader_id);
"void main()\n" glDeleteShader(fragment_shader_id);
"{\n"
" color = fragmentColor;\n"
"}";
#if 1
const char * LineFragmentShaderCode =
"#version 330 core\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
" color = vec3(0,0,0);\n"
"}";
#endif
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLuint LineFragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(VertexShaderID, 1, &VertexShaderCode, NULL);
glShaderSource(FragmentShaderID, 1, &FragmentShaderCode, NULL);
glShaderSource(LineFragmentShaderID, 1, &LineFragmentShaderCode, NULL);
glCompileShader(VertexShaderID);
glCompileShader(FragmentShaderID);
glCompileShader(LineFragmentShaderID);
programID1 = glCreateProgram();
glAttachShader(programID1, VertexShaderID);
glAttachShader(programID1, FragmentShaderID);
glLinkProgram(programID1);
programID2 = glCreateProgram();
glAttachShader(programID2, VertexShaderID);
glAttachShader(programID2, LineFragmentShaderID);
glLinkProgram(programID2);
glDetachShader(programID1, VertexShaderID);
glDetachShader(programID1, FragmentShaderID);
glDetachShader(programID2, LineFragmentShaderID);
glDetachShader(programID2, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
glDeleteShader(LineFragmentShaderID);
// TODO: what kind of errors can happen here?
return true; return true;
} }
@ -188,16 +190,16 @@ 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
g_projection_matrix = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f); g_scene_matrices.projection = glm::ortho(0.f, 1280.0f, 0.f, 720.0f, 0.1f, 100.0f);
g_view_matrix = glm::lookAt( g_scene_matrices.view = glm::lookAt(
glm::vec3(0.0f, 0.0f, 2.0f), // camera position glm::vec3(0.0f, 0.0f, 2.0f), // camera position
glm::vec3(0.0f, 0.0f, 0.0f), // look at position glm::vec3(0.0f, 0.0f, 0.0f), // look at position
glm::vec3(0,1,0) // "up" vector glm::vec3(0,1,0) // "up" vector
); );
g_model_matrix = glm::mat4(1.0f); g_scene_matrices.model = glm::mat4(1.0f);
g_MVP = g_projection_matrix * g_view_matrix * g_model_matrix; g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model;
//////////////////// ////////////////////
@ -205,56 +207,59 @@ createScene(std::vector<hex_info>* hexes)
// 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();
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54 gl_buffer *vertex_buffer = &g_filled_hex_render_group.vertex_buffer;
int buf_index = 54; vertex_buffer->buffer_len = hex_count * 6 * 3 * 3;
size_t hex_count = hexes->size(); vertex_buffer->buffer = (GLfloat*) std::calloc(vertex_buffer->buffer_len, sizeof(GLfloat));
g_buf_size = 6 * 9 * hex_count;
GLfloat vbuf_data[g_buf_size] = { 0 };
for (int i = 0; i < (int) hex_count; i++) // 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
int buf_index = 54;
for (int i = 0; i < hex_count; i++)
{ {
parseHexToGLBuffer(vbuf_data, buf_index * i, (*hexes)[i]); parseHexToGLBuffer(vertex_buffer->buffer, buf_index * i, (*hexes)[i]);
} }
g_vertex_buffer_triangle_count = g_buf_size / 3; glGenBuffers(1, &g_filled_hex_render_group.vertex_buffer.buffer_id);
glGenBuffers(1, &g_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, g_filled_hex_render_group.vertex_buffer.buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, g_vertexbuffer); glBufferData(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), vertex_buffer->buffer, GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * g_buf_size, vbuf_data, GL_STATIC_DRAW);
// color data for hex vertices // color data for hex vertices
g_color_buf_data = (GLfloat*) std::calloc( g_buf_size, sizeof(GLfloat)); gl_buffer *color_buffer = &g_filled_hex_render_group.color_buffer;
color_buffer->buffer_len = vertex_buffer->buffer_len;
color_buffer->buffer = (GLfloat*) std::calloc(color_buffer->buffer_len, sizeof(GLfloat));
if (!fillColorBuffer(g_color_buf_data, (int) g_buf_size, hexes)) if (!fillColorBuffer(color_buffer->buffer, color_buffer->buffer_len, hexes))
{ {
// TODO: log fatal error //freeBuffers();
//return false;
// TODO: check for retval in main() and run cleanUp()
return; return;
} }
glGenBuffers(1, &g_color_buffer); glGenBuffers(1, &color_buffer->buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, g_color_buffer); glBindBuffer(GL_ARRAY_BUFFER, color_buffer->buffer_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * g_buf_size, g_color_buf_data, GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), color_buffer->buffer, GL_DYNAMIC_DRAW);
// Hex Line Vertex Data // hex line vertex data
// TODO: surely there's a way to use indexed drawing for line vertices eg) LINE_LOOP // todo: surely there's a way to use indexed drawing for line vertices eg) line_loop
// 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
g_line_buf_size = hex_count * line_vertices_per_hex * 3; // 3 floats per vertex gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer;
GLfloat line_buf_data[g_line_buf_size] = { 0 }; line_vertex_buffer->buffer_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));
Point p1, p2;
int line_buf_idx = 0; int line_buf_idx = 0;
for (int i = 0; i < (int) hex_count; i++) for (int i = 0; i < (int) hexes->size(); i++)
{ {
hex_info hxi = (*hexes)[i]; hex_info hxi = (*hexes)[i];
for (int j = 0; j < 6; j ++) for (int j = 0; j < 6; j ++)
{ {
Point p1, p2;
if (j == 5) // wrap if (j == 5) // wrap
{ {
p1 = hxi.vertices[j]; p1 = hxi.vertices[j];
@ -266,20 +271,20 @@ createScene(std::vector<hex_info>* hexes)
p2 = hxi.vertices[j + 1]; p2 = hxi.vertices[j + 1];
} }
line_buf_data[line_buf_idx + 0] = p1.x; line_vertex_buffer->buffer[line_buf_idx + 0] = p1.x;
line_buf_data[line_buf_idx + 1] = p1.y; line_vertex_buffer->buffer[line_buf_idx + 1] = p1.y;
line_buf_data[line_buf_idx + 2] = 0.f; line_vertex_buffer->buffer[line_buf_idx + 2] = 0.f;
line_buf_data[line_buf_idx + 3] = p2.x; line_vertex_buffer->buffer[line_buf_idx + 3] = p2.x;
line_buf_data[line_buf_idx + 4] = p2.y; line_vertex_buffer->buffer[line_buf_idx + 4] = p2.y;
line_buf_data[line_buf_idx + 5] = 0.f; line_vertex_buffer->buffer[line_buf_idx + 5] = 0.f;
line_buf_idx += 6; line_buf_idx += 6;
} }
} }
glGenBuffers(1, &g_hex_line_vertexbuffer); glGenBuffers(1, &line_vertex_buffer->buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, g_hex_line_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * g_line_buf_size, line_buf_data, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), line_vertex_buffer->buffer, GL_STATIC_DRAW);
} }
void void
@ -381,7 +386,6 @@ 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)
{ {
LOG((type == GL_DEBUG_TYPE_ERROR) ? ERROR : DEBUG) LOG((type == GL_DEBUG_TYPE_ERROR) ? ERROR : DEBUG)
<< "openGLDebugCallback: "
<< (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "") << (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "")
<< ", type: " << type << ", type: " << type
<< ", severity: " << severity << ", severity: " << severity
@ -395,51 +399,69 @@ renderFrame(std::vector<hex_info> *hexes)
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
glUseProgram(g_hex_programID); gl_render_group* rg = &g_filled_hex_render_group;
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(g_matrixID, 1, GL_FALSE, &g_MVP[0][0]); glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]);
// 1st attribute buffer : vertices // 1st attribute buffer : vertices
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, g_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// 2nd attribute buffer : colors // 2nd attribute buffer : colors
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, g_color_buffer); glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
// get new colors every frame // get new colors every frame
fillColorBuffer(g_color_buf_data, (int) g_buf_size, hexes); fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * g_buf_size, g_color_buf_data); glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), rg->color_buffer.buffer);
glDrawArrays(GL_TRIANGLES, 0, g_vertex_buffer_triangle_count);
// draw
glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3);
// cleanup
glDisableVertexAttribArray(0); glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1); glDisableVertexAttribArray(1);
// hex lines // hex lines
glUseProgram(g_line_programID); rg = &g_hex_line_render_group;
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(g_matrixID, 1, GL_FALSE, &g_MVP[0][0]); glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]);
// 1st attribute buffer : vertices // 1st attribute buffer : vertices
GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0 GLuint attrib_index = 0; // TODO: line buffer doesn't render if this is anything other than 0
glEnableVertexAttribArray(attrib_index); glEnableVertexAttribArray(attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, g_hex_line_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id);
glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
glDrawArrays(GL_LINES, 0, g_line_buf_size / 3); glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3);
} }
void void
freeBuffers() freeBuffers()
{ {
if (g_color_buf_data) std::vector<gl_render_group> groups = {g_filled_hex_render_group, g_hex_line_render_group};
for (gl_render_group group : groups)
{ {
free(g_color_buf_data); if (group.vertex_buffer.buffer)
g_color_buf_data = 0; {
std::free(group.vertex_buffer.buffer);
group.vertex_buffer.buffer = 0;
}
if (group.color_buffer.buffer)
{
std::free(group.color_buffer.buffer);
group.color_buffer.buffer = 0;
}
} }
} }
#endif // RENDERER_H #endif // RENDERER_H

Loading…
Cancel
Save