summary refs log tree commit diff
path: root/src/shader.c
diff options
context:
space:
mode:
authoriurii plugatarov <[email protected]>2024-08-10 14:22:45 +0200
committeriurii plugatarov <[email protected]>2024-08-10 14:22:45 +0200
commit90e85b2fe655a2643535b0f49d99836ac72e724c (patch)
tree66c0656984da7b2b8a6c06c4b0af764919e0e318 /src/shader.c
parent86eb1bfcf21819492e0ec55cd08127fa8a5c6769 (diff)
downloadogl-90e85b2fe655a2643535b0f49d99836ac72e724c.tar.gz
custom shader loader
Diffstat (limited to '')
-rw-r--r--src/shader.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/shader.c b/src/shader.c
new file mode 100644
index 0000000..7e1b58f
--- /dev/null
+++ b/src/shader.c
@@ -0,0 +1,121 @@
+#include "shader.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *read_file(const char *file_path) {
+  FILE *file = fopen(file_path, "r");
+  if (!file) {
+    printf("Failed to open file: %s\n", file_path);
+    return NULL;
+  }
+
+  fseek(file, 0, SEEK_END);
+  long file_size = ftell(file);
+  fseek(file, 0, SEEK_SET);
+
+  char *buffer = (char *)malloc(file_size + 1);
+  if (!buffer) {
+    printf("Failed to allocate memory for file: %s\n", file_path);
+    fclose(file);
+    return NULL;
+  }
+
+  fread(buffer, 1, file_size, file);
+  buffer[file_size] = '\0';
+
+  fclose(file);
+  return buffer;
+}
+
+static unsigned int compile_shader(const char *source, GLenum shader_type) {
+  unsigned int shader = glCreateShader(shader_type);
+  glShaderSource(shader, 1, &source, NULL);
+  glCompileShader(shader);
+
+  int success;
+  glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+  if (!success) {
+    char info_log[512];
+    glGetShaderInfoLog(shader, 512, NULL, info_log);
+    printf("Shader compilation failed: %s\n", info_log);
+    return 0;
+  }
+
+  return shader;
+}
+
+Shader *shader_create(const char *vertex_path, const char *fragment_path) {
+  Shader *shader = (Shader *)malloc(sizeof(Shader));
+  if (!shader) {
+    printf("Failed to allocate memory for shader\n");
+    return NULL;
+  }
+
+  char *vertex_source = read_file(vertex_path);
+  char *fragment_source = read_file(fragment_path);
+
+  if (!vertex_source || !fragment_source) {
+    free(shader);
+    free(vertex_source);
+    free(fragment_source);
+    return NULL;
+  }
+
+  unsigned int vertex_shader = compile_shader(vertex_source, GL_VERTEX_SHADER);
+  unsigned int fragment_shader =
+      compile_shader(fragment_source, GL_FRAGMENT_SHADER);
+
+  free(vertex_source);
+  free(fragment_source);
+
+  if (!vertex_shader || !fragment_shader) {
+    free(shader);
+    return NULL;
+  }
+
+  shader->program = glCreateProgram();
+  glAttachShader(shader->program, vertex_shader);
+  glAttachShader(shader->program, fragment_shader);
+  glLinkProgram(shader->program);
+
+  int success;
+  glGetProgramiv(shader->program, GL_LINK_STATUS, &success);
+  if (!success) {
+    char info_log[512];
+    glGetProgramInfoLog(shader->program, 512, NULL, info_log);
+    printf("Shader program linking failed: %s\n", info_log);
+    free(shader);
+    return NULL;
+  }
+
+  glDeleteShader(vertex_shader);
+  glDeleteShader(fragment_shader);
+
+  return shader;
+}
+
+void shader_use(Shader *shader) { glUseProgram(shader->program); }
+
+void shader_delete(Shader *shader) {
+  glDeleteProgram(shader->program);
+  free(shader);
+}
+
+void shader_set_int(Shader *shader, const char *name, int value) {
+  glUniform1i(glGetUniformLocation(shader->program, name), value);
+}
+
+void shader_set_float(Shader *shader, const char *name, float value) {
+  glUniform1f(glGetUniformLocation(shader->program, name), value);
+}
+
+void shader_set_vec3(Shader *shader, const char *name, float x, float y,
+                     float z) {
+  glUniform3f(glGetUniformLocation(shader->program, name), x, y, z);
+}
+
+void shader_set_mat4(Shader *shader, const char *name, const float *value) {
+  glUniformMatrix4fv(glGetUniformLocation(shader->program, name), 1, GL_FALSE,
+                     value);
+}