shader.c (3548B)
1 // Shader.c provides utilities for shader management. 2 // GLFW and GLAD must be initialized before any functions can be used. 3 #include <errno.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <glad/glad.h> 9 #include <GLFW/glfw3.h> 10 11 #include "main.h" 12 #include "err.h" 13 14 char * 15 readfile(const char *file) 16 { 17 FILE *f = fopen(file, "r"); 18 if (f == NULL) { 19 snprintf(errstr, sizeof(errstr), "fopen: errno = %d", errno); 20 return NULL; 21 } 22 23 size_t bufsize = 128; 24 size_t bytesRead = 0; 25 char *c; 26 c = (char *)malloc(bufsize); 27 if (c == NULL) { 28 snprintf(errstr, sizeof(errstr), 29 "allocate memory: errno = %d", errno); 30 return NULL; 31 } 32 33 for (;;) { 34 size_t read = fread(&c[bytesRead], sizeof(c[0]), 35 bufsize-bytesRead, f); 36 bytesRead += read; 37 if (read < bufsize - bytesRead) { 38 break; 39 } 40 bufsize *= 2; // TODO: check overflow. 41 char* newc = (char *)realloc(c, bufsize); 42 if (newc == NULL) { 43 snprintf(errstr, sizeof(errstr), 44 "allocate memory: errno = %d", errno); 45 free(c); 46 return NULL; 47 } 48 c = newc; 49 } 50 if (!feof(f) || ferror(f)) { 51 snprintf(errstr, sizeof(errstr), 52 "read from file %s: errno = %d", file, errno); 53 free(c); 54 return NULL; 55 } 56 57 c[bytesRead] = '\0'; 58 return c; 59 } 60 61 Shader * 62 ShaderInit(const char *vs, const char *fs) 63 { 64 char *vertexShaderSource = readfile(vs); 65 if (vertexShaderSource == NULL) { 66 char *olderr = strdup(errstr); 67 snprintf(errstr, sizeof(errstr), 68 "read vertex shader: %s", olderr); 69 return NULL; 70 } 71 char *fragmentShaderSource = readfile(fs); 72 if (vertexShaderSource == NULL) { 73 char *olderr = strdup(errstr); 74 snprintf(errstr, sizeof(errstr), 75 "read fragment shader: %s", olderr); 76 return NULL; 77 } 78 79 unsigned int vertexShader; 80 int success; 81 char log[512]; 82 vertexShader = glCreateShader(GL_VERTEX_SHADER); 83 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); 84 glCompileShader(vertexShader); 85 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 86 if (!success) { 87 glGetShaderInfoLog(vertexShader, sizeof(log), NULL, log); 88 snprintf(errstr, sizeof(errstr), 89 "compile vertex shader: %s", log); 90 return NULL; 91 } 92 unsigned int fragmentShader; 93 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 94 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); 95 glCompileShader(fragmentShader); 96 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 97 if (!success) { 98 glGetShaderInfoLog(fragmentShader, sizeof(log), NULL, log); 99 snprintf(errstr, sizeof(errstr), 100 "compile fragment shader: %s", log); 101 return NULL; 102 } 103 unsigned int shaderProgram; 104 shaderProgram = glCreateProgram(); 105 glAttachShader(shaderProgram, vertexShader); 106 glAttachShader(shaderProgram, fragmentShader); 107 glLinkProgram(shaderProgram); 108 glGetShaderiv(shaderProgram, GL_COMPILE_STATUS, &success); 109 if (!success) { 110 glGetShaderInfoLog(shaderProgram, sizeof(log), NULL, log); 111 snprintf(errstr, sizeof(errstr), 112 "link shaders: %s", log); 113 return NULL; 114 } 115 116 free(vertexShaderSource); 117 free(fragmentShaderSource); 118 glDeleteShader(vertexShader); 119 glDeleteShader(fragmentShader); 120 121 Shader *shader = (Shader *) malloc(sizeof(Shader)); 122 shader->ID = shaderProgram; 123 return shader; 124 } 125 126 void 127 ShaderUse(Shader *s) 128 { 129 glUseProgram(s->ID); 130 } 131 132 void 133 ShaderDelete(Shader *s) 134 { 135 glDeleteProgram(s->ID); 136 } 137 138 void 139 ShaderSetFloat(Shader *s, const char *name, float value) 140 { 141 glUniform1f(glGetUniformLocation(s->ID, name), value); 142 } 143 144 void 145 ShaderSetMat4(Shader *s, const char *name, float *mat) 146 { 147 glUniformMatrix4fv(glGetUniformLocation(s->ID, name), 1, 148 GL_FALSE, mat); 149 }