summaryrefslogtreecommitdiff
path: root/src/gl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gl.c')
-rw-r--r--src/gl.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/gl.c b/src/gl.c
new file mode 100644
index 0000000..9dce5e5
--- /dev/null
+++ b/src/gl.c
@@ -0,0 +1,281 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glad/gl.h>
+
+#include <daw/types.h>
+#include <daw/logging.h>
+
+#include <daw/rendering.h>
+#include <daw/platform.h>
+#include <daw/daw.h>
+
+extern Instance* GLOBAL_PLATFORM;
+
+const char* ShaderType_str[] = {
+ [Shader_Error] = "Shader_Error",
+ [Shader_Program] = "Shader_Program",
+ [Shader_Vertex] = "Shader_Vertex",
+ [Shader_Tessellation] = "Shader_Tessellation",
+ [Shader_Geometry] = "Shader_Geometry",
+ [Shader_Fragment] = "Shader_Fragment",
+ [Shader_Compute] = "Shader_Compute",
+};
+
+Shader compile_shader(const char* file_path, const ShaderType shader_type) {
+ u32 shaderID = 0;
+ GLenum shadertype = GL_INVALID_ENUM;
+
+ i32 Result = GL_FALSE;
+ i32 infolog_len;
+
+ char* source = NULL;
+ FILE* file = NULL;
+
+ const GladGLContext* gl = GLOBAL_PLATFORM->window->context;
+
+ if (file_path == NULL) {
+ WARN("Empty path to shader");
+ return (Shader){.program = 0, .type = Shader_Error};
+ }
+
+ switch (shader_type) {
+ case Shader_Vertex:
+ shadertype = GL_VERTEX_SHADER;
+ break;
+ case Shader_Fragment:
+ shadertype = GL_FRAGMENT_SHADER;
+ break;
+ default: break;
+ }
+
+ file = fopen(file_path, "r");
+
+ shaderID = gl->CreateShader(shadertype);
+ LOG("CREATED SHADER ID %d", shaderID);
+
+ if(file != NULL) {
+ const usize size = f_get_sz(file);
+
+ source = calloc((usize)size + 1, sizeof(char));
+
+ // Assume the whole file is successfully read
+ fread(source, sizeof(char), (usize)size, file);
+
+ fclose(file);
+ } else {
+ ERROR("Cannot open \"" TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET"\".", file_path);
+ return (Shader){.program = 0, .type = Shader_Error};
+ }
+
+ // Compile shader
+ INFO("Compiling shader \"" TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET"\".", file_path);
+ char const* src_ptr = source;
+ gl->ShaderSource(shaderID, 1, &src_ptr , NULL);
+ gl->CompileShader(shaderID);
+
+ // Check shader
+ gl->GetShaderiv(shaderID, GL_COMPILE_STATUS, &Result);
+ gl->GetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &infolog_len);
+ if ( infolog_len > 0 ) {
+ char* msg = calloc((usize)infolog_len + 1, sizeof(char));
+ gl->GetShaderInfoLog(shaderID, infolog_len, NULL, msg);
+ ERROR("Failed to compile shader: " TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET, msg);
+ free(msg);
+ }
+
+ free(source);
+
+ return (Shader){.program = shaderID, .type = shader_type};
+}
+
+
+// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
+u32 load_shaders(
+ const GladGLContext* gl,
+ const char* vertex_file_path,
+ const char* fragment_file_path) {
+
+ i32 Result = GL_FALSE;
+ i32 infolog_len;
+
+ // Create the shaders
+ const Shader vertexShader = compile_shader(vertex_file_path, Shader_Vertex);
+ const Shader fragmentShader = compile_shader(fragment_file_path, Shader_Fragment);
+
+ // Link the program
+ INFO("Linking program");
+ u32 ProgramID = gl->CreateProgram();
+
+ if (vertex_file_path != NULL) gl->AttachShader(ProgramID, vertexShader.program);
+ if (fragment_file_path != NULL) gl->AttachShader(ProgramID, fragmentShader.program);
+
+ gl->LinkProgram(ProgramID);
+
+ // Check the program
+ gl->GetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
+ gl->GetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &infolog_len);
+ if ( infolog_len > 0 ){
+ char* msg = calloc((usize)infolog_len + 1, sizeof(char));
+ gl->GetShaderInfoLog(ProgramID, infolog_len, NULL, msg);
+ ERROR("Compiling shader: " TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET, msg);
+ free(msg);
+ }
+
+ gl->DetachShader(ProgramID, vertexShader.program);
+ gl->DetachShader(ProgramID, fragmentShader.program);
+
+ //gl->DeleteShader(vertexShader.program);
+ //gl->DeleteShader(fragmentShader.program);
+
+ return ProgramID;
+}
+
+/* Returns a shader program */
+Shader compose_shader(Shader *shaders, usize shaders_len) {
+ const GladGLContext* gl = GLOBAL_PLATFORM->window->context;
+ i32 Result = GL_FALSE;
+
+ if (shaders_len == 0) {
+ ERROR("No shaders provided!");
+ return (Shader){.program = 0, .type = Shader_Error};
+ }
+
+ u32 prog = gl->CreateProgram();
+
+ if (prog == 0) {
+ ERROR("Failed to create program!");
+ return (Shader){.program = 0, .type = Shader_Error};
+ }
+
+ for (usize i = 0; i < shaders_len; i++) {
+ gl->AttachShader(prog, shaders[i].program);
+ INFO("Attaching shader %d to %d", shaders[i].program, prog);
+ }
+
+ gl->LinkProgram(prog);
+
+ // Check the program
+ gl->GetProgramiv(prog, GL_LINK_STATUS, &Result);
+ if (Result != GL_TRUE) {
+ // Get the size of the log
+ i32 log_len = 0;
+ i32 msg_len = 0;
+ gl->GetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_len);
+ char* msg = calloc((usize)log_len + 1, sizeof(char));
+
+ // Copy the log message(s)
+ gl->GetProgramInfoLog(prog, log_len, &msg_len, msg);
+
+ ERROR("(Compose) Compiling shader:\n" TERM_COLOR_YELLOW "%s" TERM_COLOR_RESET "\n", msg);
+ free(msg);
+ }
+
+ for (usize i = 0; i < shaders_len; i++) {
+ gl->DetachShader(prog, shaders[i].program);
+ }
+
+ return (Shader){.program = prog, .type = Shader_Program};
+}
+
+/* Free up resources associated with `shader` */
+void shaders_delete(Shader* shader, usize shader_len) {
+ const GladGLContext* gl = GLOBAL_PLATFORM->window->context;
+
+ for (usize i = 0; i < shader_len; i++) {
+ gl->DeleteShader(shader[i].program);
+ }
+}
+
+GLenum ShaderBuffer_get_gl_access(u64 flags) {
+ const ShaderBufferFlag access = ShaderBuffer_get_access_type(flags);
+
+ switch(flags & 0b111) {
+ case ShaderBuffer_AccessFrequency_stream:
+ switch(access) {
+ case ShaderBuffer_AccessType_draw: return GL_STREAM_DRAW;
+ case ShaderBuffer_AccessType_read: return GL_STREAM_READ;
+ case ShaderBuffer_AccessType_copy: return GL_STREAM_COPY;
+ default: return GL_STREAM_DRAW;
+ }
+ case ShaderBuffer_AccessFrequency_static:
+ switch(access) {
+ case ShaderBuffer_AccessType_draw: return GL_STATIC_DRAW;
+ case ShaderBuffer_AccessType_read: return GL_STATIC_READ;
+ case ShaderBuffer_AccessType_copy: return GL_STATIC_COPY;
+ default: return GL_STATIC_DRAW;
+ }
+ case ShaderBuffer_AccessFrequency_dynamic:
+ switch(access) {
+ case ShaderBuffer_AccessType_draw: return GL_DYNAMIC_DRAW;
+ case ShaderBuffer_AccessType_read: return GL_DYNAMIC_READ;
+ case ShaderBuffer_AccessType_copy: return GL_DYNAMIC_COPY;
+ default: return GL_DYNAMIC_DRAW;
+ }
+ default: return GL_STATIC_DRAW;
+ }
+}
+
+RenderObject RenderObject_new(
+ Shader* shader,
+ u32 texture,
+ ShaderBuffer *restrict buffers, usize num_buffers) {
+
+ GladGLContext *gl = GLOBAL_PLATFORM->window->context;
+ RenderObject o;
+
+ gl->GenVertexArrays(1, &(o.vao));
+ gl->BindVertexArray(o.vao);
+
+ /* For each buffer in the shader, */
+ /* The shader should be generalied, */
+ for (usize i = 0; i < num_buffers; i++) {
+ const usize sz = buffers[i].size_elem * buffers[i].count;
+ const u32 b_gl_type = ShaderBuffer_get_gl_type(buffers[i].buffertype);
+
+ gl->GenBuffers(1, &(buffers[i].buffername));
+ gl->BindBuffer(b_gl_type, buffers[i].buffername);
+ gl->BufferData(b_gl_type, (isize)sz, buffers[i].data, ShaderBuffer_get_gl_accesstype(buffers[i].buffertype));
+ }
+
+ o.shader = *shader;
+ o.texture = texture;
+ o.buffer = buffers;
+ o.buffer_len = num_buffers;
+ o.mvp = gl->GetUniformLocation(o.shader.program, "MVP");
+
+ // It is very much a non-issue if we don't find the model view projection in
+ // the shader. In fact, it is removed from a shader program if it is not used.
+ // TODO: Add common uniforms, should be a list of strings (uniform name) &
+ // their locations (i32), such as
+ // * mouse coords,
+ // * time,
+ // * delta time,
+ // * modelviewprojection,
+ // * window size.
+ // These should be added to the RenderObject, if found.
+
+ // if (o.mvp == -1) {
+ // WARN("Unable to find \"MVP\" input in shader program");
+ //}
+
+ gl->BindVertexArray(0);
+
+
+ return o;
+}
+
+ShaderType guess_shadertype_from_filename(const char *restrict fname) {
+ const usize path_len = strlen(fname);
+
+ if (path_len <= 4) {
+ ERROR("Unable to determine shader type from suffix! (%s)", fname);
+ return Shader_Error;
+ }
+
+ if (!strncmp(".vert", &fname[path_len - 5], 5)) { return Shader_Vertex; }
+ if (!strncmp(".frag", &fname[path_len - 5], 5)) { return Shader_Fragment; }
+
+ return Shader_Error;
+}