From 21924d5e08814cc9028dc3866d8b97d8422807f4 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 26 Jan 2021 09:25:04 +0100 Subject: Add triangle rendering w/ shader recompilation --- Makefile | 3 ++ shaders/triangle.frag | 5 +++ shaders/triangle.vert | 5 +++ src/app.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++---- src/app.h | 4 ++ 5 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 shaders/triangle.frag create mode 100644 shaders/triangle.vert diff --git a/Makefile b/Makefile index e7770ac..d1d5630 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,13 @@ # Source code location and files to watch for changes. SRC_DIR := src +SHADERS_DIR := shaders SRC_MAIN := $(SRC_DIR)/main.c SRC_APP := $(SRC_DIR)/app.c WATCH_SRC := $(wildcard $(SRC_DIR)/*.c) WATCH_SRC += $(wildcard $(SRC_DIR)/*.h) +WATCH_SRC += $(wildcard $(SHADERS_DIR)/*.vert) +WATCH_SRC += $(wildcard $(SHADERS_DIR)/*.frag) # Output library names and executables. BIN_NAME := app diff --git a/shaders/triangle.frag b/shaders/triangle.frag new file mode 100644 index 0000000..e8bde66 --- /dev/null +++ b/shaders/triangle.frag @@ -0,0 +1,5 @@ +#version 330 core +out vec4 frag_col; +void main() { + frag_col = vec4(0.8f, 0.8f, 0.8f, 1.0f); +} diff --git a/shaders/triangle.vert b/shaders/triangle.vert new file mode 100644 index 0000000..d5168a8 --- /dev/null +++ b/shaders/triangle.vert @@ -0,0 +1,5 @@ +#version 330 core +layout (location = 0) in vec3 vertex; +void main() { + gl_Position = vec4(vertex.x, vertex.y, vertex.z, 1.0); +} diff --git a/src/app.c b/src/app.c index 99f5cff..08ca7f2 100644 --- a/src/app.c +++ b/src/app.c @@ -1,6 +1,62 @@ #include "app.h" #include "platform.h" +bool +compile_shaders(const char *vert, const char *frag, u32 *handle, + PlatformAPI platform) { + int success = 0; + char memory[MB(1)] = {0}; // Memory for reading shader files + + // Initialize shader handles. + u32 vert_handle = glCreateShader(GL_VERTEX_SHADER); + u32 frag_handle = glCreateShader(GL_FRAGMENT_SHADER); + + // Vertex shader. + { + platform.read_file(vert, memory); + const char * source = memory; + glShaderSource(vert_handle, 1, &source, NULL); + glCompileShader(vert_handle); + glGetShaderiv(vert_handle, GL_COMPILE_STATUS, &success); + if (!success) { + glDeleteShader(vert_handle); + glDeleteShader(frag_handle); + return false; + } + } + + // Fragment shader. + { + platform.read_file(frag, memory); + const char * source = memory; + glShaderSource(frag_handle, 1, &source, NULL); + glCompileShader(frag_handle); + glGetShaderiv(frag_handle, GL_COMPILE_STATUS, &success); + if (!success) { + glDeleteShader(vert_handle); + glDeleteShader(frag_handle); + return false; + } + } + + // Program linkage. + *handle = glCreateProgram(); + glAttachShader(*handle, vert_handle); + glAttachShader(*handle, frag_handle); + glLinkProgram(*handle); + glGetProgramiv(*handle, GL_LINK_STATUS, &success); + if(!success) { + glDeleteProgram(*handle); + glDeleteShader(vert_handle); + glDeleteShader(frag_handle); + return false; + } + glDeleteShader(vert_handle); + glDeleteShader(frag_handle); + + return true; +} + static inline bool app_init(AppState *state, PlatformAPI platform) { platform.log("INIT"); @@ -14,7 +70,7 @@ app_init(AppState *state, PlatformAPI platform) { glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - // // Initialize window. + // Initialize window. GLFWwindow* window = glfwCreateWindow(400, 300, "Hello MIC", NULL, NULL); if (window == NULL) { platform.log("ERROR: failed to create GLFW window"); @@ -33,8 +89,47 @@ app_init(AppState *state, PlatformAPI platform) { // Initialize viewport. glViewport(0, 0, 400, 300); + // Initialize vertex data. + state->vertices[0] = -0.5f; + state->vertices[1] = -0.5f; + state->vertices[2] = 0.0f; + state->vertices[3] = 0.5f; + state->vertices[4] = -0.5f; + state->vertices[5] = 0.0f; + state->vertices[6] = 0.0f; + state->vertices[7] = 0.5f; + state->vertices[8] = 0.0f; + + // Initialize Vertex Buffer Object (VBO) and Vertex Array Object (VAO). + u32 VBO; + glGenBuffers(1, &VBO); + u32 VAO; + glGenVertexArrays(1, &VAO); + + // Bind the VAO before any other binding. + glBindVertexArray(VAO); + + // Send vertex data to VBO. + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(state->vertices), state->vertices, + GL_STATIC_DRAW); + + // Set vertex attribute pointers. + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); + + // Compile shader program. + const char *vert = "shaders/triangle.vert"; + const char *frag = "shaders/triangle.frag"; + if (!compile_shaders(vert, frag, &state->shader_program, platform)) { + platform.log("WARNING: failed to compile shader program"); + } + // Initialize application state. state->window = window; + state->VBO = VBO; + state->VAO = VAO; + return true; } @@ -46,8 +141,12 @@ app_destroy(AppState *state, PlatformAPI platform) { static inline void app_reload(AppState *state, PlatformAPI platform) { - (void)state; // Unused parameter. platform.log("RELOAD"); + const char *vert = "shaders/triangle.vert"; + const char *frag = "shaders/triangle.frag"; + if (!compile_shaders(vert, frag, &state->shader_program, platform)) { + platform.log("WARNING: failed to compile shader program"); + } } static inline void @@ -58,13 +157,13 @@ app_unload(AppState *state, PlatformAPI platform) { static inline bool app_step(AppState *state, PlatformAPI platform) { - (void)platform; // Unused parameter. - if (glfwWindowShouldClose(state->window)) { - return false; - } + (void)platform; // Unused parameter - glClearColor(1.0f, 0.0f, 0.4f, 1.0f); + glClearColor(0.8f, 0.0f, 0.4f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(state->shader_program); + glBindVertexArray(state->VAO); + glDrawArrays(GL_TRIANGLES, 0, 3); glfwSwapBuffers(state->window); glfwPollEvents(); diff --git a/src/app.h b/src/app.h index 613360f..16dc8a5 100644 --- a/src/app.h +++ b/src/app.h @@ -10,6 +10,10 @@ typedef struct AppState { // OpenGL GLFWwindow *window; + f32 vertices[12]; + u32 VBO; + u32 VAO; + u32 shader_program; } AppState; // Function pointers for the AppAPI. -- cgit v1.2.1