some meshgen and map rendering updates
[voxelands-alt.git] / src / graphics / shader.c
blobb8b97080ab4b3febff12e3ddd270f479fe3e33e5
1 /************************************************************************
2 * shader.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "common.h"
21 #include "graphics.h"
22 #include "file.h"
23 #include "list.h"
25 #include <string.h>
27 static shader_t *shaders = NULL;
28 static shader_t *active = NULL;
30 static GLuint shader_load(file_t *f, GLenum type)
32 GLint i;
33 GLuint s = 0;
35 if (!f)
36 return s;
38 s = glCreateShader(type);
39 glShaderSource(s, 1, (const GLchar**)&f->data,NULL);
40 glCompileShader(s);
41 glGetShaderiv(s,GL_COMPILE_STATUS,&i);
42 if (i == GL_FALSE) {
43 char buff[512];
44 glGetShaderInfoLog(s,512,&i,buff);
45 vlprintf(CN_WARN, "Shader %s failed to compile: %s",f->name,buff);
46 glDeleteShader(s);
47 s = 0;
50 return s;
53 shader_t *shader_create(char* name)
55 char buff[512];
56 file_t *vert;
57 file_t *geom;
58 file_t *frag;
59 shader_t *s;
60 GLint i;
62 if (snprintf(buff,512,"%s_vertex.glsl",name) < 512)
63 vert = file_load("shader",buff);
64 if (snprintf(buff,512,"%s_geometry.glsl",name) < 512)
65 geom = file_load("shader",buff);
66 if (snprintf(buff,512,"%s_fragment.glsl",name) < 512)
67 frag = file_load("shader",buff);
69 if (!vert && !geom && !frag)
70 return NULL;
72 s = malloc(sizeof(shader_t));
73 if (!s) {
74 if (vert)
75 file_free(vert);
76 if (geom)
77 file_free(geom);
78 if (frag)
79 file_free(frag);
80 return NULL;
83 strncpy(s->name,name,256);
84 s->active = 0;
85 s->program = 0;
86 s->vert = 0;
87 s->geom = 0;
88 s->frag = 0;
90 if (vert)
91 s->vert = shader_load(vert,GL_VERTEX_SHADER);
92 if (geom)
93 s->geom = shader_load(geom,GL_GEOMETRY_SHADER);
94 if (frag)
95 s->frag = shader_load(frag,GL_FRAGMENT_SHADER);
97 if (!s->vert && !s->geom && !s->frag) {
98 if (vert)
99 file_free(vert);
100 if (geom)
101 file_free(geom);
102 if (frag)
103 file_free(frag);
104 free(s);
105 return NULL;
108 s->program = glCreateProgram();
109 if (s->vert)
110 glAttachShader(s->program,s->vert);
111 if (s->geom)
112 glAttachShader(s->program,s->geom);
113 if (s->frag)
114 glAttachShader(s->program,s->frag);
115 glLinkProgram(s->program);
116 glGetProgramiv(s->program, GL_LINK_STATUS, &i);
117 if (i == GL_FALSE) {
118 glGetProgramInfoLog(s->program, 512, &i, buff);
119 vlprintf(CN_INFO, "Shader failed to link: %s",buff);
122 glValidateProgram(s->program);
124 if (vert)
125 file_free(vert);
126 if (geom)
127 file_free(geom);
128 if (frag)
129 file_free(frag);
131 shaders = list_push(&shaders,s);
133 return s;
136 /* free a shader */
137 void shader_free(shader_t *s)
139 if (!s)
140 return;
142 if (s->active)
143 shader_disable(s);
145 glDetachShader(s->program,s->vert);
146 glDetachShader(s->program,s->frag);
147 glDeleteShader(s->vert);
148 glDeleteShader(s->frag);
149 glDeleteProgram(s->program);
151 free(s);
154 /* bind an attribute to a shader */
155 int shader_attribute(shader_t *s, int att, char* name)
157 if (!s)
158 return 1;
160 glBindAttribLocation(s->program,att,name);
161 glLinkProgram(s->program);
162 glValidateProgram(s->program);
164 return 0;
167 /* set a shader uniform value */
168 int shader_uniform_int(shader_t *s, char* name, int value)
170 GLint var;
171 if (!s)
172 s = active;
173 if (!s)
174 return 1;
176 var = glGetUniformLocation(s->program,name);
177 if (var < 0)
178 return 1;
179 glUniform1i(var,value);
181 return 0;
184 /* set a shader uniform value */
185 int shader_uniform_float(shader_t *s, char* name, float value)
187 GLint var;
188 if (!s)
189 s = active;
190 if (!s)
191 return 1;
193 var = glGetUniformLocation(s->program,name);
194 if (var < 0)
195 return 1;
196 glUniform1f(var,value);
198 return 0;
201 /* set a shader uniform value */
202 int shader_uniform_v2(shader_t *s, char* name, v2_t *value)
204 GLint var;
205 if (!s)
206 s = active;
207 if (!s)
208 return 1;
210 var = glGetUniformLocation(s->program,name);
211 if (var < 0)
212 return 1;
213 glUniform2f(var,value->x,value->y);
215 return 0;
218 /* set a shader uniform value */
219 int shader_uniform_v3(shader_t *s, char* name, v3_t *value)
221 GLint var;
222 if (!s)
223 s = active;
224 if (!s)
225 return 1;
227 var = glGetUniformLocation(s->program,name);
228 if (var < 0)
229 return 1;
230 glUniform3f(var,value->x,value->y,value->z);
232 return 0;
235 /* set a shader uniform value */
236 int shader_uniform_v4(shader_t *s, char* name, v4_t *value)
238 GLint var;
239 if (!s)
240 s = active;
241 if (!s)
242 return 1;
244 var = glGetUniformLocation(s->program,name);
245 if (var < 0)
246 return 1;
248 glUniform4f(var,value->x,value->y,value->z,value->w);
250 return 0;
253 /* set a shader uniform value */
254 int shader_uniform_colour(shader_t *s, char* name, colour_t *value)
256 GLint var;
257 GLfloat r;
258 GLfloat g;
259 GLfloat b;
260 GLfloat a;
261 if (!s)
262 s = active;
263 if (!s)
264 return 1;
266 var = glGetUniformLocation(s->program,name);
267 if (var < 0)
268 return 1;
270 r = (float)value->r/255.0;
271 g = (float)value->g/255.0;
272 b = (float)value->b/255.0;
273 a = (float)value->a/255.0;
275 glUniform4f(var,r,g,b,a);
277 return 0;
280 /* set a shader uniform value */
281 int shader_uniform_matrix(shader_t *s, char* name, matrix_t *value)
283 GLint var;
284 if (!s)
285 s = active;
286 if (!s)
287 return 1;
289 var = glGetUniformLocation(s->program,name);
290 if (var < 0)
291 return 1;
293 glUniformMatrix4fv(var,1,GL_FALSE,value->data);
295 return 0;
298 /* bind all 3 uniforms for a light */
299 int shader_uniform_light(shader_t *s, int slot, light_t *light)
301 char buff[256];
303 if (!light) {
304 snprintf(buff,256,"light%d_active",slot);
305 return shader_uniform_int(s,buff,0);
308 snprintf(buff,256,"light%d_active",slot);
309 shader_uniform_int(s,buff,1);
311 snprintf(buff,256,"light%d_pos",slot);
312 shader_uniform_v3(s,buff,&light->pos);
314 snprintf(buff,256,"light%d_att",slot);
315 shader_uniform_v3(s,buff,&light->att);
317 snprintf(buff,256,"light%d_colour",slot);
318 shader_uniform_colour(s,buff,&light->colour);
320 return 0;
323 /* use a shader */
324 int shader_enable(shader_t *s)
326 if (!s || s->active)
327 return 1;
329 if (active)
330 shader_disable(active);
332 glUseProgram(s->program);
333 s->active = 1;
335 active = s;
337 return 0;
340 /* stop using a shader */
341 int shader_disable(shader_t *s)
343 if (!s || !s->active)
344 return 1;
346 active = NULL;
348 glUseProgram(0);
349 s->active = 0;
351 return 0;