OpenGL: stipple support added to basic GLSL shader
[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 } 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_interlace_row[128] = {
144         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
145         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
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
161 const GLubyte stipple_interlace_row_swap[128] = {
162         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
163         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
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
179 const GLubyte stipple_interlace_column[128] = {
180         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
181         0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
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
197 const GLubyte stipple_interlace_column_swap[128] = {
198         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
199         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
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
215 const GLubyte stipple_interlace_checker[128] = {
216         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
217         0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa,
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
233 const GLubyte stipple_interlace_checker_swap[128] = {
234         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
235         0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55,
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
251 const GLubyte stipple_hexagon[128] = {
252         0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
253         0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
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 /* ********************************************* */
269
270 /* Init / exit */
271
272 void GPU_basic_shaders_init(void)
273 {
274         memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE));
275 }
276
277 void GPU_basic_shaders_exit(void)
278 {
279         int i;
280         
281         for (i = 0; i < GPU_SHADER_OPTION_COMBINATIONS; i++)
282                 if (GPU_MATERIAL_STATE.cached_shaders[i])
283                         GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]);
284 }
285
286 /* Shader lookup / create */
287
288 static bool solid_compatible_lighting(void)
289 {
290         int enabled = GPU_MATERIAL_STATE.lights_enabled;
291         int directional = GPU_MATERIAL_STATE.lights_directional;
292
293         /* more than 3 lights? */
294         if (enabled >= (1 << 3))
295                 return false;
296
297         /* all directional? */
298         return ((directional & enabled) == enabled);
299 }
300
301 #if 0
302 static int detect_options()
303 {
304         GLint two_sided;
305         int options = 0;
306
307         if (glIsEnabled(GL_TEXTURE_2D))
308                 options |= GPU_SHADER_TEXTURE_2D;
309         if (glIsEnabled(GL_COLOR_MATERIAL))
310                 options |= GPU_SHADER_USE_COLOR;
311
312         if (glIsEnabled(GL_LIGHTING))
313                 options |= GPU_SHADER_LIGHTING;
314
315         glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided);
316         if (two_sided == GL_TRUE)
317                 options |= GPU_SHADER_TWO_SIDED;
318         
319         return options;
320 }
321 #endif
322
323 static GPUShader *gpu_basic_shader(int options)
324 {
325         /* glsl code */
326         extern char datatoc_gpu_shader_basic_vert_glsl[];
327         extern char datatoc_gpu_shader_basic_frag_glsl[];
328         GPUShader *shader;
329
330         /* detect if we can do faster lighting for solid draw mode */
331         if (options & GPU_SHADER_LIGHTING)
332                 if (solid_compatible_lighting())
333                         options |= GPU_SHADER_SOLID_LIGHTING;
334
335         /* cached shaders */
336         shader = GPU_MATERIAL_STATE.cached_shaders[options];
337
338         if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) {
339                 /* create shader if it doesn't exist yet */
340                 char defines[64*GPU_SHADER_OPTIONS_NUM] = "";
341
342                 if (options & GPU_SHADER_USE_COLOR)
343                         strcat(defines, "#define USE_COLOR\n");
344                 if (options & GPU_SHADER_TWO_SIDED)
345                         strcat(defines, "#define USE_TWO_SIDED\n");
346                 if (options & GPU_SHADER_TEXTURE_2D)
347                         strcat(defines, "#define USE_TEXTURE\n");
348                 if (options & GPU_SHADER_STIPPLE)
349                         strcat(defines, "#define USE_STIPPLE\n");
350
351                 if (options & GPU_SHADER_SOLID_LIGHTING)
352                         strcat(defines, "#define USE_SOLID_LIGHTING\n");
353                 else if (options & GPU_SHADER_LIGHTING)
354                         strcat(defines, "#define USE_SCENE_LIGHTING\n");
355
356                 shader = GPU_shader_create(
357                         datatoc_gpu_shader_basic_vert_glsl,
358                         datatoc_gpu_shader_basic_frag_glsl,
359                         NULL,
360                         NULL,
361                         defines, 0, 0, 0);
362                 
363                 if (shader) {
364                         /* set texture map to first texture unit */
365                         if (options & GPU_SHADER_TEXTURE_2D)
366                                 glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0);
367
368                         GPU_MATERIAL_STATE.cached_shaders[options] = shader;
369                 }
370                 else
371                         GPU_MATERIAL_STATE.failed_shaders[options] = true;
372         }
373
374         return shader;
375 }
376
377 /* Bind / unbind */
378
379 void GPU_basic_shader_bind(int options)
380 {
381         if (USE_GLSL) {
382                 if (options) {
383                         GPUShader *shader = gpu_basic_shader(options);
384
385                         if (shader)
386                                 GPU_shader_bind(shader);
387                 }
388                 else {
389                         GPU_shader_unbind();
390                 }
391         }
392         else {
393                 int bound_options = GPU_MATERIAL_STATE.bound_options;
394
395                 if (options & GPU_SHADER_LIGHTING) {
396                         glEnable(GL_LIGHTING);
397
398                         if (options & GPU_SHADER_USE_COLOR)
399                                 glEnable(GL_COLOR_MATERIAL);
400                         else
401                                 glDisable(GL_COLOR_MATERIAL);
402
403                         if (options & GPU_SHADER_TWO_SIDED)
404                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
405                         else
406                                 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
407                 }
408                 else if (bound_options & GPU_SHADER_LIGHTING) {
409                         glDisable(GL_LIGHTING);
410                         glDisable(GL_COLOR_MATERIAL);
411                         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
412                 }
413
414                 if (options & GPU_SHADER_TEXTURE_2D) {
415                         GLint env_mode = (options & (GPU_SHADER_USE_COLOR|GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
416                         glEnable(GL_TEXTURE_2D);
417                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
418                 }
419                 else if (bound_options & GPU_SHADER_TEXTURE_2D) {
420                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
421                         glDisable(GL_TEXTURE_2D);
422                 }
423
424                 if (options & GPU_SHADER_STIPPLE)
425                         glEnable(GL_POLYGON_STIPPLE);
426                 else if (bound_options & GPU_SHADER_STIPPLE)
427                         glDisable(GL_POLYGON_STIPPLE);
428         }
429
430         GPU_MATERIAL_STATE.bound_options = options;
431 }
432
433 int GPU_basic_shader_bound_options(void)
434 {
435         /* ideally this should disappear, anything that uses this is making fragile
436          * assumptions that the basic shader is bound and not another shader */
437         return GPU_MATERIAL_STATE.bound_options;
438 }
439
440 /* Material Colors */
441
442 void GPU_basic_shader_colors(const float diffuse[3], const float specular[3],
443         int shininess, float alpha)
444 {
445         float gl_diffuse[4], gl_specular[4];
446
447         if (diffuse)
448                 copy_v3_v3(gl_diffuse, diffuse);
449         else
450                 zero_v3(gl_diffuse);
451         gl_diffuse[3] = alpha;
452
453         if (specular)
454                 copy_v3_v3(gl_specular, specular);
455         else
456                 zero_v3(gl_specular);
457         gl_specular[3] = 1.0f;
458
459         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse);
460         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular);
461         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128));
462 }
463
464 void GPU_basic_shader_light_set(int light_num, GPULightData *light)
465 {
466         int light_bit = (1 << light_num);
467
468         /* note that light position is affected by the current modelview matrix! */
469
470         GPU_MATERIAL_STATE.lights_enabled &= ~light_bit;
471         GPU_MATERIAL_STATE.lights_directional &= ~light_bit;
472
473         if (light) {
474                 float position[4], diffuse[4], specular[4];
475
476                 glEnable(GL_LIGHT0+light_num);
477
478                 /* position */
479                 if (light->type == GPU_LIGHT_SUN) {
480                         copy_v3_v3(position, light->direction);
481                         position[3] = 0.0f;
482                 }
483                 else {
484                         copy_v3_v3(position, light->position);
485                         position[3] = 1.0f;
486                 }
487                 glLightfv(GL_LIGHT0+light_num, GL_POSITION, position);
488
489                 /* energy */
490                 copy_v3_v3(diffuse, light->diffuse);
491                 copy_v3_v3(specular, light->specular);
492                 diffuse[3] = 1.0f;
493                 specular[3] = 1.0f;
494                 glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, diffuse);
495                 glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, specular);
496
497                 /* attenuation */
498                 if (light->type == GPU_LIGHT_SUN) {
499                         glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, 1.0f);
500                         glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, 0.0f);
501                         glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, 0.0f);
502                 }
503                 else {
504                         glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation);
505                         glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation);
506                         glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation);
507                 }
508
509                 /* spot */
510                 glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->direction);
511                 if (light->type == GPU_LIGHT_SPOT) {
512                         glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff);
513                         glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent);
514                 }
515                 else {
516                         glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, 180.0f);
517                         glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, 0.0f);
518                 }
519
520                 GPU_MATERIAL_STATE.lights_enabled |= light_bit;
521                 if (position[3] == 0.0f)
522                         GPU_MATERIAL_STATE.lights_directional |= light_bit;
523         }
524         else {
525                 if (USE_GLSL) {
526                         /* glsl shader needs these zero to skip them */
527                         const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
528
529                         glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero);
530                         glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero);
531                         glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero);
532                 }
533
534                 glDisable(GL_LIGHT0+light_num);
535         }
536 }
537
538 void GPU_basic_shader_light_set_viewer(bool local)
539 {
540         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local)? GL_TRUE: GL_FALSE);
541 }
542
543 void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
544 {
545         if (USE_GLSL) {
546                 glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
547         }
548         else {
549                 switch(stipple_id) {
550                 case GPU_SHADER_STIPPLE_HALFTONE:
551                         glPolygonStipple(stipple_halftone);
552                         return;
553                 case GPU_SHADER_STIPPLE_QUARTTONE:
554                         glPolygonStipple(stipple_quarttone);
555                         return;
556                 case GPU_SHADER_STIPPLE_CHECKER_8PX:
557                         glPolygonStipple(stipple_checker_8px);
558                         return;
559                 case GPU_SHADER_STIPPLE_HEXAGON:
560                         glPolygonStipple(stipple_hexagon);
561                         return;
562                 case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP:
563                         glPolygonStipple(stipple_diag_stripes_neg);
564                         return;
565                 case GPU_SHADER_STIPPLE_DIAG_STRIPES:
566                         glPolygonStipple(stipple_diag_stripes_pos);
567                         return;
568                 case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW:
569                         glPolygonStipple(stipple_interlace_row);
570                         return;
571                 case GPU_SHADER_STIPPLE_S3D_INTERLACE_ROW_SWAP:
572                         glPolygonStipple(stipple_interlace_row_swap);
573                         return;
574                 case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN:
575                         glPolygonStipple(stipple_interlace_column);
576                         return;
577                 case GPU_SHADER_STIPPLE_S3D_INTERLACE_COLUMN_SWAP:
578                         glPolygonStipple(stipple_interlace_column_swap);
579                         return;
580                 case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER:
581                         glPolygonStipple(stipple_interlace_checker);
582                         return;
583                 case GPU_SHADER_STIPPLE_S3D_INTERLACE_CHECKER_SWAP:
584                         glPolygonStipple(stipple_interlace_checker_swap);
585                         return;
586                 default:
587                         glPolygonStipple(stipple_hexagon);
588                         return;
589                 }
590         }
591 }