1//
2//   Copyright 2013 Pixar
3//
4//   Licensed under the Apache License, Version 2.0 (the "Apache License")
5//   with the following modification; you may not use this file except in
6//   compliance with the Apache License and the following modification to it:
7//   Section 6. Trademarks. is deleted and replaced with:
8//
9//   6. Trademarks. This License does not grant permission to use the trade
10//      names, trademarks, service marks, or product names of the Licensor
11//      and its affiliates, except as required to comply with Section 4(c) of
12//      the License and to reproduce the content of the NOTICE file.
13//
14//   You may obtain a copy of the Apache License at
15//
16//       http://www.apache.org/licenses/LICENSE-2.0
17//
18//   Unless required by applicable law or agreed to in writing, software
19//   distributed under the Apache License with the above modification is
20//   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21//   KIND, either express or implied. See the Apache License for the specific
22//   language governing permissions and limitations under the Apache License.
23//
24
25vec4 PTexLookup(vec4 patchCoord,
26                sampler2DArray data,
27                samplerBuffer packings,
28                isamplerBuffer pages)
29{
30    vec2 uv = patchCoord.xy;
31    int faceID = int(patchCoord.w);
32    int page = texelFetch(pages, faceID).x;
33    vec4 packing = texelFetch(packings, faceID);
34    vec3 coords = vec3( packing.x + uv.x * packing.z,
35                        packing.y + uv.y * packing.w,
36                        page);
37
38    return texture(data, coords);
39}
40
41uniform sampler2DArray textureImage_Data;
42uniform samplerBuffer textureImage_Packing;
43uniform isamplerBuffer textureImage_Pages;
44
45vec4 displacement(vec4 position, vec3 normal, vec4 patchCoord)
46{
47    float disp = PTexLookup(patchCoord,
48                            textureImage_Data,
49                            textureImage_Packing,
50                            textureImage_Pages).x;
51    return position + 0.01*vec4(disp * normal, 0);
52}
53
54//--------------------------------------------------------------
55// Uniform Blocks
56//--------------------------------------------------------------
57
58layout(std140) uniform Transform {
59    mat4 ModelViewMatrix;
60    mat4 ProjectionMatrix;
61    mat4 ModelViewProjectionMatrix;
62    mat4 ModelViewInverseMatrix;
63    mat4 ProjectionWithoutPickMatrix;
64};
65
66layout(std140) uniform Tessellation {
67    float TessLevel;
68};
69
70uniform int GregoryQuadOffsetBase;
71uniform int PrimitiveIdBase;
72
73//--------------------------------------------------------------
74// Osd external functions
75//--------------------------------------------------------------
76
77mat4 OsdModelViewMatrix()
78{
79    return ModelViewMatrix;
80}
81mat4 OsdProjectionMatrix()
82{
83    return ProjectionMatrix;
84}
85mat4 OsdModelViewProjectionMatrix()
86{
87    return ModelViewProjectionMatrix;
88}
89float OsdTessLevel()
90{
91    return TessLevel;
92}
93int OsdGregoryQuadOffsetBase()
94{
95    return GregoryQuadOffsetBase;
96}
97int OsdPrimitiveIdBase()
98{
99    return PrimitiveIdBase;
100}
101int OsdBaseVertex()
102{
103    return 0;
104}
105
106//--------------------------------------------------------------
107// Geometry Shader
108//--------------------------------------------------------------
109#ifdef GEOMETRY_SHADER
110
111    layout(triangles) in;
112
113    layout(triangle_strip, max_vertices = 3) out;
114
115    #define EDGE_VERTS 3
116
117    in block {
118        OutputVertex v;
119    } inpt[3];
120
121out block {
122    OutputVertex v;
123    noperspective out vec4 edgeDistance;
124} outpt;
125
126void emit(int index, vec4 position, vec3 normal, vec4 patchCoord)
127{
128    outpt.v.position = position;
129    outpt.v.patchCoord = patchCoord;
130    outpt.v.normal = normal;
131
132    gl_Position = ProjectionMatrix * outpt.v.position;
133    EmitVertex();
134}
135
136const float VIEWPORT_SCALE = 1024.0; // XXXdyu
137
138float edgeDistance(vec4 p, vec4 p0, vec4 p1)
139{
140    return VIEWPORT_SCALE *
141        abs((p.x - p0.x) * (p1.y - p0.y) -
142            (p.y - p0.y) * (p1.x - p0.x)) / length(p1.xy - p0.xy);
143}
144
145void emit(int index, vec4 position, vec3 normal, vec4 patchCoord, vec4 edgeVerts[EDGE_VERTS])
146{
147    outpt.edgeDistance[0] =
148        edgeDistance(edgeVerts[index], edgeVerts[0], edgeVerts[1]);
149    outpt.edgeDistance[1] =
150        edgeDistance(edgeVerts[index], edgeVerts[1], edgeVerts[2]);
151    outpt.edgeDistance[2] =
152        edgeDistance(edgeVerts[index], edgeVerts[2], edgeVerts[0]);
153    emit(index, position, normal, patchCoord);
154}
155
156// --------------------------------------
157
158void main()
159{
160    gl_PrimitiveID = gl_PrimitiveIDIn;
161
162    vec4 position[3];
163    vec4 patchCoord[3];
164    vec3 normal[3];
165
166    // patch coords are computed in tessellation shader
167    patchCoord[0] = inpt[0].v.patchCoord;
168    patchCoord[1] = inpt[1].v.patchCoord;
169    patchCoord[2] = inpt[2].v.patchCoord;
170
171#ifdef USE_PTEX_DISPLACEMENT
172    position[0] = displacement(inpt[0].v.position, inpt[0].v.normal, patchCoord[0]);
173    position[1] = displacement(inpt[1].v.position, inpt[1].v.normal, patchCoord[1]);
174    position[2] = displacement(inpt[2].v.position, inpt[2].v.normal, patchCoord[2]);
175#else
176    position[0] = inpt[0].v.position;
177    position[1] = inpt[1].v.position;
178    position[2] = inpt[2].v.position;
179#endif
180
181    normal[0] = inpt[0].v.normal;
182    normal[1] = inpt[1].v.normal;
183    normal[2] = inpt[2].v.normal;
184
185#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
186    vec4 edgeVerts[EDGE_VERTS];
187    edgeVerts[0] = ProjectionMatrix * inpt[0].v.position;
188    edgeVerts[1] = ProjectionMatrix * inpt[1].v.position;
189    edgeVerts[2] = ProjectionMatrix * inpt[2].v.position;
190
191    edgeVerts[0].xy /= edgeVerts[0].w;
192    edgeVerts[1].xy /= edgeVerts[1].w;
193    edgeVerts[2].xy /= edgeVerts[2].w;
194
195    emit(0, position[0], normal[0], patchCoord[0], edgeVerts);
196    emit(1, position[1], normal[1], patchCoord[1], edgeVerts);
197    emit(2, position[2], normal[2], patchCoord[2], edgeVerts);
198#else
199    emit(0, position[0], normal[0], patchCoord[0]);
200    emit(1, position[1], normal[1], patchCoord[1]);
201    emit(2, position[2], normal[2], patchCoord[2]);
202#endif
203
204    EndPrimitive();
205}
206
207#endif
208
209//--------------------------------------------------------------
210// Fragment Shader
211//--------------------------------------------------------------
212#ifdef FRAGMENT_SHADER
213
214in block {
215    OutputVertex v;
216    noperspective in vec4 edgeDistance;
217} inpt;
218
219out vec4 outColor;
220
221#define NUM_LIGHTS 2
222
223struct LightSource {
224    vec4 position;
225    vec4 ambient;
226    vec4 diffuse;
227    vec4 specular;
228};
229
230layout(std140) uniform Lighting {
231    LightSource lightSource[NUM_LIGHTS];
232};
233
234uniform vec4 diffuseColor = vec4(1);
235uniform vec4 ambientColor = vec4(1);
236
237vec4
238lighting(vec4 diffuse, vec3 Peye, vec3 Neye)
239{
240    vec4 color = vec4(0);
241
242    for (int i = 0; i < NUM_LIGHTS; ++i) {
243
244        vec4 Plight = lightSource[i].position;
245
246        vec3 l = (Plight.w == 0.0)
247                    ? normalize(Plight.xyz) : normalize(Plight.xyz - Peye);
248
249        vec3 n = normalize(Neye);
250        vec3 h = normalize(l + vec3(0,0,1));    // directional viewer
251
252        float d = max(0.0, dot(n, l));
253        float s = pow(max(0.0, dot(n, h)), 500.0f);
254
255        color += lightSource[i].ambient * ambientColor
256            + d * lightSource[i].diffuse * diffuse
257            + s * lightSource[i].specular;
258    }
259
260    color.a = 1;
261    return color;
262}
263
264#ifdef USE_PTEX_DISPLACEMENT
265vec3
266perturbNormalFromDisplacement(vec3 position, vec3 normal, vec4 patchCoord)
267{
268    // by Morten S. Mikkelsen
269    // http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf
270    // slightly modified for ptex guttering
271
272    vec3 vSigmaS = dFdx(position);
273    vec3 vSigmaT = dFdy(position);
274    vec3 vN = normal;
275    vec3 vR1 = cross(vSigmaT, vN);
276    vec3 vR2 = cross(vN, vSigmaS);
277    float fDet = dot(vSigmaS, vR1);
278
279    vec2 texDx = dFdx(patchCoord.xy);
280    vec2 texDy = dFdy(patchCoord.xy);
281
282    // limit forward differencing to the width of ptex gutter
283    const float resolution = 128.0;
284    float d = (0.5/resolution)/max(length(texDx), length(texDy));
285
286    vec4 STll = patchCoord;
287    vec4 STlr = patchCoord + d * vec4(texDx.x, texDx.y, 0, 0);
288    vec4 STul = patchCoord + d * vec4(texDy.x, texDy.y, 0, 0);
289    float Hll = PTexLookup(STll, textureImage_Data, textureImage_Packing, textureImage_Pages).x;
290    float Hlr = PTexLookup(STlr, textureImage_Data, textureImage_Packing, textureImage_Pages).x;
291    float Hul = PTexLookup(STul, textureImage_Data, textureImage_Packing, textureImage_Pages).x;
292    float dBs = (Hlr - Hll)/d;
293    float dBt = (Hul - Hll)/d;
294
295    vec3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
296    return normalize(abs(fDet) * vN - vSurfGrad);
297}
298#endif // USE_PTEX_NORMAL
299
300vec4
301edgeColor(vec4 Cfill, vec4 edgeDistance)
302{
303#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
304    float d =
305        min(inpt.edgeDistance[0], min(inpt.edgeDistance[1], inpt.edgeDistance[2]));
306    vec4 Cedge = vec4(0.5, 0.5, 0.5, 1.0);
307    float p = exp2(-2 * d * d);
308
309#if defined(GEOMETRY_OUT_WIRE)
310    if (p < 0.25) discard;
311#endif
312
313    Cfill.rgb = mix(Cfill.rgb, Cedge.rgb, p);
314#endif
315    return Cfill;
316}
317
318void
319main()
320{
321    vec3 N = (gl_FrontFacing ? inpt.v.normal : -inpt.v.normal);
322#ifdef USE_PTEX_DISPLACEMENT
323    N = perturbNormalFromDisplacement(inpt.v.position.xyz,
324                                      N,
325                                      inpt.v.patchCoord);
326#endif
327
328    vec4 Cf = vec4(1.0);
329#if defined(GEOMETRY_OUT_WIRE) || defined(GEOMETRY_OUT_LINE)
330    Cf = edgeColor(Cf, inpt.edgeDistance);
331#endif
332
333#ifdef USE_PTEX_COLOR
334    Cf = Cf * (vec4(1) - vec4(PTexLookup(inpt.v.patchCoord,
335                                    textureImage_Data,
336                                    textureImage_Packing,
337                                         textureImage_Pages).x));
338#endif
339
340    Cf = lighting(Cf, inpt.v.position.xyz, N);
341
342    outColor = Cf;
343}
344
345#endif
346