Draw Engine: remove hard coded limit on array sizes
[blender.git] / source / blender / gpu / intern / gpu_basic_shader.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2013 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_basic_shader.c
29  *  \ingroup gpu
30  *
31  * GLSL shaders to replace fixed function OpenGL materials and lighting. These
32  * are deprecated in newer OpenGL versions and missing in OpenGL ES 2.0. Also,
33  * two sided lighting is no longer natively supported on NVidia cards which
34  * results in slow software fallback.
35  *
36  * Todo:
37  * - Replace glLight and glMaterial functions entirely with GLSL uniforms, to
38  *   make OpenGL ES 2.0 work.
39  * - Replace glTexCoord and glColor with generic attributes.
40  * - Optimize for case where fewer than 3 or 8 lights are used.
41  * - Optimize for case where specular is not used.
42  * - Optimize for case where no texture matrix is used.
43  */
44
45 #include "BLI_math.h"
46 #include "BLI_utildefines.h"
47
48 #include "GPU_basic_shader.h"
49 #include "GPU_glew.h"
50 #include "GPU_shader.h"
51
52 /* State */
53
54 static struct {
55         GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS];
56         bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS];
57
58         int bound_options;
59
60         int lights_enabled;
61         int lights_directional;
62         float line_width;
63         GLint viewport[4];
64 } GPU_MATERIAL_STATE;
65
66
67 /* Stipple patterns */
68 /* ******************************************** */
69 const GLubyte stipple_halftone[128] = {
70         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
71         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
72         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
73         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
74         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
75         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
76         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
77         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
78         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
79         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
80         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
81         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
82         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
83         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
84         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
85         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
86
87 const GLubyte stipple_quarttone[128] = {
88         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
89         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
90         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
91         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
92         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
93         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
94         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
95         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
96
97 const GLubyte stipple_diag_stripes_pos[128] = {
98         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
99         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
100         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
101         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
102         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
103         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
104         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
105         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
106         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
107         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
108         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
109         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
110         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
111         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
112         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
113         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
114
115 const GLubyte stipple_diag_stripes_neg[128] = {
116         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
117         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
118         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
119         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
120         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
121         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
122         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
123         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
124         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
125         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
126         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
127         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
128         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
129         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
130         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
131         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80};
132
133 const GLubyte stipple_checker_8px[128] = {
134         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
135         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
136         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
137         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
138         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
139         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
140         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
141         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
142
143 const GLubyte stipple_hexagon[128] = {
144         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
145         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
146         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
147         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
148         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
149         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
150         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
151         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
152         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
153         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
154         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
155         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
156         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
157         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
158         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
159         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
160 /* ********************************************* */
161
162 /* Init / exit */
163
164 void GPU_basic_shaders_init(void)
165 {
166         memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE));
167 }
168
169 void GPU_basic_shaders_exit(void)
170 {
171         int i;
172         
173         for (i = 0; i < GPU_SHADER_OPTION_COMBINATIONS; i++)
174                 if (GPU_MATERIAL_STATE.cached_shaders[i])
175                         GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]);
176 }
177
178 /* Shader lookup / create */
179
180 static bool solid_compatible_lighting(void)
181 {
182         int enabled = GPU_MATERIAL_STATE.lights_enabled;
183         int directional = GPU_MATERIAL_STATE.lights_directional;
184
185         /* more than 3 lights? */
186         if (enabled >= (1 << 3))
187                 return false;
188
189         /* all directional? */
190         return ((directional & enabled) == enabled);
191 }
192
193 #if 0
194 static int detect_options()
195 {
196         GLint two_sided;
197         int options = 0;
198
199         if (glIsEnabled(GL_TEXTURE_2D))
200                 options |= GPU_SHADER_TEXTURE_2D;
201         if (glIsEnabled(GL_TEXTURE_RECTANGLE))
202                 options |= GPU_SHADER_TEXTURE_RECT;
203         GPU_SHADER_TEXTURE_RECT
204         if (glIsEnabled(GL_COLOR_MATERIAL))
205                 options |= GPU_SHADER_USE_COLOR;
206
207         if (glIsEnabled(GL_LIGHTING))
208                 options |= GPU_SHADER_LIGHTING;
209
210         glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
211         if (two_sided == GL_TRUE)
212                 options |= GPU_SHADER_TWO_SIDED;
213         
214         return options;
215 }
216 #endif
217
218 static GPUShader *gpu_basic_shader(int options)
219 {
220         /* glsl code */
221         extern char datatoc_gpu_shader_basic_vert_glsl[];
222         extern char datatoc_gpu_shader_basic_frag_glsl[];
223         extern char datatoc_gpu_shader_basic_geom_glsl[];
224         char *geom_glsl = NULL;
225         GPUShader *shader;
226
227         /* detect if we can do faster lighting for solid draw mode */
228         if (options & GPU_SHADER_LIGHTING)
229                 if (solid_compatible_lighting())
230                         options |= GPU_SHADER_SOLID_LIGHTING;
231
232         /* cached shaders */
233         shader = GPU_MATERIAL_STATE.cached_shaders[options];
234
235         if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) {
236                 /* create shader if it doesn't exist yet */
237                 char defines[64 * GPU_SHADER_OPTIONS_NUM] = "";
238
239                 if (options & GPU_SHADER_USE_COLOR)
240                         strcat(defines, "#define USE_COLOR\n");
241                 if (options & GPU_SHADER_TWO_SIDED)
242                         strcat(defines, "#define USE_TWO_SIDED\n");
243                 if (options & (GPU_SHADER_TEXTURE_2D | GPU_SHADER_TEXTURE_RECT))
244                         strcat(defines, "#define USE_TEXTURE\n");
245                 if (options & GPU_SHADER_TEXTURE_RECT)
246                         strcat(defines, "#define USE_TEXTURE_RECTANGLE\n");
247                 if (options & GPU_SHADER_STIPPLE)
248                         strcat(defines, "#define USE_STIPPLE\n");
249                 if (options & GPU_SHADER_LINE) {
250                         strcat(defines, "#define DRAW_LINE\n");
251                         geom_glsl = datatoc_gpu_shader_basic_geom_glsl;
252                 }
253                 if (options & GPU_SHADER_FLAT_NORMAL)
254                         strcat(defines, "#define USE_FLAT_NORMAL\n");
255                 if (options & GPU_SHADER_SOLID_LIGHTING)
256                         strcat(defines, "#define USE_SOLID_LIGHTING\n");
257                 else if (options & GPU_SHADER_LIGHTING)
258                         strcat(defines, "#define USE_SCENE_LIGHTING\n");
259
260                 shader = GPU_shader_create(
261                         datatoc_gpu_shader_basic_vert_glsl,
262                         datatoc_gpu_shader_basic_frag_glsl,
263                         geom_glsl,
264                         NULL,
265                         defines);
266                 
267                 if (shader) {
268                         /* set texture map to first texture unit */
269                         if (options & (GPU_SHADER_TEXTURE_2D | GPU_SHADER_TEXTURE_RECT)) {
270                                 GPU_shader_bind(shader);
271                                 glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0);
272                                 GPU_shader_unbind();
273                         }
274
275                         GPU_MATERIAL_STATE.cached_shaders[options] = shader;
276                 }
277                 else
278                         GPU_MATERIAL_STATE.failed_shaders[options] = true;
279         }
280
281         return shader;
282 }
283
284 static void GPU_basic_shader_uniform_autoset(GPUShader *shader, int options)
285 {
286         if (options & GPU_SHADER_LINE) {
287                 glGetIntegerv(GL_VIEWPORT, &GPU_MATERIAL_STATE.viewport[0]);
288                 glUniform4iv(GPU_shader_get_uniform(shader, "viewport"), 1, &GPU_MATERIAL_STATE.viewport[0]);
289                 glUniform1f(GPU_shader_get_uniform(shader, "line_width"), GPU_MATERIAL_STATE.line_width);
290         }
291 }
292
293 /* Bind / unbind */
294
295 void GPU_basic_shader_bind(int options)
296 {
297         if (options) {
298                 GPUShader *shader = gpu_basic_shader(options);
299
300                 if (shader) {
301                         GPU_shader_bind(shader);
302                         GPU_basic_shader_uniform_autoset(shader, options);
303                 }
304         }
305         else {
306                 GPU_shader_unbind();
307         }
308
309         GPU_MATERIAL_STATE.bound_options = options;
310 }
311
312 void GPU_basic_shader_bind_enable(int options)
313 {
314         GPU_basic_shader_bind(GPU_MATERIAL_STATE.bound_options | options);
315 }
316
317 void GPU_basic_shader_bind_disable(int options)
318 {
319         GPU_basic_shader_bind(GPU_MATERIAL_STATE.bound_options & ~options);
320 }
321
322 int GPU_basic_shader_bound_options(void)
323 {
324         /* ideally this should disappear, anything that uses this is making fragile
325          * assumptions that the basic shader is bound and not another shader */
326         return GPU_MATERIAL_STATE.bound_options;
327 }
328
329 /* Material Colors */
330
331 void GPU_basic_shader_colors(
332         const float diffuse[3], const float specular[3],
333         int shininess, float alpha)
334 {
335         float gl_diffuse[4], gl_specular[4];
336
337         if (diffuse)
338                 copy_v3_v3(gl_diffuse, diffuse);
339         else
340                 zero_v3(gl_diffuse);
341         gl_diffuse[3] = alpha;
342
343         if (specular)
344                 copy_v3_v3(gl_specular, specular);
345         else
346                 zero_v3(gl_specular);
347         gl_specular[3] = 1.0f;
348
349         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
350         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
351         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
352 }
353
354 void GPU_basic_shader_light_set(int light_num, GPULightData *light)
355 {
356         int light_bit = (1 << light_num);
357
358         /* note that light position is affected by the current modelview matrix! */
359
360         GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
361         GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
362
363         if (light) {
364                 float position[4], diffuse[4], specular[4];
365
366                 glEnable(GL_LIGHT0 + light_num);
367
368                 /* position */
369                 if (light->type == GPU_LIGHT_SUN) {
370                         copy_v3_v3(position, light->direction);
371                         position[3] = 0.0f;
372                 }
373                 else {
374                         copy_v3_v3(position, light->position);
375                         position[3] = 1.0f;
376                 }
377                 glLightfv(GL_LIGHT0 + light_num, GL_POSITION, position);
378
379                 /* energy */
380                 copy_v3_v3(diffuse, light->diffuse);
381                 copy_v3_v3(specular, light->specular);
382                 diffuse[3] = 1.0f;
383                 specular[3] = 1.0f;
384                 glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, diffuse);
385                 glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, specular);
386
387                 /* attenuation */
388                 if (light->type == GPU_LIGHT_SUN) {
389                         glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, 1.0f);
390                         glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, 0.0f);
391                         glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
392                 }
393                 else {
394                         glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
395                         glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
396                         glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
397                 }
398
399                 /* spot */
400                 glLightfv(GL_LIGHT0 + light_num, GL_SPOT_DIRECTION, light->direction);
401                 if (light->type == GPU_LIGHT_SPOT) {
402                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
403                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, light->spot_exponent);
404                 }
405                 else {
406                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, 180.0f);
407                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, 0.0f);
408                 }
409
410                 GPU_MATERIAL_STATE.lights_enabled |= light_bit;
411                 if (position[3] == 0.0f)
412                         GPU_MATERIAL_STATE.lights_directional |= light_bit;
413         }
414         else {
415                 /* TODO(sergey): Needs revisit. */
416                 /* glsl shader needs these zero to skip them */
417                 const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
418
419                 glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
420                 glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
421                 glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
422
423                 glDisable(GL_LIGHT0 + light_num);
424         }
425 }
426
427 void GPU_basic_shader_light_set_viewer(bool local)
428 {
429         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local) ? GL_TRUE: GL_FALSE);
430 }
431
432 void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
433 {
434         glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
435 }
436
437 void GPU_basic_shader_line_width(float line_width)
438 {
439         GPU_MATERIAL_STATE.line_width = line_width;
440         if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
441                 glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
442         }
443 }
444
445 void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern)
446 {
447         glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
448         glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
449 }