diff --git a/data/shaders/default_frag.glsl b/data/shaders/default_frag.glsl new file mode 100644 index 0000000..c0db66b --- /dev/null +++ b/data/shaders/default_frag.glsl @@ -0,0 +1,9 @@ +#version 330 + +out vec4 fragColor; +smooth in vec4 ioFragColor; + +void main() +{ + fragColor = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/data/shaders/default_vert.glsl b/data/shaders/default_vert.glsl new file mode 100644 index 0000000..91aa78b --- /dev/null +++ b/data/shaders/default_vert.glsl @@ -0,0 +1,19 @@ +#version 330 + +in vec4 inCoord; +in vec3 inNormal; +in vec2 inUV; +in vec4 inColor; + +uniform mat4 uModelMatrix; +uniform mat4 uViewMatrix; +uniform mat4 uProjectionMatrix; + +smooth out vec4 ioFragColor; + +void main() +{ + ioFragColor = inColor; + gl_Position = (uProjectionMatrix * uViewMatrix * uModelMatrix * inCoord); + +} \ No newline at end of file diff --git a/src/srender.c b/src/srender.c index 84a601a..adbd79c 100644 --- a/src/srender.c +++ b/src/srender.c @@ -20,73 +20,222 @@ typedef struct srview { GLuint mColorTexture; GLuint mDepthTexture; - simd4x4f proj; - simd4x4f view; + simd4x4f proj; + simd4x4f view; } srview; typedef struct srcmdbuf { - int ncmds; - int idx; - srcmd* cmds; + int ncmds; + int idx; + srcmd* cmds; } srcmdbuf; // // Vertex Data // typedef union srvrtxdata { - struct { - float x, y, z, w; - float nx, ny, nz; - float s, t; - GLubyte r,g,b,a; - }; - struct { - float pos[4]; - float n[4]; - float uv[2]; - GLubyte color[4]; - }; + struct { + float x, y, z, w; + float nx, ny, nz; + float s, t; + GLubyte r, g, b, a; + }; + struct { + float pos[4]; + float n[4]; + float uv[2]; + GLubyte color[4]; + }; } srvrtxdata; // // Simple Mesh Data // typedef struct srmeshdata { - int nvertices; - int nindices; + int nvertices; + int nindices; - srvrtxdata *vertices; - int *indices; + GLuint vertex_buffer_id; + GLuint index_buffer_id; } srmeshdata; static srmeshdata gCoordFrameMesh = {0}; -void init_debug_meshes () { - assert (gCoordFrameMesh.nvertices == 0); +typedef struct srshader { + const char* vert_fname; + const char* frag_fname; - gCoordFrameMesh.nvertices = 6; + GLuint program_id; + GLuint vert_shader_id; + GLuint frag_shader_id; +} srshader; - srvrtxdata coord_frame_vertices[] = { - {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255 }, - {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255 }, +static srshader gDefaultShader = {"default_vert.glsl", "default_frag.glsl", 0, 0, 0}; - {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255}, - {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255}, +bool srshader_compile (GLuint shader_id, const char* shader_src) { + glShaderSource (shader_id, 1, &shader_src, 0); + glCompileShader (shader_id); - {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255}, - {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255} - }; - GLuint coord_frame_indices[] = { - 0, 1, - 1, 2, - 3, 4 - }; + // Check Vertex Shader + GLint result = GL_FALSE; + int log_length = 0; + glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result); + glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length); + if ( log_length > 0 ){ + char* err_msg = calloc (log_length, sizeof(char)); + assert (err_msg); + glGetShaderInfoLog(shader_id, log_length, NULL, err_msg); + gLog("%s", err_msg); + free (err_msg); - gCoordFrameMesh.vertices = malloc (sizeof(coord_frame_vertices)); - memcpy (gCoordFrameMesh.vertices, coord_frame_vertices, sizeof(coord_frame_vertices)); + return false; + } - gCoordFrameMesh.indices = malloc (sizeof(coord_frame_indices)); - memcpy (gCoordFrameMesh.indices, coord_frame_indices, sizeof (coord_frame_indices)); + return true; +} + +bool srshader_load (srshader* shader, const char* vert_src, const char* frag_src) { + shader->vert_shader_id = glCreateShader(GL_VERTEX_SHADER); + if (!srshader_compile(shader->vert_shader_id, vert_src)) { + gLog("Error compiling vertex shader!"); + return false; + } + + shader->frag_shader_id = glCreateShader(GL_FRAGMENT_SHADER); + if (!srshader_compile(shader->frag_shader_id, frag_src)) { + gLog("Error compiling fragment shader!"); + return false; + } + + shader->program_id = glCreateProgram(); + glAttachShader(shader->program_id, shader->vert_shader_id); + glAttachShader(shader->program_id, shader->frag_shader_id); + + // Bind attribute locations + glBindAttribLocation(shader->program_id, 0, "inCoord"); + glBindAttribLocation(shader->program_id, 1, "inNormal"); + glBindAttribLocation(shader->program_id, 2, "inUV"); + glBindAttribLocation(shader->program_id, 3, "inColor"); + + glLinkProgram(shader->program_id); + + GLint result = GL_FALSE; + int log_length = 0; + glGetProgramiv(shader->program_id, GL_LINK_STATUS, &result); + glGetProgramiv(shader->program_id, GL_INFO_LOG_LENGTH, &log_length); + if ( log_length > 0 ){ + char* err_msg = calloc (log_length, sizeof(char)); + assert (err_msg); + glGetProgramInfoLog(shader->program_id, log_length, NULL, err_msg); + gLog("%s", err_msg); + free (err_msg); + gLog("Error linking shader program!"); + + return false; + } + + return true; +} + +bool try_read_file (const char* dir, const char* filename, char** buf) { + assert (*buf == NULL); + + int path_len = strlen(dir) + strlen(filename) + 1; + char* path_buffer = calloc (path_len, sizeof(char)); + snprintf (path_buffer, path_len, "%s%s", dir, filename); + long file_length = 0; + + FILE* file = NULL; + file = fopen(path_buffer, "rb"); + if (file) { + fseek(file, 0, SEEK_END); + file_length = ftell(file); + fseek(file, 0, SEEK_SET); + *buf = calloc(file_length, sizeof(char)); + assert (*buf); + fread (*buf, 1, file_length, file); + fclose(file); + + return true; + } + + return false; +} + +void init_shaders() { + static const char* shader_search_paths[] = { + "./data/shaders/", + "../data/shaders/", + NULL}; + + bool found = false; + int search_index = 0; + char* frag_buffer = NULL; + char* vert_buffer = NULL; + + while (shader_search_paths[search_index] != NULL) { + const char* dir = shader_search_paths[search_index]; + static char path_buf[1024]; + long length; + + if (vert_buffer == NULL) { + try_read_file (dir, gDefaultShader.vert_fname, &vert_buffer); + } + if (frag_buffer == NULL) { + try_read_file (dir, gDefaultShader.frag_fname, &frag_buffer); + } + + if ((vert_buffer != NULL) && (frag_buffer != NULL)) { + srshader_load (&gDefaultShader, vert_buffer, frag_buffer); + + free (vert_buffer); + vert_buffer = NULL; + free (frag_buffer); + frag_buffer = NULL; + break; + } + + search_index++; + } + + if (gDefaultShader.program_id == 0) { + gLog ("Error: could not load default shader!"); + } +} + +void init_debug_meshes() { + assert(gCoordFrameMesh.nvertices == 0); + + gCoordFrameMesh.nvertices = 6; + + srvrtxdata coord_frame_vertices[] = { + {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255}, + {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255}, + + {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255}, + {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255}, + + {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255}, + {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255}}; + GLuint coord_frame_indices[] = {0, 1, 1, 2, 3, 4}; + + glGenBuffers(1, &gCoordFrameMesh.vertex_buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, gCoordFrameMesh.vertex_buffer_id); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(coord_frame_vertices), + coord_frame_vertices, + GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenBuffers(1, &gCoordFrameMesh.index_buffer_id); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gCoordFrameMesh.index_buffer_id); + glBufferData( + GL_ELEMENT_ARRAY_BUFFER, + sizeof(coord_frame_indices), + coord_frame_indices, + GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); }; // @@ -95,7 +244,8 @@ void init_debug_meshes () { srndr* srndr_create() { srndr* result = calloc(1, sizeof(srndr)); - init_debug_meshes(); + init_shaders(); + init_debug_meshes(); return result; } @@ -109,13 +259,9 @@ void srview_get_output_texture(srview* sv, GLuint* texture) { *texture = sv->mColorTexture; } -void srview_set_proj(srview* sv, simd4x4f proj) { - sv->proj = proj; -} +void srview_set_proj(srview* sv, simd4x4f proj) { sv->proj = proj; } -void srview_set_view(srview* sv, simd4x4f view) { - sv->view = view; -} +void srview_set_view(srview* sv, simd4x4f view) { sv->view = view; } void srview_update_framebuffer(srview* sv) { glGenFramebuffers(1, &sv->mFrameBufferId); @@ -202,15 +348,11 @@ void srview_set_size(srview* sv, int width, int height) { return; } - gLog("Setting size to %d, %d", width, height); - sv->width = width; sv->height = height; srview_cleanup_framebuffer(sv); srview_update_framebuffer(sv); - - gLog("Color texture = %d", sv->mColorTexture); } srview* srview_create() { @@ -225,12 +367,86 @@ void srview_destroy(srview* sv) { free(sv); } +void srndr_run_frame_command(const srcmd* cmd) { + glBindBuffer(GL_ARRAY_BUFFER, gCoordFrameMesh.vertex_buffer_id); + + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, + 4, + GL_FLOAT, + GL_FALSE, + (sizeof(srvrtxdata)), + (void*)0 + ); + + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 3, + GL_FLOAT, + GL_FALSE, + (sizeof(srvrtxdata)), + (void*)(sizeof(float) * 4) + ); + + // Attribute 2: texture coordinates + glEnableVertexAttribArray(2); + glVertexAttribPointer( + 2, + 2, + GL_FLOAT, + GL_FALSE, + (sizeof(srvrtxdata)), + (void*)(sizeof(float) * 7) + ); + // Attribute 3: color + glEnableVertexAttribArray(3); + glVertexAttribPointer( + 3, + 4, + GL_UNSIGNED_BYTE, + GL_TRUE, + (sizeof(srvrtxdata)), + (void*)(sizeof(float) * 9) + ); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gCoordFrameMesh.index_buffer_id); + glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, (void*)0); +} + void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sview->mFrameBufferId); glViewport(0, 0, sview->width, sview->height); - glClearColor(1.f, 0.f, 1.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.1f, 0.1f, 0.1f, 0.1f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(gDefaultShader.program_id); + GLint view_mat_loc = glGetUniformLocation(gDefaultShader.program_id, "uViewMatrix"); + assert (view_mat_loc != -1); + glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, &sview->view); + + GLint proj_mat_loc = glGetUniformLocation(gDefaultShader.program_id, "uProjectionMatrix"); + assert (proj_mat_loc != -1); + glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, &sview->proj); + + GLint model_mat_loc = glGetUniformLocation(gDefaultShader.program_id, "uModelMatrix"); + assert (model_mat_loc != -1); + + for (int i = 0; i < scmdbuf->ncmds; i++) { + const srcmd* cmd = &scmdbuf->cmds[i]; + glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, &cmd->mat); + + switch (cmd->type) { + case SRndrCmdTypeFrame: + srndr_run_frame_command(cmd); + break; + default: + gLog("Invalid command type %d at index %d", cmd->type, i); + break; + } + } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } @@ -238,23 +454,21 @@ void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) { // // Render Commands // -srcmdbuf* srcmdbuf_create (unsigned int size_max) { - srcmdbuf* result = malloc (sizeof (srcmdbuf)); - result->ncmds = size_max; - result->idx = 0; - result->cmds = calloc (sizeof (srcmd), size_max); +srcmdbuf* srcmdbuf_create(unsigned int size_max) { + srcmdbuf* result = malloc(sizeof(srcmdbuf)); + result->ncmds = size_max; + result->idx = 0; + result->cmds = calloc(sizeof(srcmd), size_max); - return result; + return result; } -void srcmdbuf_clear (srcmdbuf* cmdbuf) { - cmdbuf->idx = 0; -} +void srcmdbuf_clear(srcmdbuf* cmdbuf) { cmdbuf->idx = 0; } -srcmd* srcmd_create (srcmdbuf* cmdbuf) { - if (cmdbuf->idx == cmdbuf->ncmds) { - gLog ("Warning: number of render commands maxed out!"); - return NULL; - } - return &(cmdbuf->cmds[cmdbuf->idx++]); +srcmd* srcmd_create(srcmdbuf* cmdbuf) { + if (cmdbuf->idx == cmdbuf->ncmds) { + gLog("Warning: number of render commands maxed out!"); + return NULL; + } + return &(cmdbuf->cmds[cmdbuf->idx++]); } diff --git a/src/vissim.cc b/src/vissim.cc index 740ff9c..b67df7a 100644 --- a/src/vissim.cc +++ b/src/vissim.cc @@ -56,9 +56,12 @@ static void opengl_error_callback( GLsizei length, const GLchar* message, const void* userParam) { - gLog ("OpenGL Error: %s type %0x%x, severity = 0x%x, message = %s", - ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), - type, severity, message ); + gLog( + "OpenGL Error: %s type %0x%x, severity = 0x%x, message = %s", + (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), + type, + severity, + message); } static void @@ -156,26 +159,31 @@ void DoRender() { // Render Output ImGui::Begin("Render Output"); - // Update the view + // Update the view const ImVec2 content_avail = ImGui::GetContentRegionAvail(); srview_set_size(gView, content_avail.x, content_avail.y); - simd4x4f view; - simd4x4f proj; - simd4x4f_identity (&view); - simd4x4f_identity (&proj); - srview_set_view(gView, view); - srview_set_view(gView, proj); + simd4x4f view; + simd4x4f proj; + simd4x4f_translation(&view, 0.1f, 0.1f, -0.1f); + simd4x4f_lookat( + &view, + simd4f_create(1.f, 1.f, 1.f, 1.f), + simd4f_create(0.f, 0.f, 0.f, 1.f), + simd4f_create(0.f, 1.f, 0.f, 1.f)); + simd4x4f_ortho(&proj, -5.0f, 5.0f, -5.0f, 5.0f, -5.0f, 5.0f); + srview_set_view(gView, view); + srview_set_proj(gView, proj); - // Populate render commands - srcmdbuf_clear(gRndrCmds); - srcmd* cmd = srcmd_create (gRndrCmds); - cmd->type = SRndrCmdTypeFrame; - simd4x4f_identity(&cmd->mat); - cmd->color = simd4f_create (1.f, 1.f, 1.f, 1.f); + // Populate render commands + srcmdbuf_clear(gRndrCmds); + srcmd* cmd = srcmd_create(gRndrCmds); + cmd->type = SRndrCmdTypeFrame; + simd4x4f_identity(&cmd->mat); + cmd->color = simd4f_create(1.f, 1.f, 1.f, 1.f); - // Perform the actual render + // Perform the actual render srndr_render(gRndr, gView, gRndrCmds); - GLuint view_texture; + GLuint view_texture; srview_get_output_texture(gView, &view_texture); ImGui::Image( @@ -267,6 +275,7 @@ int main(void) { gRndr = srndr_create(); gView = srview_create(); + gRndrCmds = srcmdbuf_create(1024); while (!glfwWindowShouldClose(gWindow)) { frame_counter++;