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