summaryrefslogtreecommitdiff
path: root/src/shader.c
blob: e9d79a636c8e620e5e3c8ca43506c65b200e5331 (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
122
123
124
125
126
127
128
129
130
131
#include "include/shader.h"

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

static char* read_file(char* file_path) {
  FILE* f = fopen(file_path, "r");
  if (f == NULL) {
    return NULL;
  }

  fseek(f, 0, SEEK_END);
  long fsize = ftell(f);
  fseek(f, 0, SEEK_SET);

  char* file_string = malloc(fsize + 1);
  if (file_string == NULL) {
    return NULL;
  }
  fread(file_string, 1, fsize, f);
  fclose(f);

  file_string[fsize] = 0;

  return file_string;
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

enum honey_shader_result honey_shader_load(honey_shader* shader,
                                           char* vertex_shader_path,
                                           char* fragment_shader_path) {
  enum honey_shader_result result;

  /* load vertex shader code */
  char* vertex_shader_code = read_file(vertex_shader_path);

  /* load fragment shader code */
  char* fragment_shader_code = read_file(fragment_shader_path);

  /* compile shaders */
  int success;
  char error[512];

  int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertex_shader, 1, ((const char**)&vertex_shader_code), NULL);
  glCompileShader(vertex_shader);
  glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
  if (!success) {
    glGetShaderInfoLog(vertex_shader, 512, NULL, error);
    printf("Failed to compile vertex shader: %s\n", error);
    result = VERTEX_SHADER_FAILED;
    return result;
  }

  int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragment_shader, 1, ((const char**)&fragment_shader_code), NULL);
  glCompileShader(fragment_shader);
  glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
  if (!success) {
    glGetShaderInfoLog(fragment_shader, 512, NULL, error);
    printf("Failed to compile fragment shader: %s\n", error);
    result = FRAGMENT_SHADER_FAILED;
    return result;
  }

  /* link shaders */
  *shader = glCreateProgram();
  glAttachShader(*shader, vertex_shader);
  glAttachShader(*shader, fragment_shader);
  glLinkProgram(*shader);
  glGetShaderiv(*shader, GL_LINK_STATUS, &success);
  if (!success) {
    glGetProgramInfoLog(*shader, 512, NULL, error);
    printf("Failed to link shaders: %s\n", error);
    result = SHADER_LINK_FAILED;
    return result;
  }

  glDeleteShader(vertex_shader);
  glDeleteShader(fragment_shader);

  free(vertex_shader_code);
  free(fragment_shader_code);

  result = SHADER_OK;
  
  return result;
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

void honey_shader_set_int(honey_shader shader,
                          char* int_name,
                          int value) {
  honey_shader_use(shader);
  unsigned int int_location = glGetUniformLocation(shader, int_name);
  glUniform1i(int_location, value);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

void honey_shader_set_float(honey_shader shader,
                            char* float_name,
                            float value) {
  honey_shader_use(shader);
  unsigned int float_location = glGetUniformLocation(shader, float_name);
  glUniform1f(float_location, value);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

void honey_shader_set_vec3(honey_shader shader,
                           char* vector_name,
                           vec3 value) {
  honey_shader_use(shader);
  unsigned int vector_location = glGetUniformLocation(shader, vector_name);
  glUniform3fv(vector_location, 1, (float*) value);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

void honey_shader_set_mat4(honey_shader shader,
                           char* matrix_name,
                           mat4 value) {
  glUseProgram(shader);
  unsigned int matrix_location = glGetUniformLocation(shader, matrix_name);
  glUniformMatrix4fv(matrix_location, 1, GL_FALSE, (float*) value);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */