Fix ATI part of T45708, crash when enabling opensubdiv.
[blender.git] / intern / opensubdiv / gpu_shader_opensubd_display.glsl
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) 2014 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Sergey Sharybin
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /* ***** Vertex shader ***** */
27
28 #extension GL_EXT_geometry_shader4 : enable
29 #extension GL_ARB_gpu_shader5 : enable
30 #extension GL_ARB_explicit_attrib_location : require
31 #extension GL_ARB_uniform_buffer_object : require
32
33 struct VertexData {
34         vec4 position;
35         vec3 normal;
36         vec2 uv;
37 };
38
39 #ifdef VERTEX_SHADER
40
41 in vec3 normal;
42 in vec4 position;
43
44 uniform mat4 modelViewMatrix;
45 uniform mat3 normalMatrix;
46
47 out block {
48         VertexData v;
49 } outpt;
50
51 void main()
52 {
53         outpt.v.position = modelViewMatrix * position;
54         outpt.v.normal = normalize(normalMatrix * normal);
55 }
56
57 #endif  /* VERTEX_SHADER */
58
59 /* ***** geometry shader ***** */
60 #ifdef GEOMETRY_SHADER
61
62 #ifndef GLSL_COMPAT_WORKAROUND
63 layout(lines_adjacency) in;
64 #ifndef WIREFRAME
65 layout(triangle_strip, max_vertices = 4) out;
66 #else
67 layout(line_strip, max_vertices = 8) out;
68 #endif
69 #endif
70
71 uniform mat4 modelViewMatrix;
72 uniform mat4 projectionMatrix;
73 uniform int PrimitiveIdBase;
74 uniform int osd_fvar_count;
75 uniform int osd_active_uv_offset;
76
77 in block {
78         VertexData v;
79 } inpt[4];
80
81 #define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord)  \
82         { \
83                 vec2 v[4]; \
84                 int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
85                 for (int i = 0; i < 4; ++i) { \
86                         int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
87                         v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
88                                     texelFetch(FVarDataBuffer, index + 1).s); \
89                 } \
90                 result = mix(mix(v[0], v[1], tessCoord.s), \
91                              mix(v[3], v[2], tessCoord.s), \
92                              tessCoord.t); \
93         }
94
95 uniform samplerBuffer FVarDataBuffer;
96
97 out block {
98         VertexData v;
99 } outpt;
100
101 #ifdef FLAT_SHADING
102 void emit(int index, vec3 normal)
103 {
104         outpt.v.position = inpt[index].v.position;
105         outpt.v.normal = normal;
106
107         /* TODO(sergey): Only uniform subdivisions atm. */
108         vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
109         vec2 st = quadst[index];
110
111         INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
112
113         gl_Position = projectionMatrix * inpt[index].v.position;
114         EmitVertex();
115 }
116
117 #  ifdef WIREFRAME
118 void emit_edge(int v0, int v1, vec3 normal)
119 {
120         emit(v0, normal);
121         emit(v1, normal);
122 }
123 #  endif
124
125 #else
126 void emit(int index)
127 {
128         outpt.v.position = inpt[index].v.position;
129         outpt.v.normal = inpt[index].v.normal;
130
131         /* TODO(sergey): Only uniform subdivisions atm. */
132         vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
133         vec2 st = quadst[index];
134
135         INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
136
137         gl_Position = projectionMatrix * inpt[index].v.position;
138         EmitVertex();
139 }
140
141 #  ifdef WIREFRAME
142 void emit_edge(int v0, int v1)
143 {
144         emit(v0);
145         emit(v1);
146 }
147 #  endif
148
149 #endif
150
151 void main()
152 {
153         gl_PrimitiveID = gl_PrimitiveIDIn;
154
155 #ifdef FLAT_SHADING
156         vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
157         vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
158         vec3 flat_normal = normalize(cross(B, A));
159 #  ifndef WIREFRAME
160         emit(0, flat_normal);
161         emit(1, flat_normal);
162         emit(3, flat_normal);
163         emit(2, flat_normal);
164 #  else
165         emit_edge(0, 1, flat_normal);
166         emit_edge(1, 2, flat_normal);
167         emit_edge(2, 3, flat_normal);
168         emit_edge(3, 0, flat_normal);
169 #  endif
170 #else
171 #  ifndef WIREFRAME
172         emit(0);
173         emit(1);
174         emit(3);
175         emit(2);
176 #  else
177         emit_edge(0, 1);
178         emit_edge(1, 2);
179         emit_edge(2, 3);
180         emit_edge(3, 0);
181 #  endif
182 #endif
183
184         EndPrimitive();
185 }
186
187 #endif  /* GEOMETRY_SHADER */
188
189 /* ***** Fragment shader ***** */
190 #ifdef FRAGMENT_SHADER
191
192 #define MAX_LIGHTS 8
193 #define NUM_SOLID_LIGHTS 3
194
195 struct LightSource {
196         vec4 position;
197         vec4 ambient;
198         vec4 diffuse;
199         vec4 specular;
200         vec4 spotDirection;
201         float constantAttenuation;
202         float linearAttenuation;
203         float quadraticAttenuation;
204         float spotCutoff;
205         float spotExponent;
206         float spotCosCutoff;
207 };
208
209 uniform Lighting {
210         LightSource lightSource[MAX_LIGHTS];
211         int num_enabled_lights;
212 };
213
214 uniform vec4 diffuse;
215 uniform vec4 specular;
216 uniform float shininess;
217
218 uniform sampler2D texture_buffer;
219
220 in block {
221         VertexData v;
222 } inpt;
223
224 void main()
225 {
226 #ifdef WIREFRAME
227         gl_FragColor = diffuse;
228 #else
229         vec3 N = inpt.v.normal;
230
231         if (!gl_FrontFacing)
232                 N = -N;
233
234         /* Compute diffuse and specular lighting. */
235         vec3 L_diffuse = vec3(0.0);
236         vec3 L_specular = vec3(0.0);
237
238 #ifndef USE_COLOR_MATERIAL
239         /* Assume NUM_SOLID_LIGHTS directional lights. */
240         for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
241                 vec4 Plight = lightSource[i].position;
242 #ifdef USE_DIRECTIONAL_LIGHT
243                 vec3 l = (Plight.w == 0.0)
244                             ? normalize(Plight.xyz)
245                             : normalize(inpt.v.position.xyz);
246 #else  /* USE_DIRECTIONAL_LIGHT */
247                 /* TODO(sergey): We can normalize it outside of the shader. */
248                 vec3 l = normalize(Plight.xyz);
249 #endif  /* USE_DIRECTIONAL_LIGHT */
250                 vec3 h = normalize(l + vec3(0, 0, 1));
251                 float d = max(0.0, dot(N, l));
252                 float s = pow(max(0.0, dot(N, h)), shininess);
253                 L_diffuse += d * lightSource[i].diffuse.rgb;
254                 L_specular += s * lightSource[i].specular.rgb;
255         }
256 #else  /* USE_COLOR_MATERIAL */
257         vec3 varying_position = inpt.v.position.xyz;
258         vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
259                 normalize(varying_position): vec3(0.0, 0.0, -1.0);
260         for (int i = 0; i < num_enabled_lights; i++) {
261                 /* todo: this is a slow check for disabled lights */
262                 if (lightSource[i].specular.a == 0.0)
263                         continue;
264
265                 float intensity = 1.0;
266                 vec3 light_direction;
267
268                 if (lightSource[i].position.w == 0.0) {
269                         /* directional light */
270                         light_direction = lightSource[i].position.xyz;
271                 }
272                 else {
273                         /* point light */
274                         vec3 d = lightSource[i].position.xyz - varying_position;
275                         light_direction = normalize(d);
276
277                         /* spot light cone */
278                         if (lightSource[i].spotCutoff < 90.0) {
279                                 float cosine = max(dot(light_direction,
280                                                        -lightSource[i].spotDirection.xyz),
281                                                    0.0);
282                                 intensity = pow(cosine, lightSource[i].spotExponent);
283                                 intensity *= step(lightSource[i].spotCosCutoff, cosine);
284                         }
285
286                         /* falloff */
287                         float distance = length(d);
288
289                         intensity /= lightSource[i].constantAttenuation +
290                                 lightSource[i].linearAttenuation * distance +
291                                 lightSource[i].quadraticAttenuation * distance * distance;
292                 }
293
294                 /* diffuse light */
295                 vec3 light_diffuse = lightSource[i].diffuse.rgb;
296                 float diffuse_bsdf = max(dot(N, light_direction), 0.0);
297                 L_diffuse += light_diffuse*diffuse_bsdf*intensity;
298
299                 /* specular light */
300                 vec3 light_specular = lightSource[i].specular.rgb;
301                 vec3 H = normalize(light_direction - V);
302
303                 float specular_bsdf = pow(max(dot(N, H), 0.0),
304                                           gl_FrontMaterial.shininess);
305                 L_specular += light_specular*specular_bsdf * intensity;
306         }
307 #endif  /* USE_COLOR_MATERIAL */
308
309         /* Compute diffuse color. */
310 #ifdef USE_TEXTURE_2D
311         L_diffuse *= texture2D(texture_buffer, inpt.v.uv).rgb;
312 #else
313         L_diffuse *= diffuse.rgb;
314 #endif
315
316         /* Sum lighting. */
317         vec3 L = L_diffuse;
318         if (shininess != 0) {
319                 L += L_specular * specular.rgb;
320         }
321
322         /* Write out fragment color. */
323         gl_FragColor = vec4(L, diffuse.a);
324 #endif
325 }
326
327 #endif  // FRAGMENT_SHADER