and now we actually can render stuff, partially
[voxelands-alt.git] / src / graphics / shader.c
blobcccb7421f06ef38b20f6c11cbde42ee65a6c17fb
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;
29 #ifndef _HAVE_SHADER_TYPE
30 #define _HAVE_SHADER_TYPE
31 typedef struct shader_s {
32 struct shader_s *prev;
33 struct shader_s *next;
34 char name[256];
35 GLuint vert;
36 GLuint frag;
37 uint8_t active;
38 } shader_t;
39 #endif
41 shader_t *shader_create(char* name)
43 char buff[512];
44 file_t *vert;
45 file_t *frag;
46 shader_t *s;
47 GLint i;
49 if (snprintf(buff,512,"%s_vertex.glsl",name) >= 512)
50 return NULL;
51 vert = file_load("shader",buff);
52 if (!vert)
53 return NULL;
54 if (snprintf(buff,512,"%s_fragment.glsl",name) >= 512) {
55 file_free(vert);
56 return NULL;
58 frag = file_load("shader",buff);
59 if (!frag) {
60 file_free(vert);
61 return NULL;
64 s = malloc(sizeof(shader_t));
65 if (!s) {
66 file_free(vert);
67 file_free(frag);
68 return NULL;
71 strncpy(s->name,name,256);
72 s->active = 0;
73 s->program = 0;
74 s->vert = glCreateShader(GL_VERTEX_SHADER);
75 if (!s->vert) {
76 file_free(vert);
77 file_free(frag);
78 free(s);
79 return NULL;
81 s->frag = glCreateShader(GL_FRAGMENT_SHADER);
82 if (!s->frag) {
83 file_free(vert);
84 file_free(frag);
85 free(s);
86 return NULL;
89 glShaderSource(s->vert, 1, (const GLchar**)&vert->data,NULL);
90 glShaderSource(s->frag, 1, (const GLchar**)&frag->data,NULL);
92 glCompileShader(s->vert);
93 glGetShaderiv(s->vert,GL_COMPILE_STATUS,&i);
94 if (i == GL_FALSE) {
95 glGetShaderInfoLog(s->vert,512,&i,buff);
96 vlprintf("Vertex Shader failed to compile: %s",buff);
97 file_free(vert);
98 file_free(frag);
99 free(s);
100 return NULL;
103 glCompileShader(s->frag);
104 glGetShaderiv(s->frag,GL_COMPILE_STATUS,&i);
105 if (i == GL_FALSE) {
106 glGetShaderInfoLog(s->frag,512,&i,buff);
107 vlprintf("Fragment Shader failed to compile: %s",buff);
108 file_free(vert);
109 file_free(frag);
110 free(s);
111 return NULL;
114 s->program = glCreateProgram();
115 glAttachShader(s->program,s->vert);
116 glAttachShader(s->program,s->frag);
117 glLinkProgram(s->program);
118 glValidateProgram(s->program);
120 file_free(vert);
121 file_free(frag);
123 shaders = list_push(&shaders,s);
125 return s;
128 /* free a shader */
129 void shader_free(shader_t *s)
131 if (!s)
132 return;
134 if (s->active)
135 shader_disable(s);
137 glDetachShader(s->program,s->vert);
138 glDetachShader(s->program,s->frag);
139 glDeleteShader(s->vert);
140 glDeleteShader(s->frag);
141 glDeleteProgram(s->program);
143 free(s);
146 /* bind an attribute to a shader */
147 int shader_attribute(shader_t *s, int att, char* name)
149 if (!s)
150 return 1;
152 glBindAttribLocation(s->program,att,name);
153 glLinkProgram(s->program);
154 glValidateProgram(s->program);
156 return 0;
159 /* set a shader uniform value */
160 int shader_uniform_int(shader_t *s, char* name, int value)
162 GLuint var;
163 if (!s)
164 return 1;
166 var = glGetUniformLocation(s->program,name);
167 glUniform1i(var,value);
169 return 0;
172 /* set a shader uniform value */
173 int shader_uniform_float(shader_t *s, char* name, float value)
175 GLuint var;
176 if (!s)
177 return 1;
179 var = glGetUniformLocation(s->program,name);
180 glUniform1f(var,value);
182 return 0;
185 /* set a shader uniform value */
186 int shader_uniform_v2(shader_t *s, char* name, v2_t *value)
188 GLuint var;
189 if (!s)
190 return 1;
192 var = glGetUniformLocation(s->program,name);
193 glUniform2f(var,value->x,value->y);
195 return 0;
198 /* set a shader uniform value */
199 int shader_uniform_v3(shader_t *s, char* name, v3_t *value)
201 GLuint var;
202 if (!s)
203 return 1;
205 var = glGetUniformLocation(s->program,name);
206 glUniform3f(var,value->x,value->y,value->z);
208 return 0;
211 /* set a shader uniform value */
212 int shader_uniform_matrix(shader_t *s, char* name, matrix_t *value)
214 GLuint var;
215 if (!s)
216 return 1;
218 var = glGetUniformLocation(s->program,name);
219 glUniformMatrix4fv(var,1,GL_FALSE,value->data);
221 return 0;
224 /* use a shader */
225 int shader_enable(shader_t *s)
227 if (!s || s->active)
228 return 1;
230 glUseProgram(s->program);
231 s->active = 1;
233 return 0;
236 /* stop using a shader */
237 int shader_disable(shader_t *s)
239 if (!s || !s->active)
240 return 1;
242 glUseProgram(0);
243 s->active = 0;
245 return 0;