]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_shader_utils.cpp
Initial vogl checkin
[vogl] / src / voglcommon / vogl_shader_utils.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 // File: vogl_shader_utils.cpp
27 #include "vogl_shader_utils.h"
28
29 GLuint vogl_create_program(const char *pVertex_shader_source, const char *pFragment_shader_source)
30 {
31     GLuint program = 0, vert_shader = 0, frag_shader = 0;
32     GLint status = 0;
33     GLchar msg[4096];
34
35     vert_shader = GL_ENTRYPOINT(glCreateShader)(GL_VERTEX_SHADER);
36     VOGL_CHECK_GL_ERROR;
37
38     frag_shader = GL_ENTRYPOINT(glCreateShader)(GL_FRAGMENT_SHADER);
39     VOGL_CHECK_GL_ERROR;
40
41     if ((!vert_shader) || (!frag_shader))
42         goto failure;
43
44     // Compile vertex shader
45     GL_ENTRYPOINT(glShaderSource)(vert_shader, 1, (GLchar * const*)(&pVertex_shader_source), NULL);
46     if (vogl_check_gl_error())
47         goto failure;
48
49     GL_ENTRYPOINT(glCompileShader)(vert_shader);
50     if (vogl_check_gl_error())
51         goto failure;
52
53     GL_ENTRYPOINT(glGetShaderiv)(vert_shader, GL_COMPILE_STATUS, &status);
54     if ((vogl_check_gl_error()) || (status == GL_FALSE))
55     {
56         GL_ENTRYPOINT(glGetShaderInfoLog)(vert_shader, sizeof(msg), NULL, msg);
57         VOGL_CHECK_GL_ERROR;
58         vogl_error_printf("%s: Error compiling vertex shader:\n%s\n", VOGL_FUNCTION_NAME, msg);
59
60         goto failure;
61     }
62
63     // Compile fragment shader
64     GL_ENTRYPOINT(glShaderSource)(frag_shader, 1, (GLchar * const*)(&pFragment_shader_source), NULL);
65     if (vogl_check_gl_error())
66         goto failure;
67
68     GL_ENTRYPOINT(glCompileShader)(frag_shader);
69     if (vogl_check_gl_error())
70         goto failure;
71
72     GL_ENTRYPOINT(glGetShaderiv)(frag_shader, GL_COMPILE_STATUS, &status);
73     if ((vogl_check_gl_error()) || (status == GL_FALSE))
74     {
75         GL_ENTRYPOINT(glGetShaderInfoLog)(frag_shader, sizeof(msg), NULL, msg);
76         VOGL_CHECK_GL_ERROR;
77         vogl_error_printf("%s: Error compiling fragment shader:\n%s\n", VOGL_FUNCTION_NAME, msg);
78
79         goto failure;
80     }
81
82     // Create and link program
83     program = GL_ENTRYPOINT(glCreateProgram)();
84     if (vogl_check_gl_error())
85         goto failure;
86
87     GL_ENTRYPOINT(glAttachShader)(program, vert_shader);
88     if (vogl_check_gl_error())
89         goto failure;
90
91     GL_ENTRYPOINT(glAttachShader)(program, frag_shader);
92     if (vogl_check_gl_error())
93         goto failure;
94
95     GL_ENTRYPOINT(glLinkProgram)(program);
96     if (vogl_check_gl_error())
97         goto failure;
98
99     GL_ENTRYPOINT(glDeleteShader)(vert_shader);
100     VOGL_CHECK_GL_ERROR;
101     vert_shader = 0;
102
103     GL_ENTRYPOINT(glDeleteShader)(frag_shader);
104     VOGL_CHECK_GL_ERROR;
105     frag_shader = 0;
106
107     GL_ENTRYPOINT(glGetProgramiv)(program, GL_LINK_STATUS, &status);
108     if ((vogl_check_gl_error()) || (status == GL_FALSE))
109     {
110         GL_ENTRYPOINT(glGetProgramInfoLog)(program, sizeof(msg), NULL, msg);
111         VOGL_CHECK_GL_ERROR;
112         vogl_error_printf("%s: Error linking program:\n%s\n", VOGL_FUNCTION_NAME, msg);
113
114         goto failure;
115     }
116
117     return program;
118
119 failure:
120     if (vert_shader)
121     {
122         GL_ENTRYPOINT(glDeleteShader)(vert_shader);
123         VOGL_CHECK_GL_ERROR;
124     }
125
126     if (frag_shader)
127     {
128         GL_ENTRYPOINT(glDeleteShader)(frag_shader);
129         VOGL_CHECK_GL_ERROR;
130     }
131
132     if (program)
133     {
134         GL_ENTRYPOINT(glDeleteProgram)(program);
135         VOGL_CHECK_GL_ERROR;
136     }
137
138     vogl_error_printf("%s: Failed creating program!\n", VOGL_FUNCTION_NAME);
139
140     VOGL_CHECK_GL_ERROR;
141     return 0;
142 }
143
144 vogl_simple_gl_program::vogl_simple_gl_program() :
145     m_program(0)
146 {
147 }
148
149 vogl_simple_gl_program::~vogl_simple_gl_program()
150 {
151     deinit();
152 }
153
154 void vogl_simple_gl_program::deinit()
155 {
156     if (m_program)
157     {
158         GL_ENTRYPOINT(glDeleteProgram)(m_program);
159         VOGL_CHECK_GL_ERROR;
160
161         m_program = 0;
162     }
163 }
164
165 bool vogl_simple_gl_program::init(const char *pVertex_shader, const char *pFragment_shader)
166 {
167     deinit();
168
169     m_program = vogl_create_program(pVertex_shader, pFragment_shader);
170
171     return m_program != 0;
172 }
173
174 GLint vogl_simple_gl_program::get_uniform_location(const char *pName) const
175 {
176     if (!m_program)
177     {
178         VOGL_ASSERT_ALWAYS;
179         return -1;
180     }
181
182     return GL_ENTRYPOINT(glGetUniformLocation)(m_program, reinterpret_cast<const GLchar *>(pName));
183 }
184
185 bool vogl_simple_gl_program::has_uniform(const char *pName) const
186 {
187     return get_uniform_location(pName) != -1;
188 }
189
190 void vogl_simple_gl_program::set_uniform(const char *pName, int s)
191 {
192     if (!m_program)
193     {
194         VOGL_ASSERT_ALWAYS;
195         return;
196     }
197
198     vogl_scoped_program_binder prog_binder(m_program);
199
200     GL_ENTRYPOINT(glUniform1i)(get_uniform_location(pName), s);
201     VOGL_CHECK_GL_ERROR;
202 }
203
204 void vogl_simple_gl_program::set_uniform(const char *pName, uint s)
205 {
206     if (!m_program)
207     {
208         VOGL_ASSERT_ALWAYS;
209         return;
210     }
211
212     vogl_scoped_program_binder prog_binder(m_program);
213
214     GL_ENTRYPOINT(glUniform1ui)(get_uniform_location(pName), s);
215     VOGL_CHECK_GL_ERROR;
216 }
217
218 void vogl_simple_gl_program::set_uniform(const char *pName, float s)
219 {
220     if (!m_program)
221     {
222         VOGL_ASSERT_ALWAYS;
223         return;
224     }
225
226     vogl_scoped_program_binder prog_binder(m_program);
227
228     GL_ENTRYPOINT(glUniform1f)(get_uniform_location(pName), s);
229     VOGL_CHECK_GL_ERROR;
230 }
231
232 void vogl_simple_gl_program::set_uniform(const char *pName, const vec2I &v)
233 {
234     if (!m_program)
235     {
236         VOGL_ASSERT_ALWAYS;
237         return;
238     }
239
240     vogl_scoped_program_binder prog_binder(m_program);
241
242     GL_ENTRYPOINT(glUniform2i)(get_uniform_location(pName), v[0], v[1]);
243     VOGL_CHECK_GL_ERROR;
244 }
245
246 void vogl_simple_gl_program::set_uniform(const char *pName, const vec2F &v)
247 {
248     if (!m_program)
249     {
250         VOGL_ASSERT_ALWAYS;
251         return;
252     }
253
254     vogl_scoped_program_binder prog_binder(m_program);
255
256     GL_ENTRYPOINT(glUniform2f)(get_uniform_location(pName), v[0], v[1]);
257     VOGL_CHECK_GL_ERROR;
258 }
259
260 void vogl_simple_gl_program::set_uniform(const char *pName, const vec3I &v)
261 {
262     if (!m_program)
263     {
264         VOGL_ASSERT_ALWAYS;
265         return;
266     }
267
268     vogl_scoped_program_binder prog_binder(m_program);
269
270     GL_ENTRYPOINT(glUniform3i)(get_uniform_location(pName), v[0], v[1], v[2]);
271     VOGL_CHECK_GL_ERROR;
272 }
273
274 void vogl_simple_gl_program::set_uniform(const char *pName, const vec3F &v)
275 {
276     if (!m_program)
277     {
278         VOGL_ASSERT_ALWAYS;
279         return;
280     }
281
282     vogl_scoped_program_binder prog_binder(m_program);
283
284     GL_ENTRYPOINT(glUniform3f)(get_uniform_location(pName), v[0], v[1], v[2]);
285     VOGL_CHECK_GL_ERROR;
286 }
287
288 void vogl_simple_gl_program::set_uniform(const char *pName, const vec4I &v)
289 {
290     if (!m_program)
291     {
292         VOGL_ASSERT_ALWAYS;
293         return;
294     }
295
296     vogl_scoped_program_binder prog_binder(m_program);
297
298     GL_ENTRYPOINT(glUniform4i)(get_uniform_location(pName), v[0], v[1], v[2], v[3]);
299     VOGL_CHECK_GL_ERROR;
300 }
301
302 void vogl_simple_gl_program::set_uniform(const char *pName, const vec4F &v)
303 {
304     if (!m_program)
305     {
306         VOGL_ASSERT_ALWAYS;
307         return;
308     }
309
310     vogl_scoped_program_binder prog_binder(m_program);
311
312     GL_ENTRYPOINT(glUniform4f)(get_uniform_location(pName), v[0], v[1], v[2], v[3]);
313     VOGL_CHECK_GL_ERROR;
314 }
315
316 void vogl_simple_gl_program::set_uniform(const char *pName, const matrix33F &m, bool transpose)
317 {
318     if (!m_program)
319     {
320         VOGL_ASSERT_ALWAYS;
321         return;
322     }
323
324     vogl_scoped_program_binder prog_binder(m_program);
325
326     GL_ENTRYPOINT(glUniformMatrix3fv)(get_uniform_location(pName), 1, transpose, m.get_ptr());
327     VOGL_CHECK_GL_ERROR;
328 }
329
330 void vogl_simple_gl_program::set_uniform(const char *pName, const matrix44F &m, bool transpose)
331 {
332     if (!m_program)
333     {
334         VOGL_ASSERT_ALWAYS;
335         return;
336     }
337
338     vogl_scoped_program_binder prog_binder(m_program);
339
340     GL_ENTRYPOINT(glUniformMatrix4fv)(get_uniform_location(pName), 1, transpose, m.get_ptr());
341     VOGL_CHECK_GL_ERROR;
342 }
343