summaryrefslogtreecommitdiff
path: root/src/shader.c
blob: 207ce30d19f678b43aafcbe2abe3a11269a6325b (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
#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 number) {
  honey_shader_use(shader);
  unsigned int int_location = glGetUniformLocation(shader, int_name);
  glUniform1i(int_location, number);
}

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

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

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