Merge branch 'master' into blender2.8
[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 const bool USE_GLSL = false;
55
56 static struct {
57         GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS];
58         bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS];
59
60         int bound_options;
61
62         int lights_enabled;
63         int lights_directional;
64         float line_width;
65         GLint viewport[4];
66 } GPU_MATERIAL_STATE;
67
68
69 /* Stipple patterns */
70 /* ******************************************** */
71 const GLubyte stipple_halftone[128] = {
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         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
87         0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
88
89 const GLubyte stipple_quarttone[128] = {
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         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0,
97         136, 136, 136, 136, 0, 0, 0, 0, 34, 34, 34, 34, 0, 0, 0, 0};
98
99 const GLubyte stipple_diag_stripes_pos[128] = {
100         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
101         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
102         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
103         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
104         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
105         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
106         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
107         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
108         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
109         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
110         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
111         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
112         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
113         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
114         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
115         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f};
116
117 const GLubyte stipple_diag_stripes_neg[128] = {
118         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
119         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
120         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
121         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
122         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
123         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
124         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
125         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80,
126         0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01,
127         0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07,
128         0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f,
129         0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f,
130         0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe,
131         0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8,
132         0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0,
133         0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80};
134
135 const GLubyte stipple_checker_8px[128] = {
136         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
137         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
138         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
139         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
140         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
141         255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
142         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
143         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
144
145 const GLubyte stipple_interlace_row[128] = {
146         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
147         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
148         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
149         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
150         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
151         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
152         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
153         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
154         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
155         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
156         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
157         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
158         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
159         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
160         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
161         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};
162
163 const GLubyte stipple_interlace_row_swap[128] = {
164         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
165         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
166         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
167         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
168         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
169         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
170         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
171         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
172         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
173         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
174         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
175         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
176         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
177         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
178         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
179         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};
180
181 const GLubyte stipple_interlace_column[128] = {
182         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
183         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
184         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
185         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
186         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
187         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
188         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
189         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
190         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
191         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
192         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
193         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
194         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
195         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
196         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
197         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
198
199 const GLubyte stipple_interlace_column_swap[128] = {
200         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
201         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
202         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
203         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
204         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
205         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
206         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
207         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
208         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
209         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
210         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
211         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
212         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
213         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
214         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
215         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
216
217 const GLubyte stipple_interlace_checker[128] = {
218         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
219         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
220         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
221         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
222         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
223         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
224         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
225         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
226         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
227         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
228         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
229         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
230         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
231         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
232         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
233         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
234
235 const GLubyte stipple_interlace_checker_swap[128] = {
236         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
237         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
238         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
239         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
240         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
241         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
242         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
243         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
244         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
245         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
246         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
247         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
248         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
249         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
250         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
251         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55};
252
253 const GLubyte stipple_hexagon[128] = {
254         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
255         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
256         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
257         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
258         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
259         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
260         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
261         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
262         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
263         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
264         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
265         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
266         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
267         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
268         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
269         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
270 /* ********************************************* */
271
272 /* Init / exit */
273
274 void GPU_basic_shaders_init(void)
275 {
276         memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE));
277 }
278
279 void GPU_basic_shaders_exit(void)
280 {
281         int i;
282         
283         for (i = 0; i < GPU_SHADER_OPTION_COMBINATIONS; i++)
284                 if (GPU_MATERIAL_STATE.cached_shaders[i])
285                         GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]);
286 }
287
288 /* Shader lookup / create */
289
290 static bool solid_compatible_lighting(void)
291 {
292         int enabled = GPU_MATERIAL_STATE.lights_enabled;
293         int directional = GPU_MATERIAL_STATE.lights_directional;
294
295         /* more than 3 lights? */
296         if (enabled >= (1 << 3))
297                 return false;
298
299         /* all directional? */
300         return ((directional & enabled) == enabled);
301 }
302
303 #if 0
304 static int detect_options()
305 {
306         GLint two_sided;
307         int options = 0;
308
309         if (glIsEnabled(GL_TEXTURE_2D))
310                 options |= GPU_SHADER_TEXTURE_2D;
311         if (glIsEnabled(GL_COLOR_MATERIAL))
312                 options |= GPU_SHADER_USE_COLOR;
313
314         if (glIsEnabled(GL_LIGHTING))
315                 options |= GPU_SHADER_LIGHTING;
316
317         glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
318         if (two_sided == GL_TRUE)
319                 options |= GPU_SHADER_TWO_SIDED;
320         
321         return options;
322 }
323 #endif
324
325 static GPUShader *gpu_basic_shader(int options)
326 {
327         /* glsl code */
328         extern char datatoc_gpu_shader_basic_vert_glsl[];
329         extern char datatoc_gpu_shader_basic_frag_glsl[];
330         extern char datatoc_gpu_shader_basic_geom_glsl[];
331         char *geom_glsl = NULL;
332         GPUShader *shader;
333
334         /* detect if we can do faster lighting for solid draw mode */
335         if (options & GPU_SHADER_LIGHTING)
336                 if (solid_compatible_lighting())
337                         options |= GPU_SHADER_SOLID_LIGHTING;
338
339         /* cached shaders */
340         shader = GPU_MATERIAL_STATE.cached_shaders[options];
341
342         if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) {
343                 /* create shader if it doesn't exist yet */
344                 char defines[64 * GPU_SHADER_OPTIONS_NUM] = "";
345
346                 if (options & GPU_SHADER_USE_COLOR)
347                         strcat(defines, "#define USE_COLOR\n");
348                 if (options & GPU_SHADER_TWO_SIDED)
349                         strcat(defines, "#define USE_TWO_SIDED\n");
350                 if (options & GPU_SHADER_TEXTURE_2D)
351                         strcat(defines, "#define USE_TEXTURE\n");
352                 if (options & GPU_SHADER_STIPPLE)
353                         strcat(defines, "#define USE_STIPPLE\n");
354                 if (options & GPU_SHADER_LINE) {
355                         strcat(defines, "#define DRAW_LINE\n");
356                         geom_glsl = datatoc_gpu_shader_basic_geom_glsl;
357                 }
358                 if (options & GPU_SHADER_FLAT_NORMAL)
359                         strcat(defines, "#define USE_FLAT_NORMAL\n");
360                 if (options & GPU_SHADER_SOLID_LIGHTING)
361                         strcat(defines, "#define USE_SOLID_LIGHTING\n");
362                 else if (options & GPU_SHADER_LIGHTING)
363                         strcat(defines, "#define USE_SCENE_LIGHTING\n");
364
365                 shader = GPU_shader_create(
366                         datatoc_gpu_shader_basic_vert_glsl,
367                         datatoc_gpu_shader_basic_frag_glsl,
368                         geom_glsl,
369                         NULL,
370                         defines, 0, 0, 0);
371                 
372                 if (shader) {
373                         /* set texture map to first texture unit */
374                         if (options & GPU_SHADER_TEXTURE_2D) {
375                                 GPU_shader_bind(shader);
376                                 glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0);
377                                 GPU_shader_unbind();
378                         }
379
380                         GPU_MATERIAL_STATE.cached_shaders[options] = shader;
381                 }
382                 else
383                         GPU_MATERIAL_STATE.failed_shaders[options] = true;
384         }
385
386         return shader;
387 }
388
389 static void GPU_basic_shader_uniform_autoset(GPUShader *shader, int options)
390 {
391         if (options & GPU_SHADER_LINE) {
392                 glGetIntegerv(GL_VIEWPORT, &GPU_MATERIAL_STATE.viewport[0]);
393                 glUniform4iv(GPU_shader_get_uniform(shader, "viewport"), 1, &GPU_MATERIAL_STATE.viewport[0]);
394                 glUniform1f(GPU_shader_get_uniform(shader, "line_width"), GPU_MATERIAL_STATE.line_width);
395         }
396 }
397
398 /* Bind / unbind */
399
400 void GPU_basic_shader_bind(int options)
401 {
402         if (USE_GLSL) {
403                 if (options) {
404                         GPUShader *shader = gpu_basic_shader(options);
405
406                         if (shader) {
407                                 GPU_shader_bind(shader);
408                                 GPU_basic_shader_uniform_autoset(shader, options);
409                         }
410                 }
411                 else {
412                         GPU_shader_unbind();
413                 }
414         }
415         else {
416                 int bound_options = GPU_MATERIAL_STATE.bound_options;
417
418                 if (options & GPU_SHADER_LIGHTING) {
419                         glEnable(GL_LIGHTING);
420
421                         if (options & GPU_SHADER_USE_COLOR)
422                                 glEnable(GL_COLOR_MATERIAL);
423                         else
424                                 glDisable(GL_COLOR_MATERIAL);
425
426                         if (options & GPU_SHADER_TWO_SIDED)
427                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
428                         else
429                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
430                 }
431                 else if (bound_options & GPU_SHADER_LIGHTING) {
432                         glDisable(GL_LIGHTING);
433                         glDisable(GL_COLOR_MATERIAL);
434                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
435                 }
436
437                 if (options & GPU_SHADER_TEXTURE_2D) {
438                         GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
439                         glEnable(GL_TEXTURE_2D);
440                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
441                 }
442                 else if (bound_options & GPU_SHADER_TEXTURE_2D) {
443                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
444                         glDisable(GL_TEXTURE_2D);
445                 }
446
447                 if ((options & GPU_SHADER_LINE) && (options & GPU_SHADER_STIPPLE)) {
448                         glEnable(GL_LINE_STIPPLE);
449                 }
450                 else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) {
451                         glDisable(GL_LINE_STIPPLE);
452                 }
453                 else {
454                         if (options & GPU_SHADER_STIPPLE)
455                                 glEnable(GL_POLYGON_STIPPLE);
456                         else if (bound_options & GPU_SHADER_STIPPLE)
457                                 glDisable(GL_POLYGON_STIPPLE);
458                 }
459
460                 if (options & GPU_SHADER_FLAT_NORMAL)
461                         glShadeModel(GL_FLAT);
462                 else
463                         glShadeModel(GL_SMOOTH);
464
465         }
466
467         GPU_MATERIAL_STATE.bound_options = options;
468 }
469
470 int GPU_basic_shader_bound_options(void)
471 {
472         /* ideally this should disappear, anything that uses this is making fragile
473          * assumptions that the basic shader is bound and not another shader */
474         return GPU_MATERIAL_STATE.bound_options;
475 }
476
477 /* Material Colors */
478
479 void GPU_basic_shader_colors(const float diffuse[3], const float specular[3],
480         int shininess, float alpha)
481 {
482         float gl_diffuse[4], gl_specular[4];
483
484         if (diffuse)
485                 copy_v3_v3(gl_diffuse, diffuse);
486         else
487                 zero_v3(gl_diffuse);
488         gl_diffuse[3] = alpha;
489
490         if (specular)
491                 copy_v3_v3(gl_specular, specular);
492         else
493                 zero_v3(gl_specular);
494         gl_specular[3] = 1.0f;
495
496         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
497         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
498         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
499 }
500
501 void GPU_basic_shader_light_set(int light_num, GPULightData *light)
502 {
503         int light_bit = (1 << light_num);
504
505         /* note that light position is affected by the current modelview matrix! */
506
507         GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
508         GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
509
510         if (light) {
511                 float position[4], diffuse[4], specular[4];
512
513                 glEnable(GL_LIGHT0 + light_num);
514
515                 /* position */
516                 if (light->type == GPU_LIGHT_SUN) {
517                         copy_v3_v3(position, light->direction);
518                         position[3] = 0.0f;
519                 }
520                 else {
521                         copy_v3_v3(position, light->position);
522                         position[3] = 1.0f;
523                 }
524                 glLightfv(GL_LIGHT0 + light_num, GL_POSITION, position);
525
526                 /* energy */
527                 copy_v3_v3(diffuse, light->diffuse);
528                 copy_v3_v3(specular, light->specular);
529                 diffuse[3] = 1.0f;
530                 specular[3] = 1.0f;
531                 glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, diffuse);
532                 glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, specular);
533
534                 /* attenuation */
535                 if (light->type == GPU_LIGHT_SUN) {
536                         glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, 1.0f);
537                         glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, 0.0f);
538                         glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
539                 }
540                 else {
541                         glLightf(GL_LIGHT0 + light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
542                         glLightf(GL_LIGHT0 + light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
543                         glLightf(GL_LIGHT0 + light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
544                 }
545
546                 /* spot */
547                 glLightfv(GL_LIGHT0 + light_num, GL_SPOT_DIRECTION, light->direction);
548                 if (light->type == GPU_LIGHT_SPOT) {
549                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
550                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, light->spot_exponent);
551                 }
552                 else {
553                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_CUTOFF, 180.0f);
554                         glLightf(GL_LIGHT0 + light_num, GL_SPOT_EXPONENT, 0.0f);
555                 }
556
557                 GPU_MATERIAL_STATE.lights_enabled |= light_bit;
558                 if (position[3] == 0.0f)
559                         GPU_MATERIAL_STATE.lights_directional |= light_bit;
560         }
561         else {
562                 /* TODO(sergey): Needs revisit. */
563                 if (USE_GLSL || true) {
564                         /* glsl shader needs these zero to skip them */
565                         const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
566
567                         glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
568                         glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
569                         glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
570                 }
571
572                 glDisable(GL_LIGHT0 + light_num);
573         }
574 }
575
576 void GPU_basic_shader_light_set_viewer(bool local)
577 {
578         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local) ? GL_TRUE: GL_FALSE);
579 }
580
581 void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
582 {
583         if (USE_GLSL) {
584                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
585         }
586         else {
587                 switch (stipple_id) {
588                         case GPU_SHADER_STIPPLE_HALFTONE:
589                                 glPolygonStipple(stipple_halftone);
590                                 return;
591                         case GPU_SHADER_STIPPLE_QUARTTONE:
592                                 glPolygonStipple(stipple_quarttone);
593                                 return;
594                         case GPU_SHADER_STIPPLE_CHECKER_8PX:
595                                 glPolygonStipple(stipple_checker_8px);
596                                 return;
597                         case GPU_SHADER_STIPPLE_HEXAGON:
598                                 glPolygonStipple(stipple_hexagon);
599                                 return;
600                         case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP:
601                                 glPolygonStipple(stipple_diag_stripes_neg);
602                                 return;
603                         case GPU_SHADER_STIPPLE_DIAG_STRIPES:
604                                 glPolygonStipple(stipple_diag_stripes_pos);
605                                 return;
606                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW:
607                                 glPolygonStipple(stipple_interlace_row);
608                                 return;
609                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP:
610                                 glPolygonStipple(stipple_interlace_row_swap);
611                                 return;
612                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN:
613                                 glPolygonStipple(stipple_interlace_column);
614                                 return;
615                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP:
616                                 glPolygonStipple(stipple_interlace_column_swap);
617                                 return;
618                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER:
619                                 glPolygonStipple(stipple_interlace_checker);
620                                 return;
621                         case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP:
622                                 glPolygonStipple(stipple_interlace_checker_swap);
623                                 return;
624                         default:
625                                 glPolygonStipple(stipple_hexagon);
626                                 return;
627                 }
628         }
629 }
630
631 void GPU_basic_shader_line_width(float line_width)
632 {
633         if (USE_GLSL) {
634                 GPU_MATERIAL_STATE.line_width = line_width;
635                 if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
636                         glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
637                 }
638         }
639         else {
640                 glLineWidth(line_width);
641         }
642 }
643
644 void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern)
645 {
646         if (USE_GLSL) {
647                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
648                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
649         }
650         else {
651                 glLineStipple(stipple_factor, stipple_pattern);
652         }
653 }