SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLGLProgramGenerated.cpp
Go to the documentation of this file.
1 /**
2  * \file SLGLProgramGenerated.cpp
3  * \date December 2020
4  * \authors Marcus Hudritsch
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #include <SLAssetManager.h>
11 #include <SLGLProgramManager.h>
12 #include <SLGLProgramGenerated.h>
13 #include <SLGLShader.h>
14 #include <SLCamera.h>
15 #include <SLLight.h>
16 #include <SLGLDepthBuffer.h>
17 
18 using std::string;
19 using std::to_string;
20 
21 ///////////////////////////////
22 // Const. GLSL code snippets //
23 ///////////////////////////////
24 
25 //-----------------------------------------------------------------------------
27 //-----------------------------------------------------------------------------
28 const string vertInput_a_pn = R"(
29 layout (location = 0) in vec4 a_position; // Vertex position attribute
30 layout (location = 1) in vec3 a_normal; // Vertex normal attribute)";
31 const string vertInput_PS_a_p = R"(
32 layout (location = 0) in vec3 a_position; // Particle position attribute)";
33 const string vertInput_PS_a_v = R"(
34 layout (location = 1) in vec3 a_velocity; // Particle velocity attribute)";
35 const string vertInput_PS_a_st = R"(
36 layout (location = 2) in float a_startTime; // Particle start time attribute)";
37 const string vertInput_PS_a_initV = R"(
38 layout (location = 3) in vec3 a_initialVelocity;// Particle initial velocity attribute)";
39 const string vertInput_PS_a_r = R"(
40 layout (location = 4) in float a_rotation; // Particle rotation attribute)";
41 const string vertInput_PS_a_r_angularVelo = R"(
42 layout (location = 5) in float a_angularVelo; // Particle rotation rate attribute)";
43 const string vertInput_PS_a_texNum = R"(
44 layout (location = 6) in uint a_texNum; // Particle rotation attribute)";
45 const string vertInput_PS_a_initP = R"(
46 layout (location = 7) in vec3 a_initialPosition;// Particle initial position attribute)";
47 const string vertInput_PS_a_InstPos = R"(
48 layout (location = 8) in vec3 a_instancePos; // Particle instance triangle vertex position attribute)";
49 const string vertInput_a_uv0 = R"(
50 layout (location = 2) in vec2 a_uv0; // Vertex tex.coord. 1 for diffuse color)";
51 const string vertInput_a_uv1 = R"(
52 layout (location = 3) in vec2 a_uv1; // Vertex tex.coord. 2 for AO)";
53 const string vertInput_a_tangent = R"(
54 layout (location = 5) in vec4 a_tangent; // Vertex tangent attribute)";
55 const string vertInput_a_skinning = R"(
56 layout (location = 6) in ivec4 a_jointIds; // Vertex joint indices attributes
57 layout (location = 7) in vec4 a_jointWeights; // Vertex joint weights attributes)";
58 //-----------------------------------------------------------------------------
59 const string vertInput_u_matrices_all = R"(
60 
61 uniform mat4 u_mMatrix; // Model matrix (object to world transform)
62 uniform mat4 u_vMatrix; // View matrix (world to camera transform)
63 uniform mat4 u_pMatrix; // Projection matrix (camera to normalize device coords.))";
64 const string vertInput_u_matrix_vOmv = R"(
65 uniform mat4 u_vOmvMatrix; // view or modelview matrix)";
66 //-----------------------------------------------------------------------------
67 const string vertInput_u_skinning = R"(
68 
69 uniform mat4 u_jointMatrices[100]; // Joint matrices for skinning
70 uniform bool u_skinningEnabled; // Flag if the shader should perform skinning
71 )";
72 //-----------------------------------------------------------------------------
73 const string vertInput_u_lightNm = R"(
74 
75 uniform vec4 u_lightPosVS[NUM_LIGHTS]; // position of light in view space
76 uniform vec3 u_lightSpotDir[NUM_LIGHTS]; // spot direction in view space
77 uniform float u_lightSpotDeg[NUM_LIGHTS]; // spot cutoff angle 1-180 degrees)";
78 //-----------------------------------------------------------------------------
79 const string vertConstant_PS_pi = R"(
80 
81 #define PI 3.1415926538
82 #define TWOPI 6.2831853076
83 )";
84 //-----------------------------------------------------------------------------
85 const string vertInput_PS_u_time = R"(
86 uniform float u_time; // Simulation time
87 uniform float u_difTime; // Simulation delta time after frustum culling
88 uniform float u_tTL; // Time to live of a particle)";
89 const string fragInput_PS_u_tTL = R"(
90 uniform float u_tTL; // Time to live of a particle)";
92 uniform vec4 u_al_bernstein; // Bernstein polynomial for alpha over time)";
94 uniform vec4 u_si_bernstein; // Bernstein polynomial for size over time)";
95 const string vertInput_PS_u_colorOvLF = R"(
96 uniform float u_colorArr[256 * 3]; // Array of color value (for color over life))";
97 const string fragInput_PS_u_colorOvLF = R"(
98 uniform float u_colorArr[256 * 3]; // Array of color value (for color over life))";
99 const string vertInput_PS_u_deltaTime = R"(
100 uniform float u_deltaTime; // Elapsed time between frames)";
101 const string vertInput_PS_u_pgPos = R"(
102 uniform vec3 u_pGPosition; // Particle Generator position)";
103 const string vertInput_PS_u_a_const = R"(
104 uniform float u_accConst; // Particle acceleration constant)";
105 const string vertInput_PS_u_a_diffDir = R"(
106 uniform vec3 u_acceleration; // Particle acceleration)";
107 const string vertInput_PS_u_g = R"(
108 uniform vec3 u_gravity; // Particle gravity)";
109 const string vertInput_PS_u_angularVelo = R"(
110 uniform float u_angularVelo; // Particle angular velocity)";
111 const string vertInput_PS_u_col = R"(
112 uniform int u_col; // Number of column of flipbook texture)";
113 const string vertInput_PS_u_row = R"(
114 uniform int u_row; // Number of row of flipbook texture)";
115 const string vertInput_PS_u_condFB = R"(
116 uniform int u_condFB; // Condition to update texNum)";
117 
118 //-----------------------------------------------------------------------------
119 const string vertOutput_v_P_VS = R"(
120 out vec3 v_P_VS; // Point of illumination in view space (VS))";
121 const string vertOutput_v_P_WS = R"(
122 out vec3 v_P_WS; // Point of illumination in world space (WS))";
123 const string vertOutput_v_N_VS = R"(
124 out vec3 v_N_VS; // Normal at P_VS in view space (VS))";
125 const string vertOutput_v_R_OS = R"(
126 out vec3 v_R_OS; // Reflection vector in object space (WS))";
127 const string vertOutput_v_uv0 = R"(
128 out vec2 v_uv0; // Texture coordinate 0 output)";
129 const string vertOutput_v_uv1 = R"(
130 out vec2 v_uv1; // Texture coordinate 1 output)";
131 const string vertOutput_v_lightVecTS = R"(
132 out vec3 v_eyeDirTS; // Vector to the eye in tangent space
133 out vec3 v_lightDirTS[NUM_LIGHTS]; // Vector to the light 0 in tangent space
134 out vec3 v_spotDirTS[NUM_LIGHTS]; // Spot direction in tangent space)";
135 //-----------------------------------------------------------------------------
136 const string vertFunction_PS_ColorOverLT = R"(
137 vec3 colorByAge(float age)
138 {
139  int cachePos = int(clamp(age, 0.0, 1.0) * 255.0) * 3;
140  vec3 color = vec3(u_colorArr[cachePos], u_colorArr[cachePos + 1], u_colorArr[cachePos + 2]);
141  return color;
142 })";
143 //-----------------------------------------------------------------------------
144 const string fragFunction_PS_ColorOverLT = R"(
145 vec3 colorByAge(float age)
146 {
147  int cachePos = int(clamp(age, 0.0, 1.0) * 255.0) * 3;
148  vec3 color = vec3(u_colorArr[cachePos], u_colorArr[cachePos + 1], u_colorArr[cachePos + 2]);
149  return color;
150 })";
151 //-----------------------------------------------------------------------------
152 const string vertOutput_PS_struct_Begin = R"(
153 
154 out vertex
155 { )";
156 const string vertOutput_PS_struct_t = R"(
157  float transparency; // Transparency of a particle)";
158 const string vertOutput_PS_struct_r = R"(
159  float rotation; // Rotation of a particle)";
160 const string vertOutput_PS_struct_s = R"(
161  float size; // Size of a particle )";
162 const string vertOutput_PS_struct_c = R"(
163  vec3 color; // Color of a particle )";
164 const string vertOutput_PS_struct_texNum = R"(
165  uint texNum; // Num of texture in flipbook)";
166 const string vertOutput_PS_struct_End = R"(
167 } vert; )";
168 
170 out float transparency; // transparency of a particle )";
172 in float transparency; // transparency of a particle )";
173 
175  vec4 color = vec4(colorByAge(v_age/u_tTL), 1.0); // Particle color)";
176 const string fragMain_PS_instanced_c = R"(
177  vec4 color = u_color; // Particle color)";
179  color.w *= transparency; // Apply transparency)";
180 const string vertInput_u_matrix_p = R"(
181 uniform mat4 u_pMatrix; // Projection matrix)";
183 uniform mat4 u_vYawPMatrix; // Projection matrix)";
184 const string fragInput_PS_u_c = R"(
185 uniform vec4 u_color; // Particle color)";
186 const string vertInput_PS_u_ScaRa = R"(
187 uniform float u_scale; // Particle scale
188 uniform float u_radiusW; // Particle width radius)
189 uniform float u_radiusH; // Particle height radius)";
190 
191 //-----------------------------------------------------------------------------
192 const string vertOutput_PS_tf_p = R"(
193 
194 out vec3 tf_position; // To transform feedback)";
195 const string vertOutput_PS_tf_v = R"(
196 out vec3 tf_velocity; // To transform feedback)";
197 const string vertOutput_PS_tf_st = R"(
198 out float tf_startTime; // To transform feedback)";
199 const string vertOutput_PS_tf_initV = R"(
200 out vec3 tf_initialVelocity; // To transform feedback)";
201 const string vertOutput_PS_tf_r = R"(
202 out float tf_rotation; // To transform feedback)";
204 out float tf_angularVelo; // To transform feedback)";
205 const string vertOutput_PS_tf_texNum = R"(
206 flat out uint tf_texNum; // To transform feedback)";
207 const string vertOutput_PS_tf_initP = R"(
208 out vec3 tf_initialPosition; // To transform feedback)";
209 
210 //-----------------------------------------------------------------------------
211 const string main_Begin = R"(
212 //-----------------------------------------------------------------------------
213 void main()
214 {)";
215 //-----------------------------------------------------------------------------
216 const string vertMain_v_P_VS = R"(
217  mat4 mvMatrix = u_vMatrix * u_mMatrix;
218  v_P_VS = vec3(mvMatrix * ${localPosition}); // vertex position in view space)";
219 const string vertMain_v_P_WS_Sm = R"(
220  v_P_WS = vec3(u_mMatrix * ${localPosition}); // vertex position in world space)";
221 const string vertMain_v_N_VS = R"(
222  mat3 invMvMatrix = mat3(inverse(mvMatrix));
223  mat3 nMatrix = transpose(invMvMatrix);
224  v_N_VS = vec3(nMatrix * ${localNormal}); // vertex normal in view space)";
225 const string vertMain_v_R_OS = R"(
226  vec3 I = normalize(v_P_VS);
227  vec3 N = normalize(v_N_VS);
228  v_R_OS = invMvMatrix * reflect(I, N); // R = I-2.0*dot(N,I)*N;)";
229 const string vertMain_v_uv0 = R"(
230  v_uv0 = a_uv0; // pass diffuse color tex.coord. 0 for interpolation)";
231 const string vertMain_v_uv1 = R"(
232  v_uv1 = a_uv1; // pass diffuse color tex.coord. 1 for interpolation)";
233 const string vertMain_skinning = R"(
234  vec4 skinnedPosition;
235  vec3 skinnedNormal;
236 
237  if (u_skinningEnabled)
238  {
239  // In skinned skeleton animation, every vertex of a mesh is transformed by
240  // max. four joints (bones) of a skeleton identified by indices. The joint
241  // matrix is a weighted sum of four joint matrices and can change per frame
242  // to animate the mesh.
243  mat4 jm = u_jointMatrices[int(a_jointIds.x)] * a_jointWeights.x
244  + u_jointMatrices[int(a_jointIds.y)] * a_jointWeights.y
245  + u_jointMatrices[int(a_jointIds.z)] * a_jointWeights.z
246  + u_jointMatrices[int(a_jointIds.w)] * a_jointWeights.w;
247 
248  skinnedPosition = jm * a_position;
249  skinnedNormal = mat3(jm) * a_normal;
250  }
251  else
252  {
253  skinnedPosition = a_position;
254  skinnedNormal = a_normal;
255  }
256 )";
257 const string vertMain_skinning_Nm = R"(
258  vec4 skinnedPosition;
259  vec3 skinnedNormal;
260  vec4 skinnedTangent;
261 
262  if (u_skinningEnabled)
263  {
264  // In skinned skeleton animation, every vertex of a mesh is transformed by
265  // max. four joints (bones) of a skeleton identified by indices. The joint
266  // matrix is a weighted sum of four joint matrices and can change per frame
267  // to animate the mesh.
268  mat4 jm = u_jointMatrices[int(a_jointIds.x)] * a_jointWeights.x
269  + u_jointMatrices[int(a_jointIds.y)] * a_jointWeights.y
270  + u_jointMatrices[int(a_jointIds.z)] * a_jointWeights.z
271  + u_jointMatrices[int(a_jointIds.w)] * a_jointWeights.w;
272 
273  skinnedPosition = jm * a_position;
274  skinnedNormal = mat3(jm) * a_normal;
275  skinnedTangent = vec4(mat3(jm) * a_tangent.xyz, a_tangent.w);
276  }
277  else
278  {
279  skinnedPosition = a_position;
280  skinnedNormal = a_normal;
281  skinnedTangent = a_tangent;
282  }
283 )";
284 const string vertMain_TBN_Nm = R"(
285 
286  // Building the matrix Eye Space -> Tangent Space
287  // See the math behind at: http://www.terathon.com/code/tangent.html
288  vec3 n = normalize(nMatrix * ${localNormal});
289  vec3 t = normalize(nMatrix * ${localTangent}.xyz);
290  vec3 b = cross(n, t) * ${localTangent}.w; // bitangent w. corrected handedness
291  mat3 TBN = mat3(t,b,n);
292 
293  // Transform vector to the eye into tangent space
294  v_eyeDirTS = -v_P_VS; // eye vector in view space
295  v_eyeDirTS *= TBN;
296 
297  for (int i = 0; i < NUM_LIGHTS; ++i)
298  {
299  // Transform spot direction into tangent space
300  v_spotDirTS[i] = u_lightSpotDir[i];
301  v_spotDirTS[i] *= TBN;
302 
303  // Transform vector to the light 0 into tangent space
304  vec3 L = u_lightPosVS[i].xyz - v_P_VS;
305  v_lightDirTS[i] = L;
306  v_lightDirTS[i] *= TBN;
307  }
308 )";
309 
310 //-----------------------------------------------------------------------------
311 // Things that goes directly to geometry shader
312 const string vertMain_PS_v_t_default = R"(
313  if(age < 0.0)
314  vert.transparency = 0.0; // To be discard, because the particle is to be born
315  else
316  vert.transparency = 1.0;)";
317 const string vertMain_PS_v_t_begin = R"(
318  if(age < 0.0)
319  vert.transparency = 0.0; // To be discard, because the particle is to be born
320  else
321  {
322  vert.transparency = age / u_tTL; // Get by the ratio age:lifetime)";
323 const string vertMain_PS_v_t_linear = R"(
324  vert.transparency = 1.0 - vert.transparency; // Linear)";
325 const string vertMain_PS_v_t_curve = R"(
326  vert.transparency = pow(vert.transparency,3.0) * u_al_bernstein.x +
327  pow(vert.transparency,2.0) * u_al_bernstein.y +
328  vert.transparency * u_al_bernstein.z +
329  u_al_bernstein.w; // Get transparency by bezier curve)";
330 const string vertMain_PS_v_t_end = R"(
331  })";
332 const string vertMain_PS_v_r = R"(
333  vert.rotation = a_rotation;)";
334 const string vertMain_PS_v_s = R"(
335  vert.size = age / u_tTL;)";
336 const string vertMain_PS_v_s_curve = R"(
337  vert.size = pow(vert.size,3.0) * u_si_bernstein.x +
338  pow(vert.size,2.0) * u_si_bernstein.y +
339  vert.size * u_si_bernstein.z +
340  u_si_bernstein.w; // Get transparency by bezier curve)";
341 
342 const string vertMain_PS_v_doColorOverLT = R"(
343  vert.color = colorByAge(age/u_tTL);)";
344 const string vertOutput_PS_age = R"(
345 out float v_age; // Age of a particle)";
346 const string fragInput_PS_age = R"(
347 in float v_age; // Age of a particle)";
348 const string vertMain_PS_v_texNum = R"(
349  vert.texNum = a_texNum;)";
350 const string vertMain_PS_v_a = R"(
351  float age = u_time - a_startTime; // Get the age of the particle)";
352 const string vertMain_PS_v_tC = R"(
353  v_texCoord = 0.5 * (a_instancePos.xy + vec2(1.0));)";
354 const string vertMain_PS_v_age = R"(
355  v_age = age;)";
356 const string vertMain_PS_v_tC_flipbook = R"(
357  int actCI = int(mod(float(a_texNum), float(u_col)));
358  float actC = float(actCI);
359  float actR = floor(float(int(a_texNum) - actCI) / float(u_col));
360 
361  vec2 p = 0.5 * (a_instancePos.xy + vec2(1.0));
362  v_texCoord = vec2((actC + p.x)/float(u_col), 1.0 - (actR - p.y)/float(u_row));
363 )";
364 
366  vec3 position = a_instancePos;
367 )";
368 const string vertMain_PS_instanced_v_s = R"(
369  float size = age / u_tTL;)";
371  size = pow(size,3.0) * u_si_bernstein.x +
372  pow(size,2.0) * u_si_bernstein.y +
373  size * u_si_bernstein.z +
374  u_si_bernstein.w; // Get transparency by bezier curve)";
375 const string vertMain_PS_instanced_v_sS = R"(
376  position = size * position;
377  )";
379  if(age < 0.0)
380  transparency = 0.0; // To be discard, because the particle is to be born
381  else
382  transparency = 1.0;)";
384  if(age < 0.0)
385  transparency = 0.0; // To be discard, because the particle is to be born
386  else
387  {
388  transparency = age / u_tTL; // Get by the ratio age:lifetime)";
390  transparency = 1.0 - transparency; // Linear)";
392  transparency = pow(transparency,3.0) * u_al_bernstein.x +
393  pow(transparency,2.0) * u_al_bernstein.y +
394  transparency * u_al_bernstein.z +
395  u_al_bernstein.w; // Get transparency by bezier curve)";
396 const string vertMain_PS_instanced_scale = R"(
397  position = vec3(u_radiusW * position.x, u_radiusH * position.y, position.z);
398  position = u_scale * position;
399  )";
401  mat2 rot = mat2(cos(a_rotation),-sin(a_rotation),
402  sin(a_rotation), cos(a_rotation)); // Matrix of rotation
403  position = vec3(rot * position.xy, position.z);
404  )";
406 
407  // Modelview matrix multiplication with (particle position + particle generator position)
408  // Calculate position in view space
409  gl_Position = u_pMatrix * (u_vOmvMatrix * vec4(a_position, 1) + vec4(position, 0.0));
410 }
411 )";
413  //gl_Position = vec4(a_position + a_instancePos, 1);
414  gl_Position = u_pMatrix * u_vYawPMatrix * vec4(a_position + position, 1.0);
415 }
416 )";
417 
418 const string vertMain_PS_EndAll = R"(
419 
420  // Modelview matrix multiplication with (particle position + particle generator position)
421  // Calculate position in view space
422  gl_Position = u_vOmvMatrix * vec4(a_position, 1);
423 }
424 )";
426  gl_Position = vec4(a_position, 1);
427 }
428 )";
429 const string vertMain_EndAll = R"(
430 
431  // pass the vertex w. the fix-function transform
432  gl_Position = u_pMatrix * mvMatrix * ${localPosition};
433 }
434 )";
435 //-----------------------------------------------------------------------------
436 const string vertMain_PS_U_Begin = R"(
437  vec4 P = vec4(a_position.xyz, 1.0); // Need to be here for the compilation
438  gl_Position = P; // Need to be here for the compilation)";
439 const string vertMain_PS_U_v_init_p = R"(
440  tf_position = a_position; // Init the output variable)";
441 const string vertMain_PS_U_v_init_v = R"(
442  tf_velocity = a_velocity; // Init the output variable)";
443 const string vertMain_PS_U_v_init_st = R"(
444  tf_startTime = a_startTime; // Init the output variable)";
445 const string vertMain_PS_U_v_init_initV = R"(
446  tf_initialVelocity = a_initialVelocity; // Init the output variable)";
447 const string vertMain_PS_U_v_init_r = R"(
448  tf_rotation = a_rotation; // Init the output variable)";
450  tf_angularVelo = a_angularVelo; // Init the output variable)";
451 const string vertMain_PS_U_v_init_texNum = R"(
452  tf_texNum = a_texNum; // Init the output variable)";
453 const string vertMain_PS_U_v_init_initP = R"(
454  tf_initialPosition = a_initialPosition; // Init the output variable)";
455 const string vertMain_PS_U_bornDead = R"(
456  tf_startTime += u_difTime; // Add time to resume after frustum culling
457 
458  if( u_time >= tf_startTime )
459  { // Check if the particle is born
460  float age = u_time - tf_startTime; // Get the age of the particle
461  if( age > u_tTL)
462  { )";
463 const string vertMain_PS_U_reset_p = R"(
464  // The particle is past its lifetime, recycle.
465  tf_position = u_pGPosition; // Reset position)";
466 const string vertMain_PS_U_reset_shape_p = R"(
467  // The particle is past its lifetime, recycle.
468  tf_position = a_initialPosition + u_pGPosition; // Reset position)";
469 const string vertMain_PS_U_reset_v = R"(
470  tf_velocity = a_initialVelocity; // Reset velocity)";
472  tf_startTime = u_time + (age - u_tTL); // Reset start time to actual time with counter gap)";
473 const string vertMain_PS_U_reset_st = R"(
474  tf_startTime = u_time; // Reset start time to actual time)";
475 const string vertMain_PS_U_alive_p = R"(
476  } else
477  {
478  // The particle is alive, update.
479  tf_position += tf_velocity * u_deltaTime; // Scale the translation by the delta time)";
480 const string vertMain_PS_U_v_rConst = R"(
481  tf_rotation = mod(tf_rotation + (u_angularVelo*u_deltaTime), TWOPI);)";
482 const string vertMain_PS_U_v_rRange = R"(
483  tf_rotation = mod(tf_rotation + (tf_angularVelo*u_deltaTime), TWOPI);)";
484 const string vertMain_PS_U_alive_a_const = R"(
485  tf_velocity += tf_initialVelocity * u_deltaTime * u_accConst; // Amplify the velocity)";
487  tf_velocity += u_deltaTime * u_acceleration; // Amplify the velocity)";
488 const string vertMain_PS_U_alive_g = R"(
489  tf_velocity += u_deltaTime * u_gravity; // Apply gravity)";
490 const string vertMain_PS_U_alive_texNum = R"(
491  if(u_condFB == 1)
492  {
493  tf_texNum++; // Increment to draw next texture (flipbook)
494  tf_texNum = uint(mod(float(tf_texNum), float(u_col * u_row))); // Modulo to not exceed the max and reset
495  })";
496 const string vertMain_PS_U_EndAll = R"(
497  }
498  }
499 })";
500 
501 //-----------------------------------------------------------------------------
502 const string geomConfig_PS = R"(
503 layout (points) in; // Primitives that we received from vertex shader
504 layout (triangle_strip, max_vertices = 4) out; // Primitives that we will output and number of vertex that will be output)";
505 const string geomInput_PS_struct_Begin = R"(
506 in vertex { )";
507 const string geomInput_PS_struct_t = R"(
508  float transparency; // Transparency of a particle)";
509 const string geomInput_PS_struct_r = R"(
510  float rotation; // Rotation of a particle)";
511 const string geomInput_PS_struct_s = R"(
512  float size; // Size of a particle )";
513 const string geomInput_PS_struct_c = R"(
514  vec3 color; // Color of a particle )";
515 const string geomInput_PS_struct_texNum = R"(
516  uint texNum; // Num of texture in flipbook)";
517 const string geomInput_PS_struct_End = R"(
518 } vert[]; )";
519 //-----------------------------------------------------------------------------
520 const string geomInput_u_matrix_p = R"(
521 uniform mat4 u_pMatrix; // Projection matrix)";
523 uniform mat4 u_vYawPMatrix; // Projection matrix)";
524 const string geomInput_PS_u_ScaRa = R"(
525 uniform float u_scale; // Particle scale
526 uniform float u_radiusW; // Particle width radius)
527 uniform float u_radiusH; // Particle height radius)";
528 const string geomInput_PS_u_c = R"(
529 uniform vec4 u_color; // Particle color)";
530 const string geomInput_PS_u_col = R"(
531 uniform int u_col; // Number of column of flipbook texture)";
532 const string geomInput_PS_u_row = R"(
533 uniform int u_row; // Number of row of flipbook texture)";
534 //-----------------------------------------------------------------------------
535 const string geomOutput_PS_v_pC = R"(
536 out vec4 v_particleColor; // The resulting color per vertex)";
537 const string geomOutput_PS_v_tC = R"(
538 out vec2 v_texCoord; // Texture coordinate at vertex)";
539 const string vertOutput_PS_v_tC = R"(
540 out vec2 v_texCoord; // Texture coordinate at vertex)";
541 //-----------------------------------------------------------------------------
542 const string geomMain_PS_v_s = R"(
543  float scale = u_scale;)";
544 const string geomMain_PS_v_sS = R"(
545  scale *= vert[0].size;)";
546 const string geomMain_PS_v_rad = R"(
547  float radiusW = u_radiusW * scale;
548  float radiusH = u_radiusH * scale;)";
549 const string geomMain_PS_v_p = R"(
550  vec4 P = gl_in[0].gl_Position; // Position of the point that we received)";
551 const string geomMain_PS_v_rot = R"(
552  mat2 rot = mat2(cos(vert[0].rotation),-sin(vert[0].rotation),
553  sin(vert[0].rotation), cos(vert[0].rotation)); // Matrix of rotation)";
554 const string geomMain_PS_v_rotIden = R"(
555  mat2 rot = mat2(1.0, 0.0, 0.0, 1.0); // Matrix of rotation)";
556 const string geomMain_PS_v_c = R"(
557  vec4 color = u_color; // Particle color)";
558 const string geomMain_PS_v_doColorOverLT = R"(
559  vec4 color = vec4(vert[0].color, 1.0); // Particle color)";
560 const string geomMain_PS_v_withoutColor = R"(
561  vec4 color = vec4( 0.0, 0.0, 0.0, 1.0); // Particle color)";
562 const string geomMain_PS_v_cT = R"(
563  color.w *= vert[0].transparency; // Apply transparency)";
564 
565 const string geomMain_PS_fourCorners = R"(
566  //BOTTOM LEFT
567  vec4 va = vec4(P.xy + (rot * vec2(-radiusW, -radiusH)), P.z, 1); //Position in view space
568  gl_Position = u_pMatrix * va; // Calculate position in clip space
569  v_texCoord = vec2(0.0, 0.0); // Texture coordinate
570  v_particleColor = color;
571  EmitVertex();
572 
573  //BOTTOM RIGHT
574  vec4 vd = vec4(P.xy + (rot * vec2(radiusW, -radiusH)), P.z,1);
575  gl_Position = u_pMatrix * vd;
576  v_texCoord = vec2(1.0, 0.0);
577  v_particleColor = color;
578  EmitVertex();
579 
580  //TOP LEFT
581  vec4 vb = vec4(P.xy + (rot * vec2(-radiusW,radiusH)) , P.z,1);
582  gl_Position = u_pMatrix * vb;
583  v_texCoord = vec2(0.0, 1.0);
584  v_particleColor = color;
585  EmitVertex();
586 
587  //TOP RIGHT
588  vec4 vc = vec4(P.xy + (rot *vec2(radiusW, radiusH)), P.z,1);
589  gl_Position = u_pMatrix * vc;
590  v_texCoord = vec2(1.0, 1.0);
591  v_particleColor = color;
592  EmitVertex();)";
594 
595  //BOTTOM LEFT
596  vec4 va = vec4(P.xy + (rot * vec2(-radiusW, -radiusH)), P.z, 1); //Position in view space
597  gl_Position = u_pMatrix * (u_vYawPMatrix * va); // Calculate position in clip space
598  v_texCoord = vec2(0.0, 0.0); // Texture coordinate
599  v_particleColor = color;
600  EmitVertex();
601 
602  //BOTTOM RIGHT
603  vec4 vd = vec4(P.xy + (rot * vec2(radiusW, -radiusH)), P.z,1);
604  gl_Position = u_pMatrix * (u_vYawPMatrix *vd);
605  v_texCoord = vec2(1.0, 0.0);
606  v_particleColor = color;
607  EmitVertex();
608 
609  //TOP LEFT
610  vec4 vb = vec4(P.xy + (rot * vec2(-radiusW,radiusH)) , P.z,1);
611  gl_Position = u_pMatrix * (u_vYawPMatrix * vb);
612  v_texCoord = vec2(0.0, 1.0);
613  v_particleColor = color;
614  EmitVertex();
615 
616  //TOP RIGHT
617  vec4 vc = vec4(P.xy + (rot *vec2(radiusW, radiusH)), P.z,1);
618  gl_Position = u_pMatrix * (u_vYawPMatrix * vc);
619  v_texCoord = vec2(1.0, 1.0);
620  v_particleColor = color;
621  EmitVertex(); )";
623 
624  //FRONT LEFT
625  vec4 va = vec4(P.xyz, 1); //Position in view space
626  va.xz = va.xz + (rot * vec2(-radiusW, -radiusH));
627  gl_Position = u_pMatrix * u_vOmvMatrix * va; // Calculate position in clip space
628  v_texCoord = vec2(0.0, 0.0); // Texture coordinate
629  v_particleColor = color;
630  EmitVertex();
631 
632  //FRONT RIGHT
633  vec4 vd = vec4(P.xyz,1);
634  vd.xz += (rot * vec2(radiusW, -radiusH));
635  gl_Position = u_pMatrix * u_vOmvMatrix * vd;
636  v_texCoord = vec2(1.0, 0.0);
637  v_particleColor = color;
638  EmitVertex();
639 
640  //BACK LEFT
641  vec4 vb = vec4(P.xyz,1);
642  vb.xz += (rot * vec2(-radiusW,radiusH));
643  gl_Position = u_pMatrix * u_vOmvMatrix * vb;
644  v_texCoord = vec2(0.0, 1.0);
645  v_particleColor = color;
646  EmitVertex();
647 
648  //BACK RIGHT
649  vec4 vc = vec4(P.xyz,1);
650  vc.xz += (rot * vec2(radiusW, radiusH));
651  gl_Position = u_pMatrix * u_vOmvMatrix * vc;
652  v_texCoord = vec2(1.0, 1.0);
653  v_particleColor = color;
654  EmitVertex(); )";
656  uint actCI = uint(mod(float(uint(vert[0].texNum), float(u_col)));
657  uint actRI = (vert[0].texNum - actCI) / u_col;
658  float actC = float(actCI);
659  float actR = float(actRI);
660 
661  //BOTTOM LEFT
662  vec4 va = vec4(P.xy + (rot * vec2(-radiusW, -radiusH)), P.z, 1); //Position in view space
663  gl_Position = u_pMatrix * va; // Calculate position in clip space
664  v_texCoord = vec2(actC/u_col, 1.0-((actR+1.0)/u_row)); // Texture coordinate
665  v_particleColor = color;
666  EmitVertex();
667 
668  //BOTTOM RIGHT
669  vec4 vd = vec4(P.xy + (rot * vec2(radiusW, -radiusH)), P.z,1);
670  gl_Position = u_pMatrix * vd;
671  v_texCoord = vec2((actC+1.0)/u_col, 1.0-((actR+1.0)/u_row)); // Texture coordinate
672  v_particleColor = color;
673  EmitVertex();
674 
675  //TOP LEFT
676  vec4 vb = vec4(P.xy + (rot * vec2(-radiusW,radiusH)) , P.z,1);
677  gl_Position = u_pMatrix * vb;
678  v_texCoord = vec2(actC/u_col, 1.0-(actR/u_row)); // Texture coordinate
679  v_particleColor = color;
680  EmitVertex();
681 
682  //TOP RIGHT
683  vec4 vc = vec4(P.xy + (rot *vec2(radiusW, radiusH)), P.z,1);
684  gl_Position = u_pMatrix * vc;
685  v_texCoord = vec2((actC+1.0)/u_col, 1.0-(actR/u_row)); // Texture coordinate
686  v_particleColor = color;
687  EmitVertex(); )";
689  uint actCI = uint(mod(float(vert[0].texNum), float(u_col)));
690  uint actRI = uint((float(vert[0].texNum) - float(actCI)) / float(u_col));
691  float actC = float(actCI);
692  float actR = float(actRI);
693 
694  //FRONT LEFT
695  vec4 va = vec4(P.xyz, 1); //Position in view space
696  va.xz = va.xz + (rot * vec2(-radiusW, -radiusH));
697  gl_Position = u_pMatrix * u_vOmvMatrix * va; // Calculate position in clip space
698  v_texCoord = vec2(actC/u_col, 1.0-((actR+1.0)/u_row)); // Texture coordinate
699  v_particleColor = color;
700  EmitVertex();
701 
702  //FRONT RIGHT
703  vec4 vd = vec4(P.xyz,1);
704  vd.xz += (rot * vec2(radiusW, -radiusH));
705  gl_Position = u_pMatrix * u_vOmvMatrix * vd;
706  v_texCoord = vec2((actC+1.0)/u_col, 1.0-((actR+1.0)/u_row)); // Texture coordinate
707  v_particleColor = color;
708  EmitVertex();
709 
710  //BACK LEFT
711  vec4 vb = vec4(P.xyz,1);
712  vb.xz += (rot * vec2(-radiusW,radiusH));
713  gl_Position = u_pMatrix * u_vOmvMatrix * vb;
714  v_texCoord = vec2(actC/u_col, 1.0-(actR/u_row)); // Texture coordinate
715  v_particleColor = color;
716  EmitVertex();
717 
718  //BACK RIGHT
719  vec4 vc = vec4(P.xyz,1);
720  vc.xz += (rot * vec2(radiusW, radiusH));
721  gl_Position = u_pMatrix * u_vOmvMatrix * vc;
722  v_texCoord = vec2((actC+1.0)/u_col, 1.0-(actR/u_row)); // Texture coordinate
723  v_particleColor = color;
724  EmitVertex(); )";
726  uint actCI = uint(mod(float(vert[0].texNum), float(u_col)));
727  uint actRI = uint((float(vert[0].texNum) - float(actCI)) / float(u_col));
728  float actC = float(actCI);
729  float actR = float(actRI);
730 
731  //BOTTOM LEFT
732  vec4 va = vec4(P.xy + (rot * vec2(-radiusW, -radiusH)), P.z, 1); //Position in view space
733  gl_Position = u_pMatrix * (u_vYawPMatrix * va); // Calculate position in clip space
734  v_texCoord = vec2(actC/float(u_col), 1.0-((actR+1.0)/float(u_row))); // Texture coordinate
735  v_particleColor = color;
736  EmitVertex();
737 
738  //BOTTOM RIGHT
739  vec4 vd = vec4(P.xy + (rot * vec2(radiusW, -radiusH)), P.z,1);
740  gl_Position = u_pMatrix * (u_vYawPMatrix * vd);
741  v_texCoord = vec2((actC+1.0)/float(u_col), 1.0-((actR+1.0)/float(u_row))); // Texture coordinate
742  v_particleColor = color;
743  EmitVertex();
744 
745  //TOP LEFT
746  vec4 vb = vec4(P.xy + (rot * vec2(-radiusW,radiusH)) , P.z,1);
747  gl_Position = u_pMatrix * (u_vYawPMatrix * vb);
748  v_texCoord = vec2(actC/float(u_col), 1.0-(actR/float(u_row))); // Texture coordinate
749  v_particleColor = color;
750  EmitVertex();
751 
752  //TOP RIGHT
753  vec4 vc = vec4(P.xy + (rot *vec2(radiusW, radiusH)), P.z,1);
754  gl_Position =u_pMatrix * (u_vYawPMatrix * vc);
755  v_texCoord = vec2((actC+1.0)/float(u_col), 1.0-(actR/float(u_row))); // Texture coordinate
756  v_particleColor = color;
757  EmitVertex(); )";
758 
759 const string geomMain_PS_EndAll = R"(
760 
761  EndPrimitive(); // Send primitives to fragment shader
762 } )";
763 //-----------------------------------------------------------------------------
764 const string fragInput_v_P_VS = R"(
765 in vec3 v_P_VS; // Interpol. point of illumination in view space (VS))";
766 const string fragInput_v_P_WS = R"(
767 in vec3 v_P_WS; // Interpol. point of illumination in world space (WS))";
768 const string fragInput_v_N_VS = R"(
769 in vec3 v_N_VS; // Interpol. normal at v_P_VS in view space)";
770 const string fragInput_v_R_OS = R"(
771 in vec3 v_R_OS; // Interpol. reflect in object space)";
772 const string fragInput_v_uv0 = R"(
773 in vec2 v_uv0; // Texture coordinate varying for uv 0)";
774 const string fragInput_v_uv1 = R"(
775 in vec2 v_uv1; // Texture coordinate varying for uv 1)";
776 const string fragInput_v_lightVecTS = R"(
777 in vec3 v_eyeDirTS; // Vector to the eye in tangent space
778 in vec3 v_lightDirTS[NUM_LIGHTS]; // Vector to light 0 in tangent space
779 in vec3 v_spotDirTS[NUM_LIGHTS]; // Spot direction in tangent space)";
780 //-----------------------------------------------------------------------------
781 const string fragInput_PS_v_pC = R"(
782 in vec4 v_particleColor; // interpolated color from the geometry shader)";
783 const string fragInput_PS_v_tC = R"(
784 in vec2 v_texCoord; // interpolated texture coordinate)";
785 //-----------------------------------------------------------------------------
786 const string fragInput_PS_u_overG = R"(
787 uniform float u_oneOverGamma; // 1.0f / Gamma correction value)";
788 const string fragInput_PS_u_wireFrame = R"(
789 uniform bool u_doWireFrame; // Boolean for wireFrame)";
790 //-----------------------------------------------------------------------------
791 const string fragMain_PS_TF = R"(
792  o_fragColor = vec4(0,0,0,0); // Need to be here for the compilation
793 }
794 )";
795 //-----------------------------------------------------------------------------
796 const string fragMain_PS = R"(
797  // Just set the interpolated color from the vertex shader
798  o_fragColor = v_particleColor;
799 
800  // componentwise multiply w. texture color
801  if(!u_doWireFrame)
802  o_fragColor *= texture(u_matTextureDiffuse0, v_texCoord);
803 
804  if(o_fragColor.a < 0.001)
805  discard;
806 )";
807 const string fragMain_PS_withoutColor = R"(
808  // componentwise multiply w. texture color
809  if(!u_doWireFrame)
810  o_fragColor = texture(u_matTextureDiffuse0, v_texCoord);
811  else
812  o_fragColor = vec4(0,0,0,1.0);
813 
814  o_fragColor.a *= v_particleColor.a;
815 
816  if(o_fragColor.a < 0.001)
817  discard;
818 )";
820  // componentwise multiply w. texture color
821  if(!u_doWireFrame)
822  o_fragColor = texture(u_matTextureDiffuse0, v_texCoord);
823  else
824  o_fragColor = vec4(0,0,0,1.0);
825 
826  o_fragColor.a *= transparency;
827 
828  if(o_fragColor.a < 0.001)
829  discard;
830 )";
831 const string fragMain_instanced_PS_end = R"(
832  // Just set the interpolated color from the vertex shader
833  o_fragColor = color;
834  // componentwise multiply w. texture color
835  if(!u_doWireFrame)
836  o_fragColor *= texture(u_matTextureDiffuse0, v_texCoord);
837 
838  if(o_fragColor.a < 0.001)
839  discard;
840 )";
841 const string fragMain_PS_endAll = R"(
842  //Same color for each wireframe
843  if(u_doWireFrame)
844  o_fragColor = vec4(0,0,0,1.0);
845 
846  o_fragColor.rgb = pow(o_fragColor.rgb, vec3(u_oneOverGamma));
847 })";
848 //-----------------------------------------------------------------------------
849 const string fragInput_u_lightAll = R"(
850 
851 uniform bool u_lightIsOn[NUM_LIGHTS]; // flag if light is on
852 uniform vec4 u_lightPosVS[NUM_LIGHTS]; // position of light in view space
853 uniform vec4 u_lightAmbi[NUM_LIGHTS]; // ambient light intensity (Ia)
854 uniform vec4 u_lightDiff[NUM_LIGHTS]; // diffuse light intensity (Id)
855 uniform vec4 u_lightSpec[NUM_LIGHTS]; // specular light intensity (Is)
856 uniform vec3 u_lightSpotDir[NUM_LIGHTS]; // spot direction in view space
857 uniform float u_lightSpotDeg[NUM_LIGHTS]; // spot cutoff angle 1-180 degrees
858 uniform float u_lightSpotCos[NUM_LIGHTS]; // cosine of spot cutoff angle
859 uniform float u_lightSpotExp[NUM_LIGHTS]; // spot exponent
860 uniform vec3 u_lightAtt[NUM_LIGHTS]; // attenuation (const,linear,quadr.)
861 uniform bool u_lightDoAtt[NUM_LIGHTS]; // flag if att. must be calc.
862 uniform vec4 u_globalAmbi; // Global ambient scene color
863 uniform float u_oneOverGamma; // 1.0f / Gamma correction value
864 )";
865 const string fragInput_u_matBlinnAll = R"(
866 uniform vec4 u_matAmbi; // ambient color reflection coefficient (ka)
867 uniform vec4 u_matDiff; // diffuse color reflection coefficient (kd)
868 uniform vec4 u_matSpec; // specular color reflection coefficient (ks)
869 uniform vec4 u_matEmis; // emissive color for self-shining materials
870 uniform float u_matShin; // shininess exponent
871 )";
872 const string fragInput_u_matAmbi = R"(
873 uniform vec4 u_matAmbi; // ambient color reflection coefficient (ka))";
874 const string fragInput_u_matDiff = R"(
875 uniform vec4 u_matDiff; // diffuse color reflection coefficient (kd))";
876 const string fragInput_u_matEmis = R"(
877 uniform vec4 u_matEmis; // emissive color (ke))";
878 const string fragInput_u_matRough = R"(
879 uniform float u_matRough; // roughness factor (0-1))";
880 const string fragInput_u_matMetal = R"(
881 uniform float u_matMetal; // metalness factor (0-1)";
882 //-----------------------------------------------------------------------------
883 const string fragInput_u_matTexDm = R"(
884 uniform sampler2D u_matTextureDiffuse0; // Diffuse color map)";
885 const string fragInput_u_matTexNm = R"(
886 uniform sampler2D u_matTextureNormal0; // Normal bump map)";
887 const string fragInput_u_matTexEm = R"(
888 uniform sampler2D u_matTextureEmissive0; // PBR material emissive texture)";
889 const string fragInput_u_matTexOm = R"(
890 uniform sampler2D u_matTextureOcclusion0; // Ambient occlusion map)";
891 const string fragInput_u_matTexRm = R"(
892 uniform sampler2D u_matTextureRoughness0; // PBR material roughness texture)";
893 const string fragInput_u_matTexMm = R"(
894 uniform sampler2D u_matTextureMetallic0; // PBR material metallic texture)";
895 const string fragInput_u_matTexRmMm = R"(
896 uniform sampler2D u_matTextureRoughMetal0; // PBR material roughness-metallic texture)";
897 const string fragInput_u_matTexOmRmMm = R"(
898 uniform sampler2D u_matTextureOccluRoughMetal0; // PBR material occlusion-roughness-metalic texture)";
899 const string fragInput_u_matGetsSm = R"(
900 
901 uniform bool u_matGetsShadows; // flag if material receives shadows)";
902 const string fragInput_u_skyCookEnvMaps = R"(
903 uniform samplerCube u_skyIrradianceCubemap; // PBR skybox irradiance light
904 uniform samplerCube u_skyRoughnessCubemap; // PBR skybox cubemap for rough reflections
905 uniform sampler2D u_skyBrdfLutTexture; // PBR lighting lookup table for BRDF
906 uniform float u_skyExposure; // PBR skybox exposure)";
907 //-----------------------------------------------------------------------------
908 const string fragInput_u_cam = R"(
909 
910 uniform int u_camProjType; // type of stereo
911 uniform int u_camStereoEye; // -1=left, 0=center, 1=right
912 uniform mat3 u_camStereoColors; // color filter matrix
913 uniform bool u_camFogIsOn; // flag if fog is on
914 uniform int u_camFogMode; // 0=LINEAR, 1=EXP, 2=EXP2
915 uniform float u_camFogDensity; // fog density value
916 uniform float u_camFogStart; // fog start distance
917 uniform float u_camFogEnd; // fog end distance
918 uniform vec4 u_camFogColor; // fog color (usually the background)
919 uniform float u_camClipNear; // camera near plane
920 uniform float u_camClipFar; // camera far plane
921 uniform float u_camBkgdWidth; // camera background width
922 uniform float u_camBkgdHeight; // camera background height
923 uniform float u_camBkgdLeft; // camera background left
924 uniform float u_camBkgdBottom; // camera background bottom)";
925 //-----------------------------------------------------------------------------
926 const string fragOutputs_o_fragColor = R"(
927 
928 out vec4 o_fragColor; // output fragment color)";
929 //-----------------------------------------------------------------------------
931 //-----------------------------------------------------------------------------
932 void directLightBlinnPhong(in int i, // Light number between 0 and NUM_LIGHTS
933  in vec3 N, // Normalized normal at v_P
934  in vec3 E, // Normalized direction at v_P to the eye
935  in vec3 S, // Normalized light spot direction
936  in float shadow, // shadow factor
937  inout vec4 Ia, // Ambient light intensity
938  inout vec4 Id, // Diffuse light intensity
939  inout vec4 Is) // Specular light intensity
940 {
941  // Calculate diffuse & specular factors
942  float diffFactor = max(dot(N, S), 0.0);
943  float specFactor = 0.0;
944 
945  if (diffFactor!=0.0)
946  {
947  vec3 H = normalize(S + E);// Half vector H between S and E
948  specFactor = pow(max(dot(N, H), 0.0), u_matShin);
949  }
950 
951  // accumulate directional light intensities w/o attenuation
952  Ia += u_lightAmbi[i];
953  Id += u_lightDiff[i] * diffFactor * (1.0 - shadow);
954  Is += u_lightSpec[i] * specFactor * (1.0 - shadow);
955 }
956 //-----------------------------------------------------------------------------
957 void pointLightBlinnPhong( in int i,
958  in vec3 N,
959  in vec3 E,
960  in vec3 S,
961  in vec3 L,
962  in float shadow,
963  inout vec4 Ia,
964  inout vec4 Id,
965  inout vec4 Is)
966 {
967  // Calculate attenuation over distance & normalize L
968  float att = 1.0;
969  if (u_lightDoAtt[i])
970  {
971  vec3 att_dist;
972  att_dist.x = 1.0;
973  att_dist.z = dot(L, L);// = distance * distance
974  att_dist.y = sqrt(att_dist.z);// = distance
975  att = min(1.0 / dot(att_dist, u_lightAtt[i]), 1.0);
976  L /= att_dist.y;// = normalize(L)
977  }
978  else
979  L = normalize(L);
980 
981  // Calculate diffuse & specular factors
982  vec3 H = normalize(E + L); // Blinn's half vector is faster than Phongs reflected vector
983  float diffFactor = max(dot(N, L), 0.0); // Lambertian downscale factor for diffuse reflection
984  float specFactor = 0.0;
985  if (diffFactor!=0.0) // specular reflection is only possible if surface is lit from front
986  specFactor = pow(max(dot(N, H), 0.0), u_matShin); // specular shininess
987 
988  // Calculate spot attenuation
989  float spotAtt = 1.0;// Spot attenuation
990  if (u_lightSpotDeg[i] < 180.0)
991  {
992  float spotDot;// Cosine of angle between L and spotdir
993  spotDot = dot(-L, S);
994  if (spotDot < u_lightSpotCos[i]) // if outside spot cone
995  spotAtt = 0.0;
996  else
997  spotAtt = max(pow(spotDot, u_lightSpotExp[i]), 0.0);
998  }
999 
1000  // Accumulate light intensities
1001  Ia += att * u_lightAmbi[i];
1002  Id += att * spotAtt * u_lightDiff[i] * diffFactor * (1.0 - shadow);
1003  Is += att * spotAtt * u_lightSpec[i] * specFactor * (1.0 - shadow);
1004 })";
1005 //-----------------------------------------------------------------------------
1007 //-----------------------------------------------------------------------------
1008 vec3 fresnelSchlick(float cosTheta, vec3 F0)
1009 {
1010  return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
1011 }
1012 // ----------------------------------------------------------------------------
1013 vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
1014 {
1015  return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
1016 }
1017 //-----------------------------------------------------------------------------
1018 float distributionGGX(vec3 N, vec3 H, float roughness)
1019 {
1020  float PI = 3.14159265;
1021  float a = roughness*roughness;
1022  float a2 = a*a;
1023  float NdotH = max(dot(N, H), 0.0);
1024  float NdotH2 = NdotH*NdotH;
1025 
1026  float nom = a2;
1027  float denom = (NdotH2 * (a2 - 1.0) + 1.0);
1028  denom = PI * denom * denom;
1029 
1030  return nom / denom;
1031 }
1032 //-----------------------------------------------------------------------------
1033 float geometrySchlickGGX(float NdotV, float roughness)
1034 {
1035  float r = (roughness + 1.0);
1036  float k = (r*r) / 8.0;
1037 
1038  float nom = NdotV;
1039  float denom = NdotV * (1.0 - k) + k;
1040 
1041  return nom / denom;
1042 }
1043 //-----------------------------------------------------------------------------
1044 float geometrySmith(vec3 N, vec3 E, vec3 L, float roughness)
1045 {
1046  float NdotV = max(dot(N, E), 0.0);
1047  float NdotL = max(dot(N, L), 0.0);
1048  float ggx2 = geometrySchlickGGX(NdotV, roughness);
1049  float ggx1 = geometrySchlickGGX(NdotL, roughness);
1050  return ggx1 * ggx2;
1051 }
1052 //-----------------------------------------------------------------------------
1053 void directLightCookTorrance(in int i, // Light index
1054  in vec3 N, // Normalized normal at v_P_VS
1055  in vec3 E, // Normalized vector from v_P to the eye
1056  in vec3 S, // Normalized light spot direction
1057  in vec3 F0, // Fresnel reflection at 90 deg. (0 to N)
1058  in vec3 matDiff, // diffuse material reflection
1059  in float matMetal, // diffuse material reflection
1060  in float matRough, // diffuse material reflection
1061  in float shadow, // shadow factor (0.0 - 1.0)
1062  inout vec3 Lo) // reflected intensity
1063 {
1064  float PI = 3.14159265;
1065  vec3 H = normalize(E + S); // Normalized halfvector between eye and light vector
1066 
1067  vec3 radiance = u_lightDiff[i].rgb; // Per light radiance without attenuation
1068 
1069  // cook-torrance brdf
1070  float NDF = distributionGGX(N, H, matRough);
1071  float G = geometrySmith(N, E, S, matRough);
1072  vec3 F = fresnelSchlick(max(dot(H, E), 0.0), F0);
1073 
1074  vec3 kS = F;
1075  vec3 kD = vec3(1.0) - kS;
1076  kD *= 1.0 - matMetal;
1077 
1078  vec3 nominator = NDF * G * F;
1079  float denominator = 4.0 * max(dot(N, E), 0.0) * max(dot(N, S), 0.0) + 0.001;
1080  vec3 specular = nominator / denominator;
1081 
1082  // add to outgoing radiance Lo
1083  float NdotL = max(dot(N, S), 0.0);
1084 
1085  Lo += (kD*matDiff.rgb/PI + specular) * radiance * NdotL * (1.0 - shadow);
1086 }
1087 //-----------------------------------------------------------------------------
1088 void pointLightCookTorrance(in int i, // Light index
1089  in vec3 N, // Normalized normal at v_P_VS
1090  in vec3 E, // Normalized vector from v_P to the eye
1091  in vec3 L, // Vector from v_P to the light
1092  in vec3 S, // Normalized light spot direction
1093  in vec3 F0, // Fresnel reflection at 90 deg. (0 to N)
1094  in vec3 matDiff, // diffuse material reflection
1095  in float matMetal, // diffuse material reflection
1096  in float matRough, // diffuse material reflection
1097  in float shadow, // shadow factor (0.0 - 1.0)
1098  inout vec3 Lo) // reflected intensity
1099 {
1100  float PI = 3.14159265;
1101  float distance = length(L); // distance to light
1102  L /= distance; // normalize light vector
1103  float att = 1.0 / (distance*distance); // quadratic light attenuation
1104 
1105  // Calculate spot attenuation
1106  if (u_lightSpotDeg[i] < 180.0)
1107  {
1108  float spotAtt; // Spot attenuation
1109  float spotDot; // Cosine of angle between L and spotdir
1110  spotDot = dot(-L, S);
1111  if (spotDot < u_lightSpotCos[i]) spotAtt = 0.0;
1112  else spotAtt = max(pow(spotDot, u_lightSpotExp[i]), 0.0);
1113  att *= spotAtt;
1114  }
1115 
1116  vec3 radiance = u_lightDiff[i].rgb * att; // per light radiance
1117 
1118  // cook-torrance brdf
1119  vec3 H = normalize(E + L); // Normalized halfvector between eye and light vector
1120  float NDF = distributionGGX(N, H, matRough);
1121  float G = geometrySmith(N, E, L, matRough);
1122  vec3 F = fresnelSchlick(max(dot(H, E), 0.0), F0);
1123 
1124  vec3 kS = F;
1125  vec3 kD = vec3(1.0) - kS;
1126  kD *= 1.0 - matMetal;
1127 
1128  vec3 nominator = NDF * G * F;
1129  float denominator = 4.0 * max(dot(N, E), 0.0) * max(dot(N, L), 0.0) + 0.001;
1130  vec3 specular = nominator / denominator;
1131 
1132  // add to outgoing radiance Lo
1133  float NdotL = max(dot(N, L), 0.0);
1134 
1135  Lo += (kD*matDiff.rgb/PI + specular) * radiance * NdotL * (1.0 - shadow);
1136 })";
1137 //-----------------------------------------------------------------------------
1139 //-----------------------------------------------------------------------------
1140 void doStereoSeparation()
1141 {
1142  // See SLProjType in SLEnum.h
1143  if (u_camProjType > 8) // stereoColors
1144  {
1145  // Apply color filter but keep alpha
1146  o_fragColor.rgb = u_camStereoColors * o_fragColor.rgb;
1147  }
1148  else if (u_camProjType == 6) // stereoLineByLine
1149  {
1150  if (mod(floor(gl_FragCoord.y), 2.0) < 0.5)// even
1151  {
1152  if (u_camStereoEye ==-1)
1153  discard;
1154  } else // odd
1155  {
1156  if (u_camStereoEye == 1)
1157  discard;
1158  }
1159  }
1160  else if (u_camProjType == 7) // stereoColByCol
1161  {
1162  if (mod(floor(gl_FragCoord.x), 2.0) < 0.5)// even
1163  {
1164  if (u_camStereoEye ==-1)
1165  discard;
1166  } else // odd
1167  {
1168  if (u_camStereoEye == 1)
1169  discard;
1170  }
1171  }
1172  else if (u_camProjType == 8) // stereoCheckerBoard
1173  {
1174  bool h = (mod(floor(gl_FragCoord.x), 2.0) < 0.5);
1175  bool v = (mod(floor(gl_FragCoord.y), 2.0) < 0.5);
1176  if (h==v)// both even or odd
1177  {
1178  if (u_camStereoEye ==-1)
1179  discard;
1180  } else // odd
1181  {
1182  if (u_camStereoEye == 1)
1183  discard;
1184  }
1185  }
1186 })";
1187 //-----------------------------------------------------------------------------
1188 const string fragFunctionFogBlend = R"(
1189 //-----------------------------------------------------------------------------
1190 vec4 fogBlend(vec3 P_VS, vec4 inColor)
1191 {
1192  float factor = 0.0f;
1193  float distance = length(P_VS);
1194 
1195  switch (u_camFogMode)
1196  {
1197  case 0:
1198  factor = (u_camFogEnd - distance) / (u_camFogEnd - u_camFogStart);
1199  break;
1200  case 1:
1201  factor = exp(-u_camFogDensity * distance);
1202  break;
1203  default:
1204  factor = exp(-u_camFogDensity * distance * u_camFogDensity * distance);
1205  break;
1206  }
1207 
1208  vec4 outColor = factor * inColor + (1.0 - factor) * u_camFogColor;
1209  outColor = clamp(outColor, 0.0, 1.0);
1210  return outColor;
1211 })";
1212 //-----------------------------------------------------------------------------
1214 //-----------------------------------------------------------------------------
1215 void doColoredShadows(in vec3 N)
1216 {
1217  const vec3 SHADOW_COLOR[6] = vec3[6](vec3(1.0, 0.0, 0.0),
1218  vec3(0.0, 1.0, 0.0),
1219  vec3(0.0, 0.0, 1.0),
1220  vec3(1.0, 1.0, 0.0),
1221  vec3(0.0, 1.0, 1.0),
1222  vec3(1.0, 0.0, 1.0));
1223 
1224  for (int i = 0; i < NUM_LIGHTS; ++i)
1225  {
1226  if (u_lightIsOn[i])
1227  {
1228  if (u_lightPosVS[i].w == 0.0)
1229  {
1230  // We use the spot light direction as the light direction vector
1231  vec3 S = normalize(-u_lightSpotDir[i].xyz);
1232 
1233  // Test if the current fragment is in shadow
1234  float shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0;
1235  if (u_lightNumCascades[i] > 0)
1236  {
1237  int casIndex = getCascadesDepthIndex(i, u_lightNumCascades[i]);
1238  o_fragColor.rgb += shadow * SHADOW_COLOR[casIndex];
1239  } else
1240  o_fragColor.rgb += shadow * SHADOW_COLOR[0];
1241  }
1242  else
1243  {
1244  vec3 L = u_lightPosVS[i].xyz - v_P_VS; // Vector from v_P to light in VS
1245 
1246  // Test if the current fragment is in shadow
1247  float shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0;
1248  o_fragColor.rgb += shadow * SHADOW_COLOR[0];
1249  }
1250  }
1251  }
1252 })";
1253 //-----------------------------------------------------------------------------
1254 const string fragMain_0_Intensities = R"(
1255  vec4 Ia = vec4(0.0); // Accumulated ambient light intensity at v_P_VS
1256  vec4 Id = vec4(0.0); // Accumulated diffuse light intensity at v_P_VS
1257  vec4 Is = vec4(0.0); // Accumulated specular light intensity at v_P_VS
1258 )";
1259 //-----------------------------------------------------------------------------
1260 const string fragMain_1_EN_in_VS = R"(
1261  vec3 E = normalize(-v_P_VS); // Interpolated vector from p to the eye
1262  vec3 N = normalize(v_N_VS); // A input normal has not anymore unit length
1263 )";
1264 const string fragMain_1_EN_in_TS = R"(
1265  vec3 E = normalize(v_eyeDirTS); // normalized interpolated eye direction
1266 
1267  // Get normal from normal map, move from [0,1] to [-1, 1] range & normalize
1268  vec3 N = normalize(texture(u_matTextureNormal0, v_uv0).rgb * 2.0 - 1.0);
1269 )";
1270 const string fragMain_1_matEmis = R"(
1271  vec4 matEmis = u_matEmis;)";
1272 const string fragMain_1_matEmis_Em = R"(
1273  vec4 matEmis = texture(u_matTextureEmissive0, v_uv0);)";
1274 const string fragMain_1_matOccl = R"(
1275  float matOccl = 1.0;)";
1276 const string fragMain_1_matOccl_Om0 = R"(
1277  float matOccl = texture(u_matTextureOcclusion0, v_uv0).r;)";
1278 const string fragMain_1_matOccl_Om1 = R"(
1279  float matOccl = texture(u_matTextureOcclusion0, v_uv1).r;)";
1280 //-----------------------------------------------------------------------------
1281 const string fragMainBlinn_2_LightLoop = R"(
1282 
1283  // Get the reflection from all lights into Ia, Id & Is
1284  for (int i = 0; i < NUM_LIGHTS; ++i)
1285  {
1286  if (u_lightIsOn[i])
1287  {
1288  if (u_lightPosVS[i].w == 0.0)
1289  {
1290  // We use the spot light direction as the light direction vector
1291  vec3 S = normalize(-u_lightSpotDir[i].xyz);
1292  directLightBlinnPhong(i, N, E, S, 0.0, Ia, Id, Is);
1293  }
1294  else
1295  {
1296  vec3 S = u_lightSpotDir[i]; // normalized spot direction in VS
1297  vec3 L = u_lightPosVS[i].xyz - v_P_VS; // Vector from v_P to light in VS
1298  pointLightBlinnPhong(i, N, E, S, L, 0.0, Ia, Id, Is);
1299  }
1300  }
1301  }
1302 )";
1304 
1305  // Get the reflection from all lights into Ia, Id & Is
1306  for (int i = 0; i < NUM_LIGHTS; ++i)
1307  {
1308  if (u_lightIsOn[i])
1309  {
1310  if (u_lightPosVS[i].w == 0.0)
1311  {
1312  // We use the spot light direction as the light direction vector
1313  vec3 S = normalize(-v_spotDirTS[i]);
1314  directLightBlinnPhong(i, N, E, S, 0.0, Ia, Id, Is);
1315  }
1316  else
1317  {
1318  vec3 S = normalize(v_spotDirTS[i]); // normalized spot direction in TS
1319  vec3 L = v_lightDirTS[i]; // Vector from v_P to light in TS
1320  pointLightBlinnPhong(i, N, E, S, L, 0.0, Ia, Id, Is);
1321  }
1322  }
1323  }
1324 )";
1326 
1327  // Get the reflection from all lights into Ia, Id & Is
1328  for (int i = 0; i < NUM_LIGHTS; ++i)
1329  {
1330  if (u_lightIsOn[i])
1331  {
1332  if (u_lightPosVS[i].w == 0.0)
1333  {
1334  // We use the spot light direction as the light direction vector
1335  vec3 S = normalize(-u_lightSpotDir[i].xyz);
1336 
1337  // Test if the current fragment is in shadow
1338  float shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0;
1339  directLightBlinnPhong(i, N, E, S, shadow, Ia, Id, Is);
1340  }
1341  else
1342  {
1343  vec3 S = u_lightSpotDir[i]; // normalized spot direction in VS
1344  vec3 L = u_lightPosVS[i].xyz - v_P_VS; // Vector from v_P to light in VS
1345 
1346  // Test if the current fragment is in shadow
1347  float shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0;
1348  pointLightBlinnPhong(i, N, E, S, L, shadow, Ia, Id, Is);
1349  }
1350  }
1351  }
1352 )";
1354 
1355  // Get the reflection from all lights into Ia, Id & Is
1356  for (int i = 0; i < NUM_LIGHTS; ++i)
1357  {
1358  if (u_lightIsOn[i])
1359  {
1360  if (u_lightPosVS[i].w == 0.0)
1361  {
1362  // We use the spot light direction as the light direction vector
1363  vec3 S = normalize(-v_spotDirTS[i]);
1364 
1365  // Test if the current fragment is in shadow
1366  float shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0;
1367  directLightBlinnPhong(i, N, E, S, shadow, Ia, Id, Is);
1368  }
1369  else
1370  {
1371  vec3 S = normalize(v_spotDirTS[i]); // normalized spot direction in TS
1372  vec3 L = v_lightDirTS[i]; // Vector from v_P to light in TS
1373 
1374  // Test if the current fragment is in shadow
1375  float shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0;
1376  pointLightBlinnPhong(i, N, E, S, L, shadow, Ia, Id, Is);
1377  }
1378  }
1379  }
1380 )";
1381 const string fragMainBlinn_3_FragColor = R"(
1382  // Sum up all the reflected color components
1383  o_fragColor = u_matEmis +
1384  u_globalAmbi +
1385  Ia * u_matAmbi * matOccl +
1386  Id * u_matDiff +
1387  Is * u_matSpec;
1388 
1389  // For correct alpha blending overwrite alpha component
1390  o_fragColor.a = u_matDiff.a;
1391 )";
1393  // Sum up all the reflected color components
1394  o_fragColor = u_matEmis +
1395  u_globalAmbi +
1396  Ia * u_matAmbi * matOccl +
1397  Id * u_matDiff;
1398 
1399  // Componentwise multiply w. texture color
1400  o_fragColor *= texture(u_matTextureDiffuse0, v_uv0);
1401 
1402  // add finally the specular RGB-part
1403  vec4 specColor = Is * u_matSpec;
1404  o_fragColor.rgb += specColor.rgb;
1405 )";
1406 //-----------------------------------------------------------------------------
1407 const string fragMain_4_ColoredShadows = R"(
1408  // Colorize cascaded shadows for debugging purpose
1409  if (u_lightsDoColoredShadows)
1410  doColoredShadows(N);
1411 )";
1412 //-----------------------------------------------------------------------------
1413 const string fragMain_5_FogGammaStereo = R"(
1414  // Apply fog by blending over distance
1415  if (u_camFogIsOn)
1416  o_fragColor = fogBlend(v_P_VS, o_fragColor);
1417 
1418  // Apply gamma correction
1419  o_fragColor.rgb = pow(o_fragColor.rgb, vec3(u_oneOverGamma));
1420 
1421  // Apply stereo eye separation
1422  if (u_camProjType > 1)
1423  doStereoSeparation();
1424 }
1425 )";
1426 //-----------------------------------------------------------------------------
1427 const string fragMainCook_1_matDiff = R"(
1428  vec4 matDiff = u_matDiff;)";
1429 const string fragMainCook_1_matDiff_Dm = R"(
1430  vec4 matDiff = pow(texture(u_matTextureDiffuse0, v_uv0), vec4(2.2));)";
1431 const string fragMainCook_1_matEmis = R"(
1432  vec4 matEmis = u_matEmis;)";
1433 const string fragMainCook_1_matEmis_Em = R"(
1434  vec4 matEmis = pow(texture(u_matTextureEmissive0, v_uv0), vec4(2.2));)";
1435 const string fragMainCook_1_matRough = R"(
1436  float matRough = u_matRough;)";
1437 const string fragMainCook_1_matRough_Rm = R"(
1438  float matRough = texture(u_matTextureRoughness0, v_uv0).r;)";
1440  float matRough = texture(u_matTextureRoughMetal0, v_uv0).g;)";
1442  float matRough = texture(u_matTextureOccluRoughMetal0, v_uv0).g;)";
1443 const string fragMainCook_1_matMetal = R"(
1444  float matMetal = u_matMetal;)";
1445 const string fragMainCook_1_matMetal_Mm = R"(
1446  float matMetal = texture(u_matTextureMetallic0, v_uv0).r;)";
1448  float matMetal = texture(u_matTextureRoughMetal0, v_uv0).b;)";
1450  float matMetal = texture(u_matTextureOccluRoughMetal0, v_uv0).b;)";
1451 const string fragMainCook_1_matOcclu_1 = R"(
1452  float matOccl = 1.0;)";
1454  float matOccl = texture(u_matTextureOcclusion0, v_uv0).r;)";
1456  float matOccl = texture(u_matTextureOcclusion0, v_uv1).r;)";
1458  float matOccl = texture(u_matTextureOccluRoughMetal0, v_uv0).r;)";
1459 const string fragMainCook_2_LightLoop = R"(
1460 
1461  vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N)
1462  F0 = mix(F0, matDiff.rgb, matMetal);
1463 
1464  // Get the reflection from all lights into Lo
1465  vec3 Lo = vec3(0.0);
1466  for (int i = 0; i < NUM_LIGHTS; ++i)
1467  {
1468  if (u_lightIsOn[i])
1469  {
1470  if (u_lightPosVS[i].w == 0.0)
1471  {
1472  // We use the spot light direction as the light direction vector
1473  vec3 S = normalize(-u_lightSpotDir[i].xyz);
1474  directLightCookTorrance(i, N, E, S, F0,
1475  matDiff.rgb,
1476  matMetal,
1477  matRough,
1478  0.0,
1479  Lo);
1480  }
1481  else
1482  {
1483  vec3 L = u_lightPosVS[i].xyz - v_P_VS;
1484  vec3 S = u_lightSpotDir[i]; // normalized spot direction in VS
1485  pointLightCookTorrance( i, N, E, L, S, F0,
1486  matDiff.rgb,
1487  matMetal,
1488  matRough,
1489  0.0,
1490  Lo);
1491  }
1492  }
1493  }
1494 )";
1495 const string fragMainCook_2_LightLoopNm = R"(
1496 
1497  vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N)
1498  F0 = mix(F0, matDiff.rgb, matMetal);
1499 
1500  // Get the reflection from all lights into Lo
1501  vec3 Lo = vec3(0.0);
1502  for (int i = 0; i < NUM_LIGHTS; ++i)
1503  {
1504  if (u_lightIsOn[i])
1505  {
1506  if (u_lightPosVS[i].w == 0.0)
1507  {
1508  // We use the spot light direction as the light direction vector
1509  vec3 S = normalize(-v_spotDirTS[i]);
1510  directLightCookTorrance(i, N, E, S, F0,
1511  matDiff.rgb,
1512  matMetal,
1513  matRough,
1514  0.0,
1515  Lo);
1516  }
1517  else
1518  {
1519  vec3 L = v_lightDirTS[i]; // Vector from v_P to light in TS
1520  vec3 S = normalize(-v_spotDirTS[i]);
1521  pointLightCookTorrance( i, N, E, L, S, F0,
1522  matDiff.rgb,
1523  matMetal,
1524  matRough,
1525  0.0,
1526  Lo);
1527  }
1528  }
1529  }
1530 )";
1531 const string fragMainCook_2_LightLoopSm = R"(
1532 
1533  vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N)
1534  F0 = mix(F0, matDiff.rgb, matMetal);
1535 
1536  // Get the reflection from all lights into Lo
1537  vec3 Lo = vec3(0.0);
1538  for (int i = 0; i < NUM_LIGHTS; ++i)
1539  {
1540  if (u_lightIsOn[i])
1541  {
1542  if (u_lightPosVS[i].w == 0.0)
1543  {
1544  // We use the spot light direction as the light direction vector
1545  vec3 S = normalize(-u_lightSpotDir[i].xyz);
1546 
1547  // Test if the current fragment is in shadow
1548  float shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0;
1549  directLightCookTorrance(i, N, E, S, F0,
1550  matDiff.rgb,
1551  matMetal,
1552  matRough,
1553  shadow,
1554  Lo);
1555  }
1556  else
1557  {
1558  vec3 L = u_lightPosVS[i].xyz - v_P_VS;
1559  vec3 S = u_lightSpotDir[i]; // normalized spot direction in VS
1560 
1561  // Test if the current fragment is in shadow
1562  float shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0;
1563  pointLightCookTorrance( i, N, E, L, S, F0,
1564  matDiff.rgb,
1565  matMetal,
1566  matRough,
1567  shadow,
1568  Lo);
1569  }
1570  }
1571  }
1572 )";
1574 
1575  vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N)
1576  F0 = mix(F0, matDiff.rgb, matMetal);
1577 
1578  // Get the reflection from all lights into Lo
1579  vec3 Lo = vec3(0.0);
1580  for (int i = 0; i < NUM_LIGHTS; ++i)
1581  {
1582  if (u_lightIsOn[i])
1583  {
1584  if (u_lightPosVS[i].w == 0.0)
1585  {
1586  // We use the spot light direction as the light direction vector
1587  vec3 S = normalize(-v_spotDirTS[i]);
1588 
1589  // Test if the current fragment is in shadow
1590  float shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0;
1591  directLightCookTorrance(i, N, E, S, F0,
1592  matDiff.rgb,
1593  matMetal,
1594  matRough,
1595  shadow,
1596  Lo);
1597  }
1598  else
1599  {
1600  vec3 L = v_lightDirTS[i]; // Vector from v_P to light in TS
1601  vec3 S = normalize(-v_spotDirTS[i]);
1602 
1603  // Test if the current fragment is in shadow
1604  float shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0;
1605  pointLightCookTorrance( i, N, E, L, S, F0,
1606  matDiff.rgb,
1607  matMetal,
1608  matRough,
1609  shadow,
1610  Lo);
1611  }
1612  }
1613  }
1614 )";
1615 const string fragMainCook_3_FragColor = R"(
1616  // ambient lighting (note that the next IBL tutorial will replace
1617  // this ambient lighting with environment lighting).
1618  vec3 ambient = vec3(0.03) * matDiff.rgb * matOccl;
1619 
1620  vec3 color = ambient + matEmis.rgb + Lo;
1621 
1622  // HDR tone-mapping
1623  color = color / (color + vec3(1.0));
1624  o_fragColor = vec4(color, 1.0);
1625 
1626  // For correct alpha blending overwrite alpha component
1627  o_fragColor.a = matDiff.a;
1628 )";
1630  // Build diffuse reflection from environment light map
1631  vec3 F = fresnelSchlickRoughness(max(dot(N, E), 0.0), F0, matRough);
1632  vec3 kS = F;
1633  vec3 kD = 1.0 - kS;
1634  kD *= 1.0 - matMetal;
1635  vec3 irradiance = texture(u_skyIrradianceCubemap, N).rgb;
1636  vec3 diffuse = kD * irradiance * matDiff.rgb;
1637 
1638  // sample both the pre-filter map and the BRDF lut and combine them together as per the split-sum approximation to get the IBL specular part.
1639  const float MAX_REFLECTION_LOD = 4.0;
1640  vec3 prefilteredColor = textureLod(u_skyRoughnessCubemap, v_R_OS, matRough * MAX_REFLECTION_LOD).rgb;
1641  vec2 brdf = texture(u_skyBrdfLutTexture, vec2(max(dot(N, E), 0.0), matRough)).rg;
1642  vec3 specular = prefilteredColor * (F * brdf.x + brdf.y);
1643  vec3 ambient = (diffuse + specular) * matOccl;
1644 
1645  vec3 color = ambient + matEmis.rgb + Lo;
1646 
1647  // Exposure tone mapping
1648  vec3 mapped = vec3(1.0) - exp(-color * u_skyExposure);
1649  o_fragColor = vec4(mapped, 1.0);
1650 
1651  // For correct alpha blending overwrite alpha component
1652  o_fragColor.a = matDiff.a;
1653 )";
1654 //-----------------------------------------------------------------------------
1655 const string fragMainVideoBkgd = R"(
1656  float x = (gl_FragCoord.x - u_camBkgdLeft) / u_camBkgdWidth;
1657  float y = (gl_FragCoord.y - u_camBkgdBottom) / u_camBkgdHeight;
1658 
1659  if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f)
1660  o_fragColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
1661  else
1662  o_fragColor = texture(u_matTextureDiffuse0, vec2(x, y));
1663 
1664  vec3 N = normalize(v_N_VS); // A input normal has not anymore unit length
1665  float shadow = 0.0;
1666 
1667  // Colorize cascaded shadows for debugging purpose
1668  if (u_lightsDoColoredShadows)
1669  doColoredShadows(N);
1670  else
1671  {
1672  for (int i = 0; i < NUM_LIGHTS; ++i)
1673  {
1674  if (u_lightIsOn[i])
1675  {
1676  if (u_lightPosVS[i].w == 0.0)
1677  {
1678  // We use the spot light direction as the light direction vector
1679  vec3 S = normalize(-u_lightSpotDir[i].xyz);
1680 
1681  // Test if the current fragment is in shadow
1682  shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0;
1683  }
1684  else
1685  {
1686  vec3 L = u_lightPosVS[i].xyz - v_P_VS; // Vector from v_P to light in VS
1687 
1688  // Test if the current fragment is in shadow
1689  shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0;
1690  }
1691  o_fragColor = o_fragColor * min(1.0 - shadow + u_matAmbi.r, 1.0);
1692  }
1693  }
1694  }
1695 
1696 )";
1697 //-----------------------------------------------------------------------------
1698 
1699 //-----------------------------------------------------------------------------
1700 //! Builds unique program name that identifies shader program
1701 /*! See the class information for more insights of the generated name. This
1702  function is used in advance of the code generation to check if the program
1703  already exists in the asset manager. See SLMaterial::activate.
1704  @param mat Parent material pointer
1705  @param lights Pointer of vector of lights
1706  @param programName Reference to program name string that gets built
1707 
1708  The shader program gets a unique name with the following pattern:
1709  <pre>
1710  genCook-D00-N00-E00-O01-RM00-Sky-C4s-S
1711  | | | | | | | | |
1712  | | | | | | | | + Support for GPU skinning
1713  | | | | | | | + Directional light w. 4 shadow cascades
1714  | | | | | | + Ambient light from skybox
1715  | | | | | + Roughness-metallic map with index 0 and uv 0
1716  | | | | + Ambient Occlusion map with index 0 and uv 1
1717  | | | + Emissive Map with index 0 and uv 0
1718  | | + Normal Map with index 0 and uv 0
1719  | + Diffuse Texture Mapping with index 0 and uv 0
1720  + Cook-Torrance or Blinn-Phong reflection model
1721  </pre>
1722  */
1724  SLVLight* lights,
1725  SLbool supportGPUSkinning,
1726  string& programName)
1727 {
1728  assert(mat && "No material pointer passed!");
1729  assert(lights && !lights->empty() && "No lights passed!");
1730 
1731  programName = "gen";
1732 
1733  if (mat->hasTextureType(TT_videoBkgd))
1734  programName += "VideoBkgdDm";
1735  else if (mat->reflectionModel() == RM_BlinnPhong)
1736  programName += "Blinn";
1737  else if (mat->reflectionModel() == RM_CookTorrance)
1738  programName += "Cook";
1739  else
1740  programName += "Custom";
1741 
1742  programName += mat->texturesString();
1743  programName += "-";
1744 
1745  // Add letter per light type
1746  for (auto light : *lights)
1747  {
1748  if (light->positionWS().w == 0.0f)
1749  {
1750  if (light->doCascadedShadows())
1751  programName += "C" + std::to_string(light->shadowMap()->numCascades()); // Directional light with cascaded shadowmap
1752  else
1753  programName += "D"; // Directional light
1754  }
1755  else if (light->spotCutOffDEG() < 180.0f)
1756  programName += "S"; // Spotlight
1757  else
1758  programName += "P"; // Pointlight
1759  if (light->createsShadows())
1760  programName += "s"; // Creates shadows
1761  }
1762 
1763  if (supportGPUSkinning)
1764  programName += "-S";
1765 }
1766 //-----------------------------------------------------------------------------
1767 /*! See the class information for more insights of the generated name. This
1768  function is used in advance of the code generation to check if the program
1769  already exists in the asset manager. See SLMaterial::activate.
1770  @param mat Parent material pointer
1771  @param programName Reference to program name string that gets built
1772  @param isDrawProg Flag if program is for drawing instead of updating
1773 
1774  The shader program gets a unique name with the following pattern:
1775  <pre>
1776  genCook-D00-N00-E00-O01-RM00-Sky-C4s
1777  | | | | | | | |
1778  | | | | | | | + Directional light w. 4 shadow cascades
1779  | | | | | | + Ambient light from skybox
1780  | | | | | + Roughness-metallic map with index 0 and uv 0
1781  | | | | + Ambient Occlusion map with index 0 and uv 1
1782  | | | + Emissive Map with index 0 and uv 0
1783  | | + Normal Map with index 0 and uv 0
1784  | + Diffuse Texture Mapping with index 0 and uv 0
1785  + Cook-Torrance or Blinn-Phong reflection model
1786  </pre>
1787  */
1789  string& programName,
1790  bool isDrawProg,
1791  bool drawInstanced)
1792 {
1793  assert(mat && "No material pointer passed!");
1794  programName = "gen";
1795 
1796  if (mat->reflectionModel() == RM_Particle)
1797  programName += "Particle";
1798  else
1799  programName += "Custom";
1800 
1801  // programName += "-";
1802  if (isDrawProg) // Drawing program
1803  {
1804  programName += "-Draw";
1805 
1806  if (drawInstanced)
1807  programName += "-Inst";
1808 
1809  programName += mat->texturesString();
1810  GLint billboardType = mat->ps()->billboardType(); // Billboard type (0 -> default; 1 -> vertical billboard, 2 -> horizontal billboard)
1811  bool AlOvLi = mat->ps()->doAlphaOverLT(); // Alpha over life
1812  bool AlOvLiCu = mat->ps()->doAlphaOverLTCurve(); // Alpha over life curve
1813  bool SiOvLi = mat->ps()->doSizeOverLT(); // Size over life
1814  bool SiOvLiCu = mat->ps()->doSizeOverLTCurve(); // Size over life curve
1815  bool Co = mat->ps()->doColor(); // Color over life
1816  bool CoOvLi = mat->ps()->doColorOverLT(); // Color over life
1817  bool FlBoTex = mat->ps()->doFlipBookTexture(); // Flipbook texture
1818  bool WS = mat->ps()->doWorldSpace(); // World space or local space
1819  bool rot = mat->ps()->doRotation(); // Rotation
1820  programName += "-B" + std::to_string(billboardType);
1821  if (rot) programName += "-RT";
1822  if (AlOvLi) programName += "-AL";
1823  if (AlOvLi && AlOvLiCu) programName += "cu";
1824  if (SiOvLi) programName += "-SL";
1825  if (SiOvLi && SiOvLiCu) programName += "cu";
1826  if (Co) programName += "-CO";
1827  if (Co && CoOvLi) programName += "cl";
1828  if (FlBoTex) programName += "-FB";
1829  if (WS) programName += "-WS";
1830  }
1831  else // Updating program
1832  {
1833  bool counterGap = mat->ps()->doCounterGap(); // Counter gap/lag
1834  bool acc = mat->ps()->doAcc(); // Acceleration
1835  bool accDiffDir = mat->ps()->doAccDiffDir(); // Acceleration different direction
1836  bool gravity = mat->ps()->doGravity(); // Gravity
1837  bool FlBoTex = mat->ps()->doFlipBookTexture(); // Flipbook texture
1838  bool rot = mat->ps()->doRotation(); // Rotation
1839  bool rotRange = mat->ps()->doRotRange(); // Rotation range
1840  bool shape = mat->ps()->doShape(); // Shape
1841  programName += "-Update";
1842  if (counterGap) programName += "-CG";
1843  if (rot) programName += "-RT";
1844  if (rot) programName += rotRange ? "ra" : "co";
1845  if (acc)
1846  {
1847  programName += "-AC";
1848  programName += accDiffDir ? "di" : "co";
1849  }
1850  if (gravity) programName += "-GR";
1851  if (FlBoTex) programName += "-FB";
1852  if (shape) programName += "-SH";
1853  }
1854 }
1855 //-----------------------------------------------------------------------------
1856 /*! Builds the GLSL program code for the vertex and fragment shaders. The code
1857  * is only assembled but not compiled and linked. This happens within the
1858  * before the first draw call from within SLMesh::draw.
1859  * \param mat Parent material pointer
1860  * \param lights Pointer of vector of lights
1861  */
1863  SLVLight* lights,
1864  SLbool supportGPUSkinning)
1865 {
1866  assert(mat && "No material pointer passed!");
1867  assert(!lights->empty() && "No lights passed!");
1868  assert(_shaders.size() > 1 &&
1869  _shaders[0]->type() == ST_vertex &&
1870  _shaders[1]->type() == ST_fragment);
1871 
1872  // Check what textures the material has
1873  bool Dm = mat->hasTextureType(TT_diffuse); // Texture Mapping
1874  bool Nm = mat->hasTextureType(TT_normal); // Normal Mapping
1875  bool Hm = mat->hasTextureType(TT_height); // Height Mapping
1876  bool Om = mat->hasTextureType(TT_occlusion); // Ambient Occlusion Mapping
1877  bool Vm = mat->hasTextureType(TT_videoBkgd); // Video Background Mapping
1878  bool env = mat->skybox() != nullptr; // Environment Mapping from skybox
1879 
1880  // Check if any of the scene lights does shadow mapping
1881  bool Sm = lightsDoShadowMapping(lights);
1882 
1883  if (mat->reflectionModel() == RM_BlinnPhong)
1884  {
1885  buildPerPixBlinn(mat, lights, supportGPUSkinning);
1886  }
1887  else if (mat->reflectionModel() == RM_CookTorrance)
1888  {
1889  buildPerPixCook(mat, lights, supportGPUSkinning);
1890  }
1891  else if (mat->reflectionModel() == RM_Custom)
1892  {
1893  if (Vm && Sm)
1894  buildPerPixVideoBkgdSm(lights);
1895  else
1896  SL_EXIT_MSG("SLGLProgramGenerated::buildProgramCode: Unknown program for RM_Custom.");
1897  }
1898  else
1899  SL_EXIT_MSG("SLGLProgramGenerated::buildProgramCode: Unknown Lighting Model.");
1900 }
1901 //-----------------------------------------------------------------------------
1902 /*! Builds the GLSL program code for the vertex, geometry and fragment shaders
1903  * (for particle system drawing). The code is only assembled but not compiled and linked.
1904  * This happens within the before the first draw call from within SLMesh::draw.
1905  * \param mat Parent material pointer
1906  * \param isDrawProg Flag if program is for drawing instead of update
1907  */
1909  bool isDrawProg,
1910  bool drawInstanced)
1911 {
1912  if (mat->name() == "IBLMat")
1913  {
1914  std::cout << "build program code for IBLMat" << std::endl;
1915  }
1916  assert(mat && "No material pointer passed!");
1917  assert(_shaders.size() > 1 &&
1918  _shaders[0]->type() == ST_vertex &&
1919  _shaders[1]->type() == ST_fragment);
1920 
1921  if (isDrawProg)
1922  {
1923  if (drawInstanced)
1925  else
1926  buildPerPixParticle(mat);
1927  }
1928  else
1930 }
1931 //-----------------------------------------------------------------------------
1932 
1933 //-----------------------------------------------------------------------------
1935  SLVLight* lights,
1936  SLbool supportGPUSkinning)
1937 {
1938  assert(mat && lights);
1939  assert(_shaders.size() > 1 &&
1940  _shaders[0]->type() == ST_vertex &&
1941  _shaders[1]->type() == ST_fragment);
1942 
1943  // Check what textures the material has
1944  bool Dm = mat->hasTextureType(TT_diffuse);
1945  bool Nm = mat->hasTextureType(TT_normal);
1946  bool Hm = mat->hasTextureType(TT_height);
1947  bool Rm = mat->hasTextureType(TT_roughness);
1948  bool Mm = mat->hasTextureType(TT_metallic);
1949  bool RMm = mat->hasTextureType(TT_roughMetal);
1950  bool Em = mat->hasTextureType(TT_emissive);
1951  bool Om0 = mat->hasTextureTypeWithUVIndex(TT_occlusion, 0, 0);
1952  bool Om1 = mat->hasTextureTypeWithUVIndex(TT_occlusion, 0, 1);
1953  bool ORMm = mat->hasTextureType(TT_occluRoughMetal);
1954  bool Vm = mat->hasTextureType(TT_videoBkgd);
1955  bool Sm = lightsDoShadowMapping(lights);
1956  bool uv0 = mat->usesUVIndex(0);
1957  bool uv1 = mat->usesUVIndex(1);
1958  bool sky = mat->skybox() != nullptr;
1959 
1960  // Assemble vertex shader code
1961  string vertCode;
1962  vertCode += shaderHeader((int)lights->size());
1963 
1964  // Vertex shader inputs
1965  vertCode += vertInput_a_pn;
1966  if (uv0) vertCode += vertInput_a_uv0;
1967  if (uv1) vertCode += vertInput_a_uv1;
1968  if (Nm) vertCode += vertInput_a_tangent;
1969  if (supportGPUSkinning) vertCode += vertInput_a_skinning;
1970  vertCode += vertInput_u_matrices_all;
1971  if (Nm) vertCode += vertInput_u_lightNm;
1972  if (supportGPUSkinning) vertCode += vertInput_u_skinning;
1973 
1974  // Vertex shader outputs
1975  vertCode += vertOutput_v_P_VS;
1976  if (Sm) vertCode += vertOutput_v_P_WS;
1977  vertCode += vertOutput_v_N_VS;
1978  if (sky) vertCode += vertOutput_v_R_OS;
1979  if (uv0) vertCode += vertOutput_v_uv0;
1980  if (uv1) vertCode += vertOutput_v_uv1;
1981  if (Nm) vertCode += vertOutput_v_lightVecTS;
1982 
1983  // Vertex shader main loop
1984  vertCode += main_Begin;
1985  if (supportGPUSkinning) vertCode += Nm ? vertMain_skinning_Nm : vertMain_skinning;
1986  vertCode += vertMain_v_P_VS;
1987  if (Sm) vertCode += vertMain_v_P_WS_Sm;
1988  vertCode += vertMain_v_N_VS;
1989  if (sky) vertCode += vertMain_v_R_OS;
1990  if (uv0) vertCode += vertMain_v_uv0;
1991  if (uv1) vertCode += vertMain_v_uv1;
1992  if (Nm) vertCode += vertMain_TBN_Nm;
1993  vertCode += vertMain_EndAll;
1994 
1995  // Vertex shader variables
1996  setVariable(vertCode, "localPosition", supportGPUSkinning ? "skinnedPosition" : "a_position");
1997  setVariable(vertCode, "localNormal", supportGPUSkinning ? "skinnedNormal" : "a_normal");
1998  if (Nm) setVariable(vertCode, "localTangent", supportGPUSkinning ? "skinnedTangent" : "a_tangent");
1999 
2000  addCodeToShader(_shaders[0], vertCode, _name + ".vert");
2001 
2002  // Assemble fragment shader code
2003  string fragCode;
2004  fragCode += shaderHeader((int)lights->size());
2005 
2006  // Fragment shader inputs
2007  fragCode += fragInput_v_P_VS;
2008  if (Sm) fragCode += fragInput_v_P_WS;
2009  fragCode += fragInput_v_N_VS;
2010  if (sky) fragCode += fragInput_v_R_OS;
2011  if (uv0) fragCode += fragInput_v_uv0;
2012  if (uv1) fragCode += fragInput_v_uv1;
2013  if (Nm) fragCode += fragInput_v_lightVecTS;
2014 
2015  // Fragment shader uniforms
2016  fragCode += fragInput_u_lightAll;
2017  if (Sm) fragCode += fragInput_u_lightSm(lights);
2018  fragCode += Dm ? fragInput_u_matTexDm : fragInput_u_matDiff;
2019  fragCode += Em ? fragInput_u_matTexEm : fragInput_u_matEmis;
2020  if (Rm) fragCode += fragInput_u_matTexRm;
2021  if (Mm) fragCode += fragInput_u_matTexMm;
2022  if (RMm) fragCode += fragInput_u_matTexRmMm;
2023  if (ORMm) fragCode += fragInput_u_matTexOmRmMm;
2024  if (!Rm && !RMm && !ORMm) fragCode += fragInput_u_matRough;
2025  if (!Mm && !RMm && !ORMm) fragCode += fragInput_u_matMetal;
2026  if (Nm) fragCode += fragInput_u_matTexNm;
2027  if (Om0 || Om1) fragCode += fragInput_u_matTexOm;
2028  if (Sm) fragCode += fragInput_u_matGetsSm;
2029  if (Sm) fragCode += fragInput_u_shadowMaps(lights);
2030  if (sky) fragCode += fragInput_u_skyCookEnvMaps;
2031  fragCode += fragInput_u_cam;
2032 
2033  // Fragment shader outputs
2034  fragCode += fragOutputs_o_fragColor;
2035 
2036  // Fragment shader functions
2038  fragCode += fragFunctionFogBlend;
2039  fragCode += fragFunctionDoStereoSeparation;
2040  if (Sm) fragCode += fragFunctionShadowTest(lights);
2041  if (Sm) fragCode += fragFunctionDoColoredShadows;
2042 
2043  // Fragment shader main loop
2044  fragCode += main_Begin;
2045  fragCode += fragMain_0_Intensities;
2046  fragCode += Nm ? fragMain_1_EN_in_TS : fragMain_1_EN_in_VS;
2058  fragCode += Nm && Sm ? fragMainCook_2_LightLoopNmSm : Nm ? fragMainCook_2_LightLoopNm
2062  if (Sm) fragCode += fragMain_4_ColoredShadows;
2063  fragCode += fragMain_5_FogGammaStereo;
2064 
2065  addCodeToShader(_shaders[1], fragCode, _name + ".frag");
2066 }
2067 //-----------------------------------------------------------------------------
2069  SLVLight* lights,
2070  SLbool supportGPUSkinning)
2071 {
2072  assert(mat && lights);
2073  assert(_shaders.size() > 1 &&
2074  _shaders[0]->type() == ST_vertex &&
2075  _shaders[1]->type() == ST_fragment);
2076 
2077  // Check what textures the material has
2078  bool Dm = mat->hasTextureType(TT_diffuse);
2079  bool Nm = mat->hasTextureType(TT_normal);
2080  bool Hm = mat->hasTextureType(TT_height);
2081  bool Em = mat->hasTextureType(TT_emissive);
2082  bool Om0 = mat->hasTextureTypeWithUVIndex(TT_occlusion, 0, 0);
2083  bool Om1 = mat->hasTextureTypeWithUVIndex(TT_occlusion, 0, 1);
2084  bool Sm = lightsDoShadowMapping(lights);
2085  bool uv0 = mat->usesUVIndex(0);
2086  bool uv1 = mat->usesUVIndex(1);
2087 
2088  // Assemble vertex shader code
2089  string vertCode;
2090  vertCode += shaderHeader((int)lights->size());
2091 
2092  // Vertex shader inputs
2093  vertCode += vertInput_a_pn;
2094  if (uv0) vertCode += vertInput_a_uv0;
2095  if (uv1) vertCode += vertInput_a_uv1;
2096  if (Nm) vertCode += vertInput_a_tangent;
2097  if (supportGPUSkinning) vertCode += vertInput_a_skinning;
2098  vertCode += vertInput_u_matrices_all;
2099  if (Nm) vertCode += vertInput_u_lightNm;
2100  if (supportGPUSkinning) vertCode += vertInput_u_skinning;
2101 
2102  // Vertex shader outputs
2103  vertCode += vertOutput_v_P_VS;
2104  if (Sm) vertCode += vertOutput_v_P_WS;
2105  vertCode += vertOutput_v_N_VS;
2106  if (uv0) vertCode += vertOutput_v_uv0;
2107  if (uv1) vertCode += vertOutput_v_uv1;
2108  if (Nm) vertCode += vertOutput_v_lightVecTS;
2109 
2110  // Vertex shader main loop
2111  vertCode += main_Begin;
2112  if (supportGPUSkinning) vertCode += Nm ? vertMain_skinning_Nm : vertMain_skinning;
2113  vertCode += vertMain_v_P_VS;
2114  if (Sm) vertCode += vertMain_v_P_WS_Sm;
2115  vertCode += vertMain_v_N_VS;
2116  if (uv0) vertCode += vertMain_v_uv0;
2117  if (uv1) vertCode += vertMain_v_uv1;
2118  if (Nm) vertCode += vertMain_TBN_Nm;
2119  vertCode += vertMain_EndAll;
2120 
2121  // Vertex shader variables
2122  setVariable(vertCode, "localPosition", supportGPUSkinning ? "skinnedPosition" : "a_position");
2123  setVariable(vertCode, "localNormal", supportGPUSkinning ? "skinnedNormal" : "a_normal");
2124  if (Nm) setVariable(vertCode, "localTangent", supportGPUSkinning ? "skinnedTangent" : "a_tangent");
2125 
2126  addCodeToShader(_shaders[0], vertCode, _name + ".vert");
2127 
2128  // Assemble fragment shader code
2129  string fragCode;
2130  fragCode += shaderHeader((int)lights->size());
2131 
2132  // Fragment shader inputs
2133  fragCode += fragInput_v_P_VS;
2134  if (Sm) fragCode += fragInput_v_P_WS;
2135  fragCode += fragInput_v_N_VS;
2136  if (uv0) fragCode += fragInput_v_uv0;
2137  if (uv1) fragCode += fragInput_v_uv1;
2138  if (Nm) fragCode += fragInput_v_lightVecTS;
2139 
2140  // Fragment shader uniforms
2141  fragCode += fragInput_u_lightAll;
2142  fragCode += fragInput_u_matBlinnAll;
2143  if (Sm) fragCode += fragInput_u_lightSm(lights);
2144  if (Dm) fragCode += fragInput_u_matTexDm;
2145  if (Nm) fragCode += fragInput_u_matTexNm;
2146  if (Em) fragCode += fragInput_u_matTexEm;
2147  if (Om0 || Om1) fragCode += fragInput_u_matTexOm;
2148  if (Sm) fragCode += fragInput_u_matGetsSm;
2149  if (Sm) fragCode += fragInput_u_shadowMaps(lights);
2150  fragCode += fragInput_u_cam;
2151 
2152  // Fragment shader outputs
2153  fragCode += fragOutputs_o_fragColor;
2154 
2155  // Fragment shader functions
2156  fragCode += fragFunctionsLightingBlinnPhong;
2157  fragCode += fragFunctionFogBlend;
2158  fragCode += fragFunctionDoStereoSeparation;
2159  if (Sm) fragCode += fragFunctionShadowTest(lights);
2160  if (Sm) fragCode += fragFunctionDoColoredShadows;
2161 
2162  // Fragment shader main loop
2163  fragCode += main_Begin;
2164  fragCode += fragMain_0_Intensities;
2165  fragCode += Nm ? fragMain_1_EN_in_TS : fragMain_1_EN_in_VS;
2166  fragCode += Em ? fragMain_1_matEmis_Em : fragMain_1_matEmis;
2167 
2168  fragCode += Om0 ? fragMain_1_matOccl_Om0 : Om1 ? fragMain_1_matOccl_Om1
2170 
2171  fragCode += Nm && Sm ? fragMainBlinn_2_LightLoopNmSm : Nm ? fragMainBlinn_2_LightLoopNm
2175  if (Sm) fragCode += fragMain_4_ColoredShadows;
2176  fragCode += fragMain_5_FogGammaStereo;
2177 
2178  addCodeToShader(_shaders[1], fragCode, _name + ".frag");
2179 }
2180 //-----------------------------------------------------------------------------
2182 {
2183  assert(_shaders.size() == 2 &&
2184  _shaders[0]->type() == ST_vertex &&
2185  _shaders[1]->type() == ST_fragment);
2186 
2187  // Check what textures the material has
2188  bool Dm = mat->hasTextureType(TT_diffuse);
2189  GLint billboardType = mat->ps()->billboardType(); // Billboard type (0 -> default; 1 -> vertical billboard, 2 -> horizontal billboard)
2190  bool rot = mat->ps()->doRotation(); // Rotation
2191  bool AlOvLi = mat->ps()->doAlphaOverLT(); // Alpha over life
2192  bool Co = mat->ps()->doColor(); // Color over life
2193  bool CoOvLi = mat->ps()->doColorOverLT(); // Color over life
2194  bool AlOvLiCu = mat->ps()->doAlphaOverLTCurve(); // Alpha over life curve
2195  bool SiOvLi = mat->ps()->doSizeOverLT(); // Size over life
2196  bool SiOvLiCu = mat->ps()->doSizeOverLTCurve(); // Size over life curve
2197  bool FlBoTex = mat->ps()->doFlipBookTexture(); // Flipbook texture
2198 
2199  //////////////////////////////
2200  // Assemble vertex shader code
2201  //////////////////////////////
2202 
2203  string vertCode;
2204  vertCode += shaderHeader();
2205 
2206  // Vertex shader inputs
2207  vertCode += vertInput_PS_a_InstPos; // instance position
2208  vertCode += vertInput_PS_a_p; // position
2209  vertCode += vertInput_PS_a_st; // start time
2210  if (rot) vertCode += vertInput_PS_a_r; // rotation as float
2211 
2212  if (FlBoTex)
2213  {
2214  vertCode += vertInput_PS_a_texNum; // per particle texture number
2215  vertCode += vertInput_PS_u_col;
2216  vertCode += vertInput_PS_u_row;
2217  }
2218 
2219  // Vertex shader uniforms
2220  vertCode += vertInput_PS_u_ScaRa;
2221  vertCode += vertInput_u_matrix_p;
2222  vertCode += vertInput_PS_u_time;
2223 
2224  if (billboardType == BT_Vertical)
2226 
2227  vertCode += vertInput_u_matrix_vOmv;
2228 
2229  if (AlOvLi && AlOvLiCu) vertCode += vertInput_PS_u_al_bernstein_alpha;
2230  if (SiOvLi && SiOvLiCu) vertCode += vertInput_PS_u_al_bernstein_size;
2231 
2232  // Vertex shader outputs
2234  vertCode += vertOutput_PS_v_tC;
2235 
2236  if (CoOvLi) vertCode += vertOutput_PS_age;
2237 
2238  // Vertex shader main loop
2239  vertCode += main_Begin;
2240  vertCode += vertMain_PS_instanced_position;
2241  vertCode += vertMain_PS_v_a;
2242  if (FlBoTex)
2243  vertCode += vertMain_PS_v_tC_flipbook;
2244  else
2245  vertCode += vertMain_PS_v_tC;
2246 
2247  if (AlOvLi)
2248  vertCode += vertMain_PS_instanced_v_t_begin;
2249  else
2251  if (AlOvLi) vertCode += AlOvLiCu ? vertMain_PS_instanced_v_t_curve : vertMain_PS_instanced_v_t_linear;
2252  if (AlOvLi) vertCode += vertMain_PS_v_t_end;
2253  vertCode += vertMain_PS_instanced_scale;
2254  if (SiOvLi) vertCode += vertMain_PS_instanced_v_s;
2255  if (SiOvLi && SiOvLiCu) vertCode += vertMain_PS_instanced_v_s_curve;
2256  if (SiOvLi) vertCode += vertMain_PS_instanced_v_sS;
2257  if (rot) vertCode += vertMain_PS_instanced_rotate;
2258  if (CoOvLi) vertCode += vertMain_PS_v_age;
2259 
2260  if (billboardType == BT_Vertical || billboardType == BT_Horizontal)
2262  else
2263  vertCode += vertMain_PS_instanced_EndAll;
2264 
2265  addCodeToShader(_shaders[0], vertCode, _name + ".vert");
2266 
2267  ////////////////////////////////
2268  // Assemble fragment shader code
2269  ////////////////////////////////
2270 
2271  string fragCode;
2272  fragCode += shaderHeader();
2273 
2274  // Fragment shader inputs
2275  fragCode += fragInput_PS_v_tC;
2276  if (Co && !CoOvLi) fragCode += fragInput_PS_u_c;
2277  if (CoOvLi)
2278  {
2279  fragCode += fragInput_PS_u_tTL;
2280  fragCode += fragInput_PS_age;
2281  fragCode += fragInput_PS_u_colorOvLF;
2282  }
2284 
2285  // Fragment shader uniforms
2286  if (Dm) fragCode += fragInput_u_matTexDm;
2287  fragCode += fragInput_PS_u_overG;
2288  fragCode += fragInput_PS_u_wireFrame;
2289 
2290  // Fragment shader outputs
2291  fragCode += fragOutputs_o_fragColor;
2292 
2293  if (CoOvLi) fragCode += fragFunction_PS_ColorOverLT;
2294 
2295  // Fragment shader main loop
2296  fragCode += main_Begin;
2297 
2298  if (Co && !CoOvLi) fragCode += fragMain_PS_instanced_c;
2299 
2300  if (CoOvLi) fragCode += fragMain_PS_instanced_v_doColorOverLT;
2301 
2302  if (Co || CoOvLi)
2303  {
2305  fragCode += fragMain_instanced_PS_end;
2306  }
2307  else
2309 
2310  fragCode += fragMain_PS_endAll;
2311 
2312  addCodeToShader(_shaders[1], fragCode, _name + ".frag");
2313 }
2314 //-----------------------------------------------------------------------------
2316 {
2317  assert(_shaders.size() > 2 &&
2318  _shaders[0]->type() == ST_vertex &&
2319  _shaders[1]->type() == ST_fragment &&
2320  _shaders[2]->type() == ST_geometry);
2321 
2322  // Check what textures the material has
2323  bool Dm = mat->hasTextureType(TT_diffuse);
2324  GLint billboardType = mat->ps()->billboardType(); // Billboard type (0 -> default; 1 -> vertical billboard, 2 -> horizontal billboard)
2325  bool rot = mat->ps()->doRotation(); // Rotation
2326  bool AlOvLi = mat->ps()->doAlphaOverLT(); // Alpha over life
2327  bool Co = mat->ps()->doColor(); // Color over life
2328  bool CoOvLi = mat->ps()->doColorOverLT(); // Color over life
2329  bool AlOvLiCu = mat->ps()->doAlphaOverLTCurve(); // Alpha over life curve
2330  bool SiOvLi = mat->ps()->doSizeOverLT(); // Size over life
2331  bool SiOvLiCu = mat->ps()->doSizeOverLTCurve(); // Size over life curve
2332  bool FlBoTex = mat->ps()->doFlipBookTexture(); // Flipbook texture
2333 
2334  //////////////////////////////
2335  // Assemble vertex shader code
2336  //////////////////////////////
2337 
2338  string vertCode;
2339  vertCode += shaderHeader();
2340 
2341  // Vertex shader inputs
2342  vertCode += vertInput_PS_a_p;
2343  vertCode += vertInput_PS_a_st;
2344  if (rot) vertCode += vertInput_PS_a_r;
2345  if (FlBoTex) vertCode += vertInput_PS_a_texNum;
2346 
2347  // Vertex shader uniforms
2348  vertCode += vertInput_PS_u_time;
2349  vertCode += vertInput_u_matrix_vOmv;
2350  if (AlOvLi && AlOvLiCu) vertCode += vertInput_PS_u_al_bernstein_alpha;
2351  if (SiOvLi && SiOvLiCu) vertCode += vertInput_PS_u_al_bernstein_size;
2352  if (Co && CoOvLi) vertCode += vertInput_PS_u_colorOvLF;
2353 
2354  // Vertex shader outputs
2355  vertCode += vertOutput_PS_struct_Begin;
2356  vertCode += vertOutput_PS_struct_t;
2357  if (rot) vertCode += vertOutput_PS_struct_r;
2358  if (SiOvLi) vertCode += vertOutput_PS_struct_s;
2359  if (Co && CoOvLi) vertCode += vertOutput_PS_struct_c;
2360  if (FlBoTex) vertCode += vertOutput_PS_struct_texNum;
2361  vertCode += vertOutput_PS_struct_End;
2362 
2363  // Vertex shader functions
2364  if (Co && CoOvLi) vertCode += vertFunction_PS_ColorOverLT;
2365 
2366  // Vertex shader main loop
2367  vertCode += main_Begin;
2368  vertCode += vertMain_PS_v_a;
2369  if (AlOvLi)
2370  vertCode += vertMain_PS_v_t_begin;
2371  else
2372  vertCode += vertMain_PS_v_t_default;
2373 
2374  if (AlOvLi) vertCode += AlOvLiCu ? vertMain_PS_v_t_curve : vertMain_PS_v_t_linear;
2375  if (AlOvLi) vertCode += vertMain_PS_v_t_end;
2376  if (rot) vertCode += vertMain_PS_v_r;
2377  if (SiOvLi) vertCode += vertMain_PS_v_s;
2378  if (SiOvLi && SiOvLiCu) vertCode += vertMain_PS_v_s_curve;
2379  if (Co && CoOvLi) vertCode += vertMain_PS_v_doColorOverLT;
2380  if (FlBoTex) vertCode += vertMain_PS_v_texNum;
2381  if (billboardType == BT_Vertical || billboardType == BT_Horizontal)
2383  else
2384  vertCode += vertMain_PS_EndAll;
2385 
2386  addCodeToShader(_shaders[0], vertCode, _name + ".vert");
2387 
2388  ////////////////////////////////
2389  // Assemble geometry shader code
2390  ////////////////////////////////
2391 
2392  string geomCode;
2393  geomCode += shaderHeader();
2394 
2395  // geometry shader inputs
2396  geomCode += geomConfig_PS;
2397 
2398  geomCode += geomInput_PS_struct_Begin;
2399  geomCode += geomInput_PS_struct_t;
2400  if (rot) geomCode += geomInput_PS_struct_r;
2401  if (SiOvLi) geomCode += geomInput_PS_struct_s;
2402  if (Co && CoOvLi) geomCode += geomInput_PS_struct_c;
2403  if (FlBoTex) geomCode += geomInput_PS_struct_texNum;
2404  geomCode += geomInput_PS_struct_End;
2405 
2406  // geometry shader uniforms
2407  geomCode += geomInput_PS_u_ScaRa;
2408  if (Co && !CoOvLi) geomCode += geomInput_PS_u_c;
2409  if (FlBoTex) geomCode += geomInput_PS_u_col;
2410  if (FlBoTex) geomCode += geomInput_PS_u_row;
2411  geomCode += geomInput_u_matrix_p;
2412  if (billboardType == BT_Vertical)
2414  else if (billboardType == BT_Horizontal)
2415  geomCode += vertInput_u_matrix_vOmv;
2416 
2417  // geometry shader outputs
2418  geomCode += geomOutput_PS_v_pC;
2419  geomCode += geomOutput_PS_v_tC;
2420 
2421  // geometry shader main loop
2422  geomCode += main_Begin;
2423  geomCode += geomMain_PS_v_s;
2424  if (SiOvLi) geomCode += geomMain_PS_v_sS;
2425  geomCode += geomMain_PS_v_rad;
2426  geomCode += geomMain_PS_v_p;
2427  geomCode += rot ? geomMain_PS_v_rot : geomMain_PS_v_rotIden;
2428  geomCode += Co && CoOvLi ? geomMain_PS_v_doColorOverLT : Co ? geomMain_PS_v_c
2430  geomCode += geomMain_PS_v_cT;
2431  if (billboardType == BT_Vertical)
2433  else if (billboardType == BT_Horizontal)
2435  else
2437 
2438  geomCode += geomMain_PS_EndAll;
2439 
2440  addCodeToShader(_shaders[2], geomCode, _name + ".geom");
2441 
2442  ////////////////////////////////
2443  // Assemble fragment shader code
2444  ////////////////////////////////
2445 
2446  string fragCode;
2447  fragCode += shaderHeader();
2448 
2449  // Fragment shader inputs
2450  fragCode += fragInput_PS_v_pC;
2451  fragCode += fragInput_PS_v_tC;
2452 
2453  // Fragment shader uniforms
2454  if (Dm) fragCode += fragInput_u_matTexDm;
2455  fragCode += fragInput_PS_u_overG;
2456  fragCode += fragInput_PS_u_wireFrame;
2457 
2458  // Fragment shader outputs
2459  fragCode += fragOutputs_o_fragColor;
2460 
2461  // Fragment shader main loop
2462  fragCode += main_Begin;
2463  fragCode += Co ? fragMain_PS : fragMain_PS_withoutColor;
2464  fragCode += fragMain_PS_endAll;
2465 
2466  addCodeToShader(_shaders[1], fragCode, _name + ".frag");
2467 }
2468 //-----------------------------------------------------------------------------
2470 {
2471  assert(_shaders.size() > 1 &&
2472  _shaders[0]->type() == ST_vertex &&
2473  _shaders[1]->type() == ST_fragment);
2474 
2475  bool counterGap = mat->ps()->doCounterGap(); // Counter gap/lag
2476  bool acc = mat->ps()->doAcc(); // Acceleration
2477  bool accDiffDir = mat->ps()->doAccDiffDir(); // Acceleration different direction
2478  bool gravity = mat->ps()->doGravity(); // Gravity
2479  bool FlBoTex = mat->ps()->doFlipBookTexture(); // Flipbook texture
2480  bool rot = mat->ps()->doRotation(); // Rotation
2481  bool rotRange = mat->ps()->doRotRange(); // Rotation range
2482  bool shape = mat->ps()->doShape(); // Shape
2483 
2484  string vertCode;
2485  vertCode += shaderHeader();
2486 
2487  // Vertex shader inputs
2488  vertCode += vertInput_PS_a_p;
2489  vertCode += vertInput_PS_a_v;
2490  vertCode += vertInput_PS_a_st;
2491  if (acc || gravity) vertCode += vertInput_PS_a_initV;
2492  if (rot) vertCode += vertInput_PS_a_r;
2493  if (rot && rotRange) vertCode += vertInput_PS_a_r_angularVelo;
2494  if (FlBoTex) vertCode += vertInput_PS_a_texNum;
2495  if (shape) vertCode += vertInput_PS_a_initP;
2496 
2497  // Vertex shader uniforms
2498  vertCode += vertInput_PS_u_time;
2499  vertCode += vertInput_PS_u_deltaTime;
2500  vertCode += vertInput_PS_u_pgPos;
2501  if (rot && !rotRange) vertCode += vertInput_PS_u_angularVelo;
2502  if (acc) vertCode += accDiffDir ? vertInput_PS_u_a_diffDir : vertInput_PS_u_a_const;
2503  if (gravity) vertCode += vertInput_PS_u_g;
2504  if (FlBoTex) vertCode += vertInput_PS_u_col;
2505  if (FlBoTex) vertCode += vertInput_PS_u_row;
2506  if (FlBoTex) vertCode += vertInput_PS_u_condFB;
2507 
2508  // Vertex shader outputs
2509  vertCode += vertOutput_PS_tf_p;
2510  vertCode += vertOutput_PS_tf_v;
2511  vertCode += vertOutput_PS_tf_st;
2512  if (acc || gravity) vertCode += vertOutput_PS_tf_initV;
2513  if (rot) vertCode += vertOutput_PS_tf_r;
2514  if (rot && rotRange) vertCode += vertOutput_PS_tf_r_angularVelo;
2515  if (FlBoTex) vertCode += vertOutput_PS_tf_texNum;
2516  if (shape) vertCode += vertOutput_PS_tf_initP;
2517 
2518  if (rot) vertCode += vertConstant_PS_pi; // Add constant PI
2519 
2520  // Vertex shader main loop
2521  vertCode += main_Begin;
2522  vertCode += vertMain_PS_U_Begin;
2523  vertCode += vertMain_PS_U_v_init_p;
2524  vertCode += vertMain_PS_U_v_init_v;
2525  vertCode += vertMain_PS_U_v_init_st;
2526  if (acc || gravity) vertCode += vertMain_PS_U_v_init_initV;
2527  if (rot) vertCode += vertMain_PS_U_v_init_r;
2528  if (rot && rotRange) vertCode += vertMain_PS_U_v_init_r_angularVelo;
2529  if (FlBoTex) vertCode += vertMain_PS_U_v_init_texNum;
2530  if (shape) vertCode += vertMain_PS_U_v_init_initP;
2531  vertCode += vertMain_PS_U_bornDead;
2532  vertCode += shape ? vertMain_PS_U_reset_shape_p : vertMain_PS_U_reset_p;
2533  if (acc || gravity) vertCode += vertMain_PS_U_reset_v;
2534  vertCode += counterGap ? vertMain_PS_U_reset_st_counterGap : vertMain_PS_U_reset_st;
2535  vertCode += vertMain_PS_U_alive_p;
2536  if (rot) vertCode += rotRange ? vertMain_PS_U_v_rRange : vertMain_PS_U_v_rConst;
2537  if (FlBoTex) vertCode += vertMain_PS_U_alive_texNum;
2538  if (acc) vertCode += accDiffDir ? vertMain_PS_U_alive_a_diffDir : vertMain_PS_U_alive_a_const;
2539  if (gravity) vertCode += vertMain_PS_U_alive_g;
2540  vertCode += vertMain_PS_U_EndAll;
2541 
2542  addCodeToShader(_shaders[0], vertCode, _name + ".vert");
2543 
2544  // Assemble fragment shader code
2545  string fragCode;
2546  fragCode += shaderHeader();
2547 
2548  // Fragment shader inputs
2549  fragCode += fragOutputs_o_fragColor;
2550  fragCode += main_Begin;
2551  fragCode += fragMain_PS_TF;
2552 
2553  addCodeToShader(_shaders[1], fragCode, _name + ".frag");
2554 }
2555 //-----------------------------------------------------------------------------
2556 //! Assemble shaders for video on background
2558 {
2559  assert(_shaders.size() > 1 &&
2560  _shaders[0]->type() == ST_vertex &&
2561  _shaders[1]->type() == ST_fragment);
2562 
2563  // Assemble vertex shader code
2564  string vertCode;
2565  vertCode += shaderHeader((int)lights->size());
2566  vertCode += vertInput_a_pn;
2567  vertCode += vertInput_u_matrices_all;
2568  vertCode += vertOutput_v_P_VS;
2569  vertCode += vertOutput_v_P_WS;
2570  vertCode += vertOutput_v_N_VS;
2571  vertCode += main_Begin;
2572  vertCode += vertMain_v_P_VS;
2573  vertCode += vertMain_v_P_WS_Sm;
2574  vertCode += vertMain_v_N_VS;
2575  vertCode += vertMain_EndAll;
2576 
2577  // Vertex shader variables
2578  setVariable(vertCode, "localPosition", "a_position");
2579  setVariable(vertCode, "localNormal", "a_normal");
2580 
2581  addCodeToShader(_shaders[0], vertCode, _name + ".vert");
2582 
2583  // Assemble fragment shader code
2584  string fragCode;
2585  fragCode += shaderHeader((int)lights->size());
2586  fragCode += R"(
2587 in vec3 v_P_VS; // Interpol. point of illumination in view space (VS)
2588 in vec3 v_P_WS; // Interpol. point of illumination in world space (WS)
2589 in vec3 v_N_VS; // Interpol. normal at v_P_VS in view space
2590 )";
2591  fragCode += fragInput_u_lightAll;
2592  fragCode += fragInput_u_lightSm(lights);
2593  fragCode += fragInput_u_cam;
2594  fragCode += fragInput_u_matAmbi;
2595  fragCode += fragInput_u_matTexDm;
2596  fragCode += fragInput_u_matGetsSm;
2597  fragCode += fragInput_u_shadowMaps(lights);
2598  fragCode += fragOutputs_o_fragColor;
2599  fragCode += fragFunctionFogBlend;
2600  fragCode += fragFunctionDoStereoSeparation;
2601  fragCode += fragFunctionShadowTest(lights);
2602  fragCode += fragFunctionDoColoredShadows;
2603  fragCode += main_Begin;
2604  fragCode += fragMainVideoBkgd;
2605  fragCode += fragMain_5_FogGammaStereo;
2606  addCodeToShader(_shaders[1], fragCode, _name + ".frag");
2607 }
2608 //-----------------------------------------------------------------------------
2609 
2610 //-----------------------------------------------------------------------------
2611 //! Returns true if at least one of the light does shadow mapping
2613 {
2614  for (auto light : *lights)
2615  {
2616  if (light->createsShadows())
2617  return true;
2618  }
2619  return false;
2620 }
2621 //-----------------------------------------------------------------------------
2623 {
2624  string u_lightSm = R"(
2625 uniform vec4 u_lightPosWS[NUM_LIGHTS]; // position of light in world space
2626 uniform bool u_lightCreatesShadows[NUM_LIGHTS]; // flag if light creates shadows
2627 uniform int u_lightNumCascades[NUM_LIGHTS]; // number of cascades for cascaded shadowmap
2628 uniform bool u_lightDoSmoothShadows[NUM_LIGHTS]; // flag if percentage-closer filtering is enabled
2629 uniform int u_lightSmoothShadowLevel[NUM_LIGHTS]; // radius of area to sample for PCF
2630 uniform float u_lightShadowMinBias[NUM_LIGHTS]; // min. shadow bias value at 0° to N
2631 uniform float u_lightShadowMaxBias[NUM_LIGHTS]; // min. shadow bias value at 90° to N
2632 uniform bool u_lightUsesCubemap[NUM_LIGHTS]; // flag if light has a cube shadow map
2633 uniform bool u_lightsDoColoredShadows; // flag if shadows should be colored
2634 )";
2635  for (SLuint i = 0; i < lights->size(); ++i)
2636  {
2637  SLLight* light = lights->at(i);
2638  if (light->createsShadows())
2639  {
2640  SLShadowMap* shadowMap = light->shadowMap();
2641 
2642  if (shadowMap->useCubemap())
2643  {
2644  u_lightSm += "uniform mat4 u_lightSpace_" + std::to_string(i) + "[6];\n";
2645  }
2646  else if (light->doCascadedShadows())
2647  {
2648  u_lightSm += "uniform mat4 u_lightSpace_" + std::to_string(i) + "[" + std::to_string(shadowMap->numCascades()) + "];\n";
2649  }
2650  else
2651  {
2652  u_lightSm += "uniform mat4 u_lightSpace_" + std::to_string(i) + ";\n";
2653  }
2654  }
2655  }
2656  return u_lightSm;
2657 }
2658 //-----------------------------------------------------------------------------
2660 {
2661  string smDecl = "\n";
2662  for (SLuint i = 0; i < lights->size(); ++i)
2663  {
2664  SLLight* light = lights->at(i);
2665  if (light->createsShadows())
2666  {
2667  SLShadowMap* shadowMap = light->shadowMap();
2668  if (shadowMap->useCubemap())
2669  smDecl += "uniform samplerCube u_shadowMapCube_" + to_string(i) + ";\n";
2670  else if (light->doCascadedShadows())
2671  {
2672  for (int j = 0; j < light->shadowMap()->depthBuffers().size(); j++)
2673  smDecl += "uniform sampler2D u_cascadedShadowMap_" + to_string(i) + "_" + std::to_string(j) + ";\n";
2674 
2675  smDecl += "uniform float u_cascadesFactor_" + to_string(i) + ";\n";
2676  }
2677  else
2678  smDecl += "uniform sampler2D u_shadowMap_" + to_string(i) + ";\n";
2679  }
2680  }
2681  return smDecl;
2682 }
2683 //-----------------------------------------------------------------------------
2684 //! Adds the core shadow mapping test routine depending on the lights
2686 {
2687  bool doCascadedSM = false;
2688  for (SLLight* light : *lights)
2689  {
2690  if (light->doCascadedShadows())
2691  {
2692  doCascadedSM = true;
2693  break;
2694  }
2695  }
2696 
2697  string shadowTestCode = R"(
2698 //-----------------------------------------------------------------------------
2699 int vectorToFace(vec3 vec) // Vector to process
2700 {
2701  vec3 absVec = abs(vec);
2702  if (absVec.x > absVec.y && absVec.x > absVec.z)
2703  return vec.x > 0.0 ? 0 : 1;
2704  else if (absVec.y > absVec.x && absVec.y > absVec.z)
2705  return vec.y > 0.0 ? 2 : 3;
2706  else
2707  return vec.z > 0.0 ? 4 : 5;
2708 }
2709 //-----------------------------------------------------------------------------
2710 int getCascadesDepthIndex(in int i, int numCascades)
2711 {
2712  float factor;
2713 )";
2714 
2715  for (SLuint i = 0; i < lights->size(); ++i)
2716  {
2717  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2718  if (shadowMap && shadowMap->useCascaded())
2719  {
2720  shadowTestCode += " if (i == " + std::to_string(i) + ")\n";
2721  shadowTestCode += " {\n";
2722  shadowTestCode += " factor = u_cascadesFactor_" + std::to_string(i) + ";\n";
2723  shadowTestCode += " }\n";
2724  }
2725  }
2726 
2727  shadowTestCode += R"(
2728  float fi = u_camClipNear;
2729  float ni;
2730 
2731  for (int i = 0; i < numCascades-1; i++)
2732  {
2733  ni = fi;
2734  fi = factor * u_camClipNear * pow((u_camClipFar/(factor*u_camClipNear)), float(i+1)/float(numCascades));
2735  if (-v_P_VS.z < fi)
2736  return i;
2737  }
2738  return numCascades-1;
2739 }
2740 //-----------------------------------------------------------------------------
2741 float shadowTest(in int i, in vec3 N, in vec3 lightDir)
2742 {
2743  if (u_lightCreatesShadows[i])
2744  {
2745  // Calculate position in light space
2746  mat4 lightSpace;
2747  vec3 lightToFragment = v_P_WS - u_lightPosWS[i].xyz;
2748 )";
2749 
2750  if (doCascadedSM > 0)
2751  {
2752  shadowTestCode += R"(
2753  int index = 0;
2754 
2755  if (u_lightNumCascades[i] > 0)
2756  {
2757  index = getCascadesDepthIndex(i, u_lightNumCascades[i]);
2758  )";
2759  for (SLuint i = 0; i < lights->size(); ++i)
2760  {
2761  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2762  if (shadowMap && shadowMap->useCascaded())
2763  shadowTestCode += " if (i == " + std::to_string(i) + ") { lightSpace = u_lightSpace_" + std::to_string(i) + "[index]; }\n";
2764  }
2765  shadowTestCode += R"(
2766  }
2767  else if (u_lightUsesCubemap[i])
2768  {)";
2769  for (SLuint i = 0; i < lights->size(); ++i)
2770  {
2771  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2772  if (shadowMap && shadowMap->useCubemap())
2773  shadowTestCode += " if (i == " + std::to_string(i) + ") { lightSpace = u_lightSpace_" + std::to_string(i) + "[vectorToFace(lightToFragment)]; }\n";
2774  }
2775  shadowTestCode += R"(
2776  }
2777  else
2778  {
2779  )";
2780  for (SLuint i = 0; i < lights->size(); ++i)
2781  {
2782  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2783  if (shadowMap && !shadowMap->useCubemap() && !shadowMap->useCascaded())
2784  shadowTestCode += "if (i == " + std::to_string(i) + ") { lightSpace = u_lightSpace_" + std::to_string(i) + "}\n";
2785  }
2786  shadowTestCode += R"(
2787  }
2788  )";
2789  }
2790  else
2791  {
2792  shadowTestCode += R"(
2793  if (u_lightUsesCubemap[i])
2794  {
2795 )";
2796  for (SLuint i = 0; i < lights->size(); ++i)
2797  {
2798  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2799  if (shadowMap && shadowMap->useCubemap())
2800  shadowTestCode += " if (i == " + std::to_string(i) + ") lightSpace = u_lightSpace_" + std::to_string(i) + "[vectorToFace(lightToFragment)];\n";
2801  }
2802  shadowTestCode += R"(
2803  }
2804  else
2805  {
2806 )";
2807  for (SLuint i = 0; i < lights->size(); ++i)
2808  {
2809  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2810  if (shadowMap && !shadowMap->useCubemap() && !shadowMap->useCascaded())
2811  shadowTestCode += " if (i == " + std::to_string(i) + ") lightSpace = u_lightSpace_" + std::to_string(i) + ";\n";
2812  }
2813  shadowTestCode += R"(
2814  }
2815  )";
2816  }
2817 
2818  shadowTestCode += R"(
2819  vec4 lightSpacePosition = lightSpace * vec4(v_P_WS, 1.0);
2820 
2821  // Normalize lightSpacePosition
2822  vec3 projCoords = lightSpacePosition.xyz / lightSpacePosition.w;
2823 
2824  // Convert to texture coordinates
2825  projCoords = projCoords * 0.5 + 0.5;
2826 
2827  float currentDepth = projCoords.z;
2828 
2829  // Look up depth from shadow map
2830  float shadow = 0.0;
2831  float closestDepth;
2832 
2833  // calculate bias between min. and max. bias depending on the angle between N and lightDir
2834  float bias = max(u_lightShadowMaxBias[i] * (1.0 - dot(N, lightDir)), u_lightShadowMinBias[i]);
2835 
2836  // Use percentage-closer filtering (PCF) for softer shadows (if enabled)
2837  if (u_lightDoSmoothShadows[i])
2838  {
2839  int level = u_lightSmoothShadowLevel[i];
2840  vec2 texelSize;
2841 )";
2842 
2843  for (SLuint i = 0; i < lights->size(); ++i)
2844  {
2845  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2846  if (!shadowMap->useCascaded() && !shadowMap->useCubemap())
2847  shadowTestCode += " if (i == " + to_string(i) + ") { texelSize = 1.0 / vec2(textureSize(u_shadowMap_" + to_string(i) + ", 0)); }\n";
2848  else if (shadowMap->useCascaded())
2849  {
2850  shadowTestCode += " if (i == " + to_string(i) + ")\n {\n";
2851  for (int j = 0; j < shadowMap->depthBuffers().size(); j++)
2852  shadowTestCode += " if (index == " + to_string(j) + ") { texelSize = 1.0 / vec2(textureSize(u_cascadedShadowMap_" + to_string(i) + "_" + to_string(j) + ", 0)); }\n";
2853 
2854  shadowTestCode += " }\n";
2855  }
2856  }
2857  shadowTestCode += R"(
2858  for (int x = -level; x <= level; ++x)
2859  {
2860  for (int y = -level; y <= level; ++y)
2861  {
2862  )";
2863  for (SLuint i = 0; i < lights->size(); ++i)
2864  {
2865  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2866  if (!shadowMap->useCascaded() && !shadowMap->useCubemap())
2867  shadowTestCode += " if (i == " + to_string(i) + ") { closestDepth = texture(u_shadowMap_" + to_string(i) + ", projCoords.xy + vec2(x, y) * texelSize).r; }\n";
2868  else if (shadowMap->useCascaded())
2869  {
2870  shadowTestCode += " if (i == " + to_string(i) + ")\n {\n";
2871  for (int j = 0; j < shadowMap->depthBuffers().size(); j++)
2872  shadowTestCode += " if (index == " + to_string(j) + ") { closestDepth = texture(u_cascadedShadowMap_" + to_string(i) + "_" + to_string(j) + ", projCoords.xy + vec2(x, y) * texelSize).r; }\n";
2873  shadowTestCode += " }\n";
2874  }
2875  }
2876 
2877  shadowTestCode += R"(
2878  shadow += currentDepth - bias > closestDepth ? 1.0 : 0.0;
2879  }
2880  }
2881  shadow /= pow(1.0 + 2.0 * float(level), 2.0);
2882  }
2883  else
2884  {
2885  if (u_lightUsesCubemap[i])
2886  {
2887 )";
2888  for (SLuint i = 0; i < lights->size(); ++i)
2889  {
2890  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2891  if (shadowMap->useCubemap())
2892  shadowTestCode += " if (i == " + to_string(i) + ") closestDepth = texture(u_shadowMapCube_" + to_string(i) + ", lightToFragment).r;\n";
2893  }
2894  shadowTestCode += R"(
2895  }
2896  else if (u_lightNumCascades[i] > 0)
2897  {
2898 )";
2899  for (SLuint i = 0; i < lights->size(); ++i)
2900  {
2901  SLLight* light = lights->at(i);
2902  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2903  if (light->doCascadedShadows())
2904  {
2905  shadowTestCode += " if (i == " + to_string(i) + ")\n {\n";
2906  for (int j = 0; j < shadowMap->depthBuffers().size(); j++)
2907  shadowTestCode += " if (index == " + to_string(j) + ") { closestDepth = texture(u_cascadedShadowMap_" + to_string(i) + "_" + to_string(j) + ", projCoords.xy).r; }\n";
2908  shadowTestCode += " }";
2909  }
2910  }
2911 
2912  shadowTestCode += R"(
2913  }
2914  else
2915  {
2916 )";
2917 
2918  for (SLuint i = 0; i < lights->size(); ++i)
2919  {
2920  SLShadowMap* shadowMap = lights->at(i)->shadowMap();
2921  if (!shadowMap->useCubemap() && !shadowMap->useCascaded())
2922  shadowTestCode += " if (i == " + to_string(i) + ") closestDepth = texture(u_shadowMap_" + to_string(i) + ", projCoords.xy).r;\n";
2923  }
2924 
2925  shadowTestCode += R"(
2926  }
2927 
2928  // The fragment is in shadow if the light doesn't "see" it
2929  if (currentDepth > closestDepth + bias)
2930  shadow = 1.0;
2931  }
2932 
2933  return shadow;
2934  }
2935 
2936  return 0.0;
2937 })";
2938 
2939  return shadowTestCode;
2940 }
2941 //-----------------------------------------------------------------------------
2942 //! Add vertex shader code to the SLGLShader instance
2944  const string& code,
2945  const string& name)
2946 {
2947 
2948 #if defined(DEBUG) && defined(_DEBUG)
2949  shader->code(SLGLShader::removeComments(code));
2950 #else
2951  shader->code(code);
2952 #endif
2953  shader->name(name);
2954 
2955 #ifndef SL_EMSCRIPTEN
2956  // Check if generatedShaderPath folder exists
2957  generatedShaderPath = SLGLProgramManager::configPath + "generatedShaders/";
2959  SL_EXIT_MSG("SLGLProgramGenerated::addCodeToShader: SLGLProgramManager::configPath not existing");
2960 
2962  {
2963  bool dirCreated = Utils::makeDir(generatedShaderPath);
2964  if (!dirCreated)
2965  SL_EXIT_MSG("SLGLProgramGenerated::addCodeToShader: Failed to created SLGLProgramManager::configPath/generatedShaders");
2966  }
2967 
2968  shader->file(generatedShaderPath + name);
2969 #endif
2970 }
2971 //-----------------------------------------------------------------------------
2972 //! Sets a variable in the shader code.
2973 /*! A variable is specified in templates like this: ${variableName}.
2974  */
2975 void SLGLProgramGenerated::setVariable(std::string& code,
2976  const std::string& name,
2977  const std::string& value)
2978 {
2979  std::string placeholder = "${" + name + "}";
2980 
2981  std::string::size_type pos = 0;
2982  while ((pos = code.find(placeholder)) != std::string::npos)
2983  {
2984  code.replace(pos, placeholder.size(), value);
2985  pos += value.size();
2986  }
2987 }
2988 //-----------------------------------------------------------------------------
2989 //! Adds shader header code
2991 
2992 {
2993  string header = "\nprecision highp float;\n";
2994  header += "\n#define NUM_LIGHTS " + to_string(numLights) + "\n";
2995  return header;
2996 }
2997 
2998 //-----------------------------------------------------------------------------
2999 //! Adds shader header code
3001 
3002 {
3003  string header = "\nprecision highp float;\n";
3004  return header;
3005 }
3006 //-----------------------------------------------------------------------------
unsigned int SLuint
Definition: SL.h:171
bool SLbool
Definition: SL.h:175
#define SL_EXIT_MSG(message)
Definition: SL.h:240
@ ST_vertex
Definition: SLEnums.h:224
@ ST_geometry
Definition: SLEnums.h:226
@ ST_fragment
Definition: SLEnums.h:225
@ RM_BlinnPhong
Definition: SLEnums.h:289
@ RM_Custom
Definition: SLEnums.h:292
@ RM_Particle
Definition: SLEnums.h:291
@ RM_CookTorrance
Definition: SLEnums.h:290
@ BT_Horizontal
Definition: SLEnums.h:274
@ BT_Vertical
Definition: SLEnums.h:273
Uses an OpenGL framebuffer object as a depth-buffer.
const string vertOutput_PS_tf_initP
const string vertInput_PS_a_v
const string vertMain_PS_instanced_v_t_begin
const string fragMainCook_3_FragColorSky
const string vertMain_EndAll
const string vertOutput_v_uv1
const string fragMain_1_matOccl_Om0
const string fragInput_v_uv0
const string vertMain_v_P_VS
const string fragOutputs_o_fragColor
const string vertMain_PS_v_age
const string fragMainVideoBkgd
const string fragMainBlinn_3_FragColor
const string main_Begin
const string fragMain_5_FogGammaStereo
const string vertInput_PS_u_row
const string geomMain_PS_fourCorners_horizBillboard
const string geomMain_PS_Flipbook_fourCorners
const string vertMain_PS_U_reset_v
const string vertInput_PS_u_g
const string vertMain_PS_U_v_rRange
const string vertMain_PS_instanced_v_s_curve
const string fragMainBlinn_2_LightLoopSm
const string fragInput_PS_u_wireFrame
const string geomMain_PS_v_rot
const string fragMain_1_matOccl_Om1
const string fragMain_1_matEmis_Em
const string vertMain_PS_U_reset_shape_p
const string fragMainCook_1_matRough
const string geomInput_PS_u_ScaRa
const string vertOutput_PS_struct_Begin
const string vertMain_PS_v_texNum
const string vertMain_PS_U_v_init_v
const string fragInput_PS_age
const string geomInput_u_matrix_vertBillboard
const string fragMainCook_1_matOcclu_ORMm
const string vertMain_PS_U_alive_a_const
const string fragInput_PS_v_pC
const string geomInput_PS_u_row
const string fragInput_u_matTexRm
const string fragInput_u_matTexRmMm
const string vertMain_PS_U_v_init_st
const string geomInput_PS_struct_s
const string vertMain_PS_U_EndAll
const string fragMain_1_EN_in_VS
const string fragInput_v_R_OS
const string vertMain_PS_U_reset_st
const string vertOutput_v_N_VS
const string vertMain_v_uv0
const string fragMainBlinn_2_LightLoopNm
const string geomInput_PS_struct_t
const string vertMain_PS_U_v_init_texNum
const string fragFunctionFogBlend
const string geomInput_PS_struct_texNum
const string vertMain_PS_EndAll
const string fragMain_PS_withoutColor
const string fragFunctionsLightingBlinnPhong
const string vertInput_PS_u_time
const string geomInput_PS_u_col
const string vertMain_PS_instanced_EndAll
const string vertMain_PS_U_Begin
const string vertMain_PS_instanced_v_sS
const string vertInput_PS_a_initP
const string vertInput_PS_u_ScaRa
const string geomMain_PS_EndAll
const string fragMainCook_3_FragColor
const string fragInput_PS_u_c
const string vertInput_a_tangent
const string vertInput_PS_u_deltaTime
const string vertMain_PS_instanced_v_t_curve
const string fragInput_u_matTexEm
const string vertInput_PS_u_al_bernstein_size
const string fragInput_u_lightAll
const string fragMainCook_1_matOcclu_Om0
const string geomOutput_PS_v_pC
const string vertMain_PS_v_t_end
const string vertInput_PS_a_p
const string fragInput_u_matMetal
const string fragMainCook_2_LightLoopNm
const string fragMainCook_1_matDiff
const string vertOutput_PS_tf_r
const string vertMain_PS_U_v_init_r
const string vertMain_v_N_VS
const string vertOutput_v_lightVecTS
const string vertInput_a_uv0
const string fragInput_u_matGetsSm
const string fragInput_u_matRough
const string vertFunction_PS_ColorOverLT
const string fragInput_u_matDiff
const string geomMain_PS_fourCorners_vertBillboard
const string fragInput_PS_u_colorOvLF
const string geomInput_PS_struct_r
const string fragMain_PS_endAll
const string fragInput_PS_u_tTL
const string fragMain_PS_instanced_transparency
const string vertMain_PS_v_t_curve
const string vertMain_PS_instanced_v_t_linear
const string fragInput_u_matAmbi
const string fragMainCook_1_matDiff_Dm
const string fragInput_u_cam
const string fragMainCook_1_matOcclu_1
const string vertInput_PS_u_a_diffDir
const string vertMain_PS_instanced_rotate
const string fragMainCook_2_LightLoop
const string vertOutput_PS_struct_texNum
const string vertInput_a_skinning
const string fragFunctionDoStereoSeparation
const string fragInput_u_matTexOm
const string fragMainCook_1_matMetal_RMm
const string vertMain_PS_instanced_v_t_default
const string vertInput_PS_u_pgPos
const string fragMainCook_1_matEmis_Em
const string vertInput_a_pn
const string vertMain_v_P_WS_Sm
const string vertMain_PS_v_t_default
const string fragInput_u_matBlinnAll
const string vertInput_PS_a_texNum
const string vertMain_PS_U_v_init_r_angularVelo
const string vertInput_u_matrix_p
const string geomMain_PS_fourCorners
const string vertInput_PS_u_angularVelo
const string vertMain_PS_U_reset_p
const string vertOutput_PS_struct_c
const string vertMain_PS_U_alive_g
const string vertInput_u_matrix_vOmv
const string vertOutput_PS_tf_p
const string vertMain_PS_EndAll_VertBillboard
const string geomMain_PS_v_withoutColor
const string vertInput_PS_u_colorOvLF
const string fragMainCook_1_matRough_RMm
const string fragMainCook_1_matMetal_Mm
const string fragMain_instanced_PS_end
const string fragMainCook_2_LightLoopSm
const string vertInput_PS_u_condFB
const string fragMainCook_1_matEmis
const string fragInput_u_skyCookEnvMaps
const string vertInput_u_skinning
const string fragInput_v_N_VS
const string fragFunction_PS_ColorOverLT
const string geomOutput_PS_v_tC
const string vertOutput_PS_tf_st
const string fragMain_PS_instanced_c
const string geomInput_u_matrix_p
const string fragInput_v_lightVecTS
const string geomMain_PS_v_p
const string fragMainBlinn_2_LightLoopNmSm
const string fragInput_u_matTexOmRmMm
const string vertMain_v_uv1
const string geomConfig_PS
const string vertConstant_PS_pi
const string vertOutput_PS_age
const string vertInput_PS_u_col
const string vertMain_PS_v_t_linear
const string vertInput_PS_u_a_const
const string vertOutput_PS_tf_r_angularVelo
const string vertInput_PS_a_r_angularVelo
const string fragInput_v_P_VS
const string fragMainCook_1_matMetal
const string geomMain_PS_v_cT
const string vertMain_PS_U_alive_a_diffDir
const string geomInput_PS_struct_Begin
const string vertMain_TBN_Nm
const string vertMain_skinning_Nm
const string fragInput_PS_u_overG
const string vertOutput_PS_struct_s
const string vertMain_PS_v_s_curve
const string vertMain_PS_instanced_v_s
const string vertMain_PS_instanced_EndAll_VertBillboard
const string vertOutput_PS_struct_End
const string geomMain_PS_v_doColorOverLT
const string vertInput_PS_a_st
const string vertInput_PS_a_initV
const string vertOutput_PS_tf_v
const string vertOutput_PS_v_tC
const string geomInput_PS_struct_c
const string vertOutput_v_uv0
const string vertOutput_PS_tf_texNum
const string vertMain_PS_U_alive_texNum
const string vertOutput_PS_struct_t
const string vertMain_PS_U_v_init_initP
const string fragMain_PS
const string fragInput_v_P_WS
const string vertOutput_v_P_WS
const string vertMain_PS_U_v_init_initV
const string vertInput_u_lightNm
const string fragFunctionsLightingCookTorrance
const string fragMain_4_ColoredShadows
const string geomMain_PS_Flipbook_fourCorners_horizBillboard
const string fragMainCook_1_matOcclu_Om1
const string vertMain_PS_v_a
const string geomMain_PS_v_c
const string vertMain_v_R_OS
const string vertMain_PS_U_alive_p
const string geomInput_PS_u_c
const string vertMain_PS_v_tC
const string geomMain_PS_v_sS
const string vertMain_PS_U_v_init_p
const string vertMain_PS_U_bornDead
const string fragMainCook_1_matRough_ORMm
const string vertMain_PS_v_doColorOverLT
const string fragInput_u_matEmis
const string vertMain_PS_U_v_rConst
const string vertMain_PS_instanced_position
const string vertInput_u_matrices_all
const string fragMain_1_EN_in_TS
const string vertOutput_v_R_OS
const string vertOutput_PS_tf_initV
const string fragMainCook_1_matMetal_ORMm
const string vertInput_PS_u_al_bernstein_alpha
const string fragFunctionDoColoredShadows
const string geomMain_PS_v_s
const string vertMain_PS_v_tC_flipbook
const string vertInput_u_matrix_vertBillboard
const string vertInput_a_uv1
const string fragInput_v_uv1
const string fragMain_PS_instanced_withoutColor
const string fragMainBlinn_2_LightLoop
const string fragMain_1_matEmis
const string vertMain_PS_instanced_scale
const string fragMainCook_1_matRough_Rm
const string fragInput_PS_instanced_transparency
const string fragMain_0_Intensities
const string vertInput_PS_a_InstPos
const string vertOutput_PS_struct_r
const string fragInput_u_matTexDm
const string fragMain_1_matOccl
const string vertMain_PS_v_t_begin
const string fragInput_PS_v_tC
const string vertMain_skinning
const string vertMain_PS_v_s
const string vertInput_PS_a_r
const string vertOutput_v_P_VS
const string geomMain_PS_v_rad
const string vertMain_PS_v_r
const string vertMain_PS_U_reset_st_counterGap
const string fragMainBlinn_3_FragColorDm
const string fragInput_u_matTexMm
const string fragMain_PS_TF
const string geomMain_PS_v_rotIden
const string fragMainCook_2_LightLoopNmSm
const string fragInput_u_matTexNm
const string geomInput_PS_struct_End
const string fragMain_PS_instanced_v_doColorOverLT
const string vertOutput_PS_instanced_transparency
const string geomMain_PS_Flipbook_fourCorners_vertBillboard
@ TT_occluRoughMetal
Definition: SLGLTexture.h:87
@ TT_height
Definition: SLGLTexture.h:80
@ TT_videoBkgd
Definition: SLGLTexture.h:94
@ TT_metallic
Definition: SLGLTexture.h:85
@ TT_roughMetal
Definition: SLGLTexture.h:86
@ TT_roughness
Definition: SLGLTexture.h:84
@ TT_normal
Definition: SLGLTexture.h:79
@ TT_diffuse
Definition: SLGLTexture.h:78
@ TT_occlusion
Definition: SLGLTexture.h:83
@ TT_emissive
Definition: SLGLTexture.h:82
vector< SLLight * > SLVLight
STL vector of light pointers.
Definition: SLLight.h:232
static string fragInput_u_lightSm(SLVLight *lights)
void buildPerPixParticleUpdate(SLMaterial *mat)
static bool lightsDoShadowMapping(SLVLight *lights)
Returns true if at least one of the light does shadow mapping.
static void addCodeToShader(SLGLShader *shader, const string &code, const string &name)
Add vertex shader code to the SLGLShader instance.
static void setVariable(std::string &code, const std::string &name, const std::string &value)
Sets a variable in the shader code.
void buildPerPixCook(SLMaterial *mat, SLVLight *lights, SLbool supportGPUSkinning)
void buildPerPixBlinn(SLMaterial *mat, SLVLight *lights, SLbool supportGPUSkinning)
static string generatedShaderPath
static string fragFunctionShadowTest(SLVLight *lights)
Adds the core shadow mapping test routine depending on the lights.
static string shaderHeader()
Adds shader header code.
void buildProgramCode(SLMaterial *mat, SLVLight *lights, SLbool supportGPUSkinning)
static void buildProgramNamePS(SLMaterial *mat, string &programName, bool isDrawProg, bool drawInstanced)
static void buildProgramName(SLMaterial *mat, SLVLight *lights, SLbool supportGPUSkinning, string &programName)
Builds unique program name that identifies shader program.
void buildProgramCodePS(SLMaterial *mat, bool isDrawProg, bool drawInstanced=false)
void buildPerPixParticle(SLMaterial *mat)
void buildPerPixParticleInstanced(SLMaterial *mat)
static string fragInput_u_shadowMaps(SLVLight *lights)
void buildPerPixVideoBkgdSm(SLVLight *lights)
Assemble shaders for video on background.
SLVGLShader _shaders
Vector of all shader objects.
Definition: SLGLProgram.h:143
static string configPath
Contains the global writable configuration path.
Encapsulation of an OpenGL shader object.
Definition: SLGLShader.h:25
SLstring code()
Definition: SLGLShader.h:42
void file(SLstring strFile)
Definition: SLGLShader.h:46
static SLstring removeComments(SLstring src)
SLGLShader::removeComments for C/C++ comments removal from shader code.
Definition: SLGLShader.cpp:201
Abstract Light class for OpenGL light sources.
Definition: SLLight.h:61
virtual SLbool doCascadedShadows() const
Definition: SLLight.h:154
void createsShadows(SLbool createsShadows)
Definition: SLLight.cpp:98
void shadowMap(SLShadowMap *shadowMap)
Definition: SLLight.h:125
Defines a standard CG material with textures and a shader program.
Definition: SLMaterial.h:56
void ps(SLParticleSystem *ps)
Definition: SLMaterial.h:208
SLstring texturesString()
Returns a unique string that represent all textures used.
Definition: SLMaterial.cpp:687
void reflectionModel(SLReflectionModel rm)
Definition: SLMaterial.h:169
void skybox(SLSkybox *sb)
Definition: SLMaterial.h:207
SLbool hasTextureTypeWithUVIndex(SLTextureType tt, SLuint texIndex, SLbyte uvIndex)
Definition: SLMaterial.h:153
SLbool hasTextureType(SLTextureType tt)
Definition: SLMaterial.h:149
SLbool usesUVIndex(SLbyte uvIndex)
Returns true if the specified uvIndex is used by one of the textures.
Definition: SLMaterial.cpp:707
void name(const SLstring &Name)
Definition: SLObject.h:34
SLstring _name
name of an object
Definition: SLObject.h:42
const SLstring & name() const
Definition: SLObject.h:38
Class for standard and cascaded shadow mapping.
Definition: SLShadowMap.h:39
void numCascades(int numCascades)
Definition: SLShadowMap.h:72
SLbool useCascaded() const
Definition: SLShadowMap.h:78
SLGLVDepthBuffer depthBuffers()
Definition: SLShadowMap.h:81
void useCubemap(SLbool useCubemap)
Definition: SLShadowMap.h:62
bool dirExists(const string &path)
Returns true if a directory exists.
Definition: Utils.cpp:790
bool makeDir(const string &path)
Creates a directory with given path.
Definition: Utils.cpp:810