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