1 /************************************************************************
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 ************************************************************************/
27 static shader_t
*shaders
= NULL
;
28 static shader_t
*active
= NULL
;
30 static GLuint
shader_load(file_t
*f
, GLenum type
)
38 s
= glCreateShader(type
);
39 glShaderSource(s
, 1, (const GLchar
**)&f
->data
,NULL
);
41 glGetShaderiv(s
,GL_COMPILE_STATUS
,&i
);
44 glGetShaderInfoLog(s
,512,&i
,buff
);
45 vlprintf(CN_WARN
, "Shader %s failed to compile: %s",f
->name
,buff
);
53 shader_t
*shader_create(char* name
)
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
)
72 s
= malloc(sizeof(shader_t
));
83 strncpy(s
->name
,name
,256);
91 s
->vert
= shader_load(vert
,GL_VERTEX_SHADER
);
93 s
->geom
= shader_load(geom
,GL_GEOMETRY_SHADER
);
95 s
->frag
= shader_load(frag
,GL_FRAGMENT_SHADER
);
97 if (!s
->vert
&& !s
->geom
&& !s
->frag
) {
108 s
->program
= glCreateProgram();
110 glAttachShader(s
->program
,s
->vert
);
112 glAttachShader(s
->program
,s
->geom
);
114 glAttachShader(s
->program
,s
->frag
);
115 glLinkProgram(s
->program
);
116 glGetProgramiv(s
->program
, GL_LINK_STATUS
, &i
);
118 glGetProgramInfoLog(s
->program
, 512, &i
, buff
);
119 vlprintf(CN_INFO
, "Shader failed to link: %s",buff
);
122 glValidateProgram(s
->program
);
131 shaders
= list_push(&shaders
,s
);
137 void shader_free(shader_t
*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
);
154 /* bind an attribute to a shader */
155 int shader_attribute(shader_t
*s
, int att
, char* name
)
160 glBindAttribLocation(s
->program
,att
,name
);
161 glLinkProgram(s
->program
);
162 glValidateProgram(s
->program
);
167 /* set a shader uniform value */
168 int shader_uniform_int(shader_t
*s
, char* name
, int value
)
176 var
= glGetUniformLocation(s
->program
,name
);
179 glUniform1i(var
,value
);
184 /* set a shader uniform value */
185 int shader_uniform_float(shader_t
*s
, char* name
, float value
)
193 var
= glGetUniformLocation(s
->program
,name
);
196 glUniform1f(var
,value
);
201 /* set a shader uniform value */
202 int shader_uniform_v2(shader_t
*s
, char* name
, v2_t
*value
)
210 var
= glGetUniformLocation(s
->program
,name
);
213 glUniform2f(var
,value
->x
,value
->y
);
218 /* set a shader uniform value */
219 int shader_uniform_v3(shader_t
*s
, char* name
, v3_t
*value
)
227 var
= glGetUniformLocation(s
->program
,name
);
230 glUniform3f(var
,value
->x
,value
->y
,value
->z
);
235 /* set a shader uniform value */
236 int shader_uniform_v4(shader_t
*s
, char* name
, v4_t
*value
)
244 var
= glGetUniformLocation(s
->program
,name
);
248 glUniform4f(var
,value
->x
,value
->y
,value
->z
,value
->w
);
253 /* set a shader uniform value */
254 int shader_uniform_colour(shader_t
*s
, char* name
, colour_t
*value
)
266 var
= glGetUniformLocation(s
->program
,name
);
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
);
280 /* set a shader uniform value */
281 int shader_uniform_matrix(shader_t
*s
, char* name
, matrix_t
*value
)
289 var
= glGetUniformLocation(s
->program
,name
);
293 glUniformMatrix4fv(var
,1,GL_FALSE
,value
->data
);
298 /* bind all 3 uniforms for a light */
299 int shader_uniform_light(shader_t
*s
, int slot
, light_t
*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
);
324 int shader_enable(shader_t
*s
)
330 shader_disable(active
);
332 glUseProgram(s
->program
);
340 /* stop using a shader */
341 int shader_disable(shader_t
*s
)
343 if (!s
|| !s
->active
)