summary refs log tree commit diff
path: root/src/shader.c
blob: 7e1b58f622d41ddef904799efdab9c4e352cdcf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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);
}