30 layout (location = 0) in vec4  a_position;       // Vertex position attribute 
   31 layout (location = 1) in vec3  a_normal;         // Vertex normal attribute)"; 
   33 layout (location = 0) in vec3  a_position;       // Particle position attribute)"; 
   35 layout (location = 1) in vec3  a_velocity;       // Particle velocity attribute)"; 
   37 layout (location = 2) in float a_startTime;      // Particle start time attribute)"; 
   39 layout (location = 3) in vec3  a_initialVelocity;// Particle initial velocity attribute)"; 
   41 layout (location = 4) in float a_rotation;       // Particle rotation attribute)"; 
   43 layout (location = 5) in float a_angularVelo;    // Particle rotation rate attribute)"; 
   45 layout (location = 6) in uint  a_texNum;         // Particle rotation attribute)"; 
   47 layout (location = 7) in vec3  a_initialPosition;// Particle initial position attribute)"; 
   49 layout (location = 8) in vec3  a_instancePos;    // Particle instance triangle vertex position attribute)"; 
   51 layout (location = 2) in vec2  a_uv0;            // Vertex tex.coord. 1 for diffuse color)"; 
   53 layout (location = 3) in vec2  a_uv1;            // Vertex tex.coord. 2 for AO)"; 
   55 layout (location = 5) in vec4  a_tangent;        // Vertex tangent attribute)"; 
   57 layout (location = 6) in ivec4 a_jointIds;       // Vertex joint indices attributes 
   58 layout (location = 7) in vec4  a_jointWeights;   // Vertex joint weights attributes)"; 
   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.))"; 
   66 uniform mat4  u_vOmvMatrix;         // view or modelview matrix)"; 
   70 uniform mat4 u_jointMatrices[100];          // Joint matrices for skinning 
   71 uniform bool u_skinningEnabled;             // Flag if the shader should perform skinning 
   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)"; 
   82 #define PI 3.1415926538 
   83 #define TWOPI 6.2831853076 
   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)"; 
   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)"; 
   97 uniform float u_colorArr[256 * 3];  // Array of color value (for color over life))"; 
   99 uniform float u_colorArr[256 * 3];  // Array of color value (for color over life))"; 
  101 uniform float u_deltaTime;          // Elapsed time between frames)"; 
  103 uniform vec3  u_pGPosition;         // Particle Generator position)"; 
  105 uniform float u_accConst;           // Particle acceleration constant)"; 
  107 uniform vec3  u_acceleration;       // Particle acceleration)"; 
  109 uniform vec3  u_gravity;            // Particle gravity)"; 
  111 uniform float u_angularVelo;        // Particle angular velocity)"; 
  113 uniform int   u_col;                // Number of column of flipbook texture)"; 
  115 uniform int   u_row;                // Number of row of flipbook texture)"; 
  117 uniform int   u_condFB;             // Condition to update texNum)"; 
  121 out     vec3  v_P_VS;                   // Point of illumination in view space (VS))"; 
  123 out     vec3  v_P_WS;                   // Point of illumination in world space (WS))"; 
  125 out     vec3  v_N_VS;                   // Normal at P_VS in view space (VS))"; 
  127 out     vec3  v_R_OS;                   // Reflection vector in object space (WS))"; 
  129 out     vec2  v_uv0;                    // Texture coordinate 0 output)"; 
  131 out     vec2  v_uv1;                    // Texture coordinate 1 output)"; 
  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)"; 
  138 vec3 colorByAge(float age) 
  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]); 
  146 vec3 colorByAge(float age) 
  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]); 
  158     float transparency; // Transparency of a particle)"; 
  160     float rotation;     // Rotation of a particle)"; 
  162     float size;         // Size of a particle )"; 
  164     vec3 color;         // Color of a particle )"; 
  166     uint texNum;        // Num of texture in flipbook)"; 
  171 out float transparency;             // transparency of a particle )"; 
  173 in float transparency;              // transparency of a particle )"; 
  176     vec4 color = vec4(colorByAge(v_age/u_tTL), 1.0);   // Particle color)"; 
  178     vec4 color = u_color;      // Particle color)"; 
  180     color.w *= transparency;   // Apply transparency)"; 
  182 uniform mat4  u_pMatrix;            // Projection matrix)"; 
  184 uniform mat4  u_vYawPMatrix;        // Projection matrix)"; 
  186 uniform vec4  u_color;              // Particle color)"; 
  188 uniform float u_scale;              // Particle scale 
  189 uniform float u_radiusW;            // Particle width radius) 
  190 uniform float u_radiusH;            // Particle height radius)"; 
  195 out     vec3  tf_position;          // To transform feedback)"; 
  197 out     vec3  tf_velocity;          // To transform feedback)"; 
  199 out     float tf_startTime;         // To transform feedback)"; 
  201 out     vec3  tf_initialVelocity;   // To transform feedback)"; 
  203 out     float tf_rotation;          // To transform feedback)"; 
  205 out     float tf_angularVelo;       // To transform feedback)"; 
  207 flat out uint  tf_texNum;           // To transform feedback)"; 
  209 out     vec3  tf_initialPosition;   // To transform feedback)"; 
  213 //----------------------------------------------------------------------------- 
  218     mat4 mvMatrix = u_vMatrix * u_mMatrix; 
  219     v_P_VS = vec3(mvMatrix * ${localPosition});  // vertex position in view space)"; 
  221     v_P_WS = vec3(u_mMatrix * ${localPosition}); // vertex position in world space)"; 
  223     mat3 invMvMatrix = mat3(inverse(mvMatrix)); 
  224     mat3 nMatrix = transpose(invMvMatrix); 
  225     v_N_VS = vec3(nMatrix * ${localNormal});     // vertex normal in view space)"; 
  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;)"; 
  231     v_uv0 = a_uv0;  // pass diffuse color tex.coord. 0 for interpolation)"; 
  233     v_uv1 = a_uv1;  // pass diffuse color tex.coord. 1 for interpolation)"; 
  235     vec4 skinnedPosition; 
  238     if (u_skinningEnabled) 
  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; 
  249         skinnedPosition = jm * a_position; 
  250         skinnedNormal = mat3(jm) * a_normal; 
  254         skinnedPosition = a_position; 
  255         skinnedNormal = a_normal; 
  259     vec4 skinnedPosition; 
  263     if (u_skinningEnabled) 
  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; 
  274         skinnedPosition = jm * a_position; 
  275         skinnedNormal = mat3(jm) * a_normal; 
  276         skinnedTangent = vec4(mat3(jm) * a_tangent.xyz, a_tangent.w); 
  280         skinnedPosition = a_position; 
  281         skinnedNormal = a_normal; 
  282         skinnedTangent = a_tangent; 
  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); 
  294     // Transform vector to the eye into tangent space 
  295     v_eyeDirTS = -v_P_VS;  // eye vector in view space 
  298     for (int i = 0; i < NUM_LIGHTS; ++i) 
  300         // Transform spot direction into tangent space 
  301         v_spotDirTS[i] = u_lightSpotDir[i]; 
  302         v_spotDirTS[i]  *= TBN; 
  304         // Transform vector to the light 0 into tangent space 
  305         vec3 L = u_lightPosVS[i].xyz - v_P_VS; 
  307         v_lightDirTS[i] *= TBN; 
  315         vert.transparency = 0.0; // To be discard, because the particle is to be born 
  317         vert.transparency = 1.0;)"; 
  320         vert.transparency = 0.0; // To be discard, because the particle is to be born 
  323         vert.transparency = age / u_tTL;  // Get by the ratio age:lifetime)"; 
  325         vert.transparency = 1.0 - vert.transparency;  // Linear)"; 
  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)"; 
  334     vert.rotation = a_rotation;)"; 
  336     vert.size = age / u_tTL;)"; 
  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)"; 
  344     vert.color = colorByAge(age/u_tTL);)"; 
  346 out float v_age; // Age of a particle)"; 
  348 in float v_age; // Age of a particle)"; 
  350     vert.texNum = a_texNum;)"; 
  352     float age = u_time - a_startTime;   // Get the age of the particle)"; 
  354     v_texCoord = 0.5 * (a_instancePos.xy + vec2(1.0));)"; 
  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)); 
  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)); 
  367     vec3 position = a_instancePos; 
  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)"; 
  377     position = size * position; 
  381         transparency = 0.0; // To be discard, because the particle is to be born 
  383         transparency = 1.0;)"; 
  386         transparency = 0.0; // To be discard, because the particle is to be born 
  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)"; 
  398     position = vec3(u_radiusW * position.x, u_radiusH * position.y, position.z); 
  399     position = u_scale * position; 
  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); 
  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)); 
  414     //gl_Position =  vec4(a_position + a_instancePos, 1); 
  415     gl_Position =  u_pMatrix * u_vYawPMatrix * vec4(a_position + position, 1.0); 
  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); 
  427     gl_Position = vec4(a_position, 1); 
  432     // pass the vertex w. the fix-function transform 
  433     gl_Position = u_pMatrix * mvMatrix * ${localPosition}; 
  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)"; 
  441     tf_position = a_position;           // Init the output variable)"; 
  443     tf_velocity = a_velocity;           // Init the output variable)"; 
  445     tf_startTime = a_startTime;         // Init the output variable)"; 
  447     tf_initialVelocity = a_initialVelocity; // Init the output variable)"; 
  449     tf_rotation = a_rotation;           // Init the output variable)"; 
  451     tf_angularVelo = a_angularVelo;     // Init the output variable)"; 
  453     tf_texNum = a_texNum;               // Init the output variable)"; 
  455     tf_initialPosition = a_initialPosition; // Init the output variable)"; 
  457     tf_startTime += u_difTime;          // Add time to resume after frustum culling 
  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 
  465             // The particle is past its lifetime, recycle. 
  466             tf_position = u_pGPosition; // Reset position)"; 
  468             // The particle is past its lifetime, recycle. 
  469             tf_position = a_initialPosition + u_pGPosition; // Reset position)"; 
  471             tf_velocity = a_initialVelocity; // Reset velocity)"; 
  473             tf_startTime = u_time + (age - u_tTL); // Reset start time to actual time with counter gap)"; 
  475             tf_startTime = u_time; // Reset start time to actual time)"; 
  479             // The particle is alive, update. 
  480             tf_position += tf_velocity * u_deltaTime;   // Scale the translation by the delta time)"; 
  482             tf_rotation = mod(tf_rotation + (u_angularVelo*u_deltaTime), TWOPI);)"; 
  484             tf_rotation = mod(tf_rotation + (tf_angularVelo*u_deltaTime), TWOPI);)"; 
  486             tf_velocity += tf_initialVelocity * u_deltaTime * u_accConst;  // Amplify the velocity)"; 
  488             tf_velocity += u_deltaTime * u_acceleration;    // Amplify the velocity)"; 
  490             tf_velocity += u_deltaTime * u_gravity;         // Apply gravity)"; 
  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 
  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)"; 
  509     float transparency; // Transparency of a particle)"; 
  511     float rotation;     // Rotation of a particle)"; 
  513     float size;         // Size of a particle )"; 
  515     vec3 color;         // Color of a particle )"; 
  517     uint texNum;        // Num of texture in flipbook)"; 
  522 uniform mat4  u_pMatrix;        // Projection matrix)"; 
  524 uniform mat4  u_vYawPMatrix;    // Projection matrix)"; 
  526 uniform float u_scale;          // Particle scale 
  527 uniform float u_radiusW;        // Particle width radius) 
  528 uniform float u_radiusH;        // Particle height radius)"; 
  530 uniform vec4  u_color;          // Particle color)"; 
  532 uniform int   u_col;            // Number of column of flipbook texture)"; 
  534 uniform int   u_row;            // Number of row of flipbook texture)"; 
  537 out vec4 v_particleColor;       // The resulting color per vertex)"; 
  539 out vec2 v_texCoord;                // Texture coordinate at vertex)"; 
  541 out vec2 v_texCoord;                // Texture coordinate at vertex)"; 
  544     float scale = u_scale;)"; 
  546     scale *= vert[0].size;)"; 
  548     float radiusW = u_radiusW * scale; 
  549     float radiusH = u_radiusH * scale;)"; 
  551     vec4 P = gl_in[0].gl_Position;    // Position of the point that we received)"; 
  553     mat2 rot = mat2(cos(vert[0].rotation),-sin(vert[0].rotation), 
  554                     sin(vert[0].rotation), cos(vert[0].rotation)); // Matrix of rotation)"; 
  556     mat2 rot = mat2(1.0, 0.0, 0.0, 1.0);     // Matrix of rotation)"; 
  558     vec4 color = u_color;                    // Particle color)"; 
  560     vec4 color = vec4(vert[0].color, 1.0);   // Particle color)"; 
  562     vec4 color = vec4( 0.0, 0.0, 0.0, 1.0);  // Particle color)"; 
  564     color.w *= vert[0].transparency;         // Apply transparency)"; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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; 
  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); 
  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; 
  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; 
  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; 
  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; 
  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); 
  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; 
  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; 
  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; 
  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; 
  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); 
  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; 
  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; 
  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; 
  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; 
  762     EndPrimitive();  // Send primitives to fragment shader 
  766 in      vec3        v_P_VS;                     // Interpol. point of illumination in view space (VS))"; 
  768 in      vec3        v_P_WS;                     // Interpol. point of illumination in world space (WS))"; 
  770 in      vec3        v_N_VS;                     // Interpol. normal at v_P_VS in view space)"; 
  772 in      vec3        v_R_OS;                     // Interpol. reflect in object space)"; 
  774 in      vec2        v_uv0;                      // Texture coordinate varying for uv 0)"; 
  776 in      vec2        v_uv1;                      // Texture coordinate varying for uv 1)"; 
  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)"; 
  783 in      vec4        v_particleColor;            // interpolated color from the geometry shader)"; 
  785 in      vec2        v_texCoord;                 // interpolated texture coordinate)"; 
  788 uniform float       u_oneOverGamma;             // 1.0f / Gamma correction value)"; 
  790 uniform bool        u_doWireFrame;              // Boolean for wireFrame)"; 
  793    o_fragColor = vec4(0,0,0,0); // Need to be here for the compilation 
  798     // Just set the interpolated color from the vertex shader 
  799    o_fragColor = v_particleColor; 
  801    // componentwise multiply w. texture color 
  803         o_fragColor *= texture(u_matTextureDiffuse0, v_texCoord); 
  805    if(o_fragColor.a < 0.001) 
  809    // componentwise multiply w. texture color 
  811         o_fragColor = texture(u_matTextureDiffuse0, v_texCoord); 
  813         o_fragColor = vec4(0,0,0,1.0); 
  815     o_fragColor.a *= v_particleColor.a; 
  817    if(o_fragColor.a < 0.001) 
  821    // componentwise multiply w. texture color 
  823         o_fragColor = texture(u_matTextureDiffuse0, v_texCoord); 
  825         o_fragColor = vec4(0,0,0,1.0); 
  827     o_fragColor.a *= transparency; 
  829    if(o_fragColor.a < 0.001) 
  833    // Just set the interpolated color from the vertex shader 
  835    // componentwise multiply w. texture color 
  837        o_fragColor *= texture(u_matTextureDiffuse0, v_texCoord); 
  839    if(o_fragColor.a < 0.001) 
  843     //Same color for each wireframe 
  845         o_fragColor =  vec4(0,0,0,1.0); 
  847    o_fragColor.rgb = pow(o_fragColor.rgb, vec3(u_oneOverGamma)); 
  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 
  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 
  874 uniform vec4        u_matAmbi;                      // ambient color reflection coefficient (ka))"; 
  876 uniform vec4        u_matDiff;                      // diffuse color reflection coefficient (kd))"; 
  878 uniform vec4        u_matEmis;                      // emissive color (ke))"; 
  880 uniform float       u_matRough;                     // roughness factor (0-1))"; 
  882 uniform float       u_matMetal;                     // metalness factor (0-1)"; 
  885 uniform sampler2D   u_matTextureDiffuse0;           // Diffuse color map)"; 
  887 uniform sampler2D   u_matTextureNormal0;            // Normal bump map)"; 
  889 uniform sampler2D   u_matTextureEmissive0;          // PBR material emissive texture)"; 
  891 uniform sampler2D   u_matTextureOcclusion0;         // Ambient occlusion map)"; 
  893 uniform sampler2D   u_matTextureRoughness0;         // PBR material roughness texture)"; 
  895 uniform sampler2D   u_matTextureMetallic0;          // PBR material metallic texture)"; 
  897 uniform sampler2D   u_matTextureRoughMetal0;        // PBR material roughness-metallic texture)"; 
  899 uniform sampler2D   u_matTextureOccluRoughMetal0;   // PBR material occlusion-roughness-metalic texture)"; 
  902 uniform bool        u_matGetsShadows;               // flag if material receives shadows)"; 
  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)"; 
  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)"; 
  929 out     vec4        o_fragColor;        // output fragment color)"; 
  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 
  942     // Calculate diffuse & specular factors 
  943     float diffFactor = max(dot(N, S), 0.0); 
  944     float specFactor = 0.0; 
  948         vec3 H = normalize(S + E);// Half vector H between S and E 
  949         specFactor = pow(max(dot(N, H), 0.0), u_matShin); 
  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); 
  957 //----------------------------------------------------------------------------- 
  958 void pointLightBlinnPhong( in    int   i, 
  968     // Calculate attenuation over distance & normalize L 
  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) 
  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 
  989     // Calculate spot attenuation 
  990     float spotAtt = 1.0;// Spot attenuation 
  991     if (u_lightSpotDeg[i] < 180.0) 
  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 
  998             spotAtt = max(pow(spotDot, u_lightSpotExp[i]), 0.0); 
 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); 
 1008 //----------------------------------------------------------------------------- 
 1009 vec3 fresnelSchlick(float cosTheta, vec3 F0) 
 1011     return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); 
 1013 // ---------------------------------------------------------------------------- 
 1014 vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) 
 1016     return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0); 
 1018 //----------------------------------------------------------------------------- 
 1019 float distributionGGX(vec3 N, vec3 H, float roughness) 
 1021     float PI     = 3.14159265; 
 1022     float a      = roughness*roughness; 
 1024     float NdotH  = max(dot(N, H), 0.0); 
 1025     float NdotH2 = NdotH*NdotH; 
 1028     float denom = (NdotH2 * (a2 - 1.0) + 1.0); 
 1029     denom = PI * denom * denom; 
 1033 //----------------------------------------------------------------------------- 
 1034 float geometrySchlickGGX(float NdotV, float roughness) 
 1036     float r = (roughness + 1.0); 
 1037     float k = (r*r) / 8.0; 
 1040     float denom = NdotV * (1.0 - k) + k; 
 1044 //----------------------------------------------------------------------------- 
 1045 float geometrySmith(vec3 N, vec3 E, vec3 L, float roughness) 
 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); 
 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 
 1065     float PI = 3.14159265; 
 1066     vec3 H = normalize(E + S);  // Normalized halfvector between eye and light vector 
 1068     vec3 radiance = u_lightDiff[i].rgb;  // Per light radiance without attenuation 
 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); 
 1076     vec3 kD = vec3(1.0) - kS; 
 1077     kD *= 1.0 - matMetal; 
 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; 
 1083     // add to outgoing radiance Lo 
 1084     float NdotL = max(dot(N, S), 0.0); 
 1086     Lo += (kD*matDiff.rgb/PI + specular) * radiance * NdotL * (1.0 - shadow); 
 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 
 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 
 1106     // Calculate spot attenuation 
 1107     if (u_lightSpotDeg[i] < 180.0) 
 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); 
 1117     vec3 radiance = u_lightDiff[i].rgb * att;  // per light radiance 
 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); 
 1126     vec3 kD = vec3(1.0) - kS; 
 1127     kD *= 1.0 - matMetal; 
 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; 
 1133     // add to outgoing radiance Lo 
 1134     float NdotL = max(dot(N, L), 0.0); 
 1136     Lo += (kD*matDiff.rgb/PI + specular) * radiance * NdotL * (1.0 - shadow); 
 1140 //----------------------------------------------------------------------------- 
 1141 void doStereoSeparation() 
 1143     // See SLProjType in SLEnum.h 
 1144     if (u_camProjType > 8) // stereoColors 
 1146         // Apply color filter but keep alpha 
 1147         o_fragColor.rgb = u_camStereoColors * o_fragColor.rgb; 
 1149     else if (u_camProjType == 6) // stereoLineByLine 
 1151         if (mod(floor(gl_FragCoord.y), 2.0) < 0.5)// even 
 1153             if (u_camStereoEye ==-1) 
 1157             if (u_camStereoEye == 1) 
 1161     else if (u_camProjType == 7) // stereoColByCol 
 1163         if (mod(floor(gl_FragCoord.x), 2.0) < 0.5)// even 
 1165             if (u_camStereoEye ==-1) 
 1169             if (u_camStereoEye == 1) 
 1173     else if (u_camProjType == 8) // stereoCheckerBoard 
 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 
 1179             if (u_camStereoEye ==-1) 
 1183             if (u_camStereoEye == 1) 
 1190 //----------------------------------------------------------------------------- 
 1191 vec4 fogBlend(vec3 P_VS, vec4 inColor) 
 1193     float factor = 0.0f; 
 1194     float distance = length(P_VS); 
 1196     switch (u_camFogMode) 
 1199             factor = (u_camFogEnd - distance) / (u_camFogEnd - u_camFogStart); 
 1202             factor = exp(-u_camFogDensity * distance); 
 1205             factor = exp(-u_camFogDensity * distance * u_camFogDensity * distance); 
 1209     vec4 outColor = factor * inColor + (1.0 - factor) * u_camFogColor; 
 1210     outColor = clamp(outColor, 0.0, 1.0); 
 1215 //----------------------------------------------------------------------------- 
 1216 void doColoredShadows(in vec3 N) 
 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)); 
 1225     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1229             if (u_lightPosVS[i].w == 0.0) 
 1231                 // We use the spot light direction as the light direction vector 
 1232                 vec3 S = normalize(-u_lightSpotDir[i].xyz); 
 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) 
 1238                     int casIndex = getCascadesDepthIndex(i, u_lightNumCascades[i]); 
 1239                     o_fragColor.rgb += shadow * SHADOW_COLOR[casIndex]; 
 1241                     o_fragColor.rgb += shadow * SHADOW_COLOR[0]; 
 1245                 vec3 L = u_lightPosVS[i].xyz - v_P_VS; // Vector from v_P to light in VS 
 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]; 
 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 
 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 
 1266     vec3 E = normalize(v_eyeDirTS);   // normalized interpolated eye direction 
 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); 
 1272     vec4  matEmis  = u_matEmis;)"; 
 1274     vec4  matEmis  = texture(u_matTextureEmissive0, v_uv0);)"; 
 1276     float matOccl  = 1.0;)"; 
 1278     float matOccl  = texture(u_matTextureOcclusion0, v_uv0).r;)"; 
 1280     float matOccl  = texture(u_matTextureOcclusion0, v_uv1).r;)"; 
 1284     // Get the reflection from all lights into Ia, Id & Is 
 1285     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1289             if (u_lightPosVS[i].w == 0.0) 
 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); 
 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); 
 1306     // Get the reflection from all lights into Ia, Id & Is 
 1307     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1311             if (u_lightPosVS[i].w == 0.0) 
 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); 
 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); 
 1328     // Get the reflection from all lights into Ia, Id & Is 
 1329     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1333             if (u_lightPosVS[i].w == 0.0) 
 1335                 // We use the spot light direction as the light direction vector 
 1336                 vec3 S = normalize(-u_lightSpotDir[i].xyz); 
 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); 
 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 
 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); 
 1356     // Get the reflection from all lights into Ia, Id & Is 
 1357     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1361             if (u_lightPosVS[i].w == 0.0) 
 1363                 // We use the spot light direction as the light direction vector 
 1364                 vec3 S = normalize(-v_spotDirTS[i]); 
 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); 
 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 
 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); 
 1383     // Sum up all the reflected color components 
 1384     o_fragColor =  u_matEmis + 
 1386                    Ia * u_matAmbi * matOccl + 
 1390     // For correct alpha blending overwrite alpha component 
 1391     o_fragColor.a = u_matDiff.a; 
 1394     // Sum up all the reflected color components 
 1395     o_fragColor =  u_matEmis + 
 1397                    Ia * u_matAmbi * matOccl + 
 1400     // Componentwise multiply w. texture color 
 1401     o_fragColor *= texture(u_matTextureDiffuse0, v_uv0); 
 1403     // add finally the specular RGB-part 
 1404     vec4 specColor = Is * u_matSpec; 
 1405     o_fragColor.rgb += specColor.rgb; 
 1409     // Colorize cascaded shadows for debugging purpose 
 1410     if (u_lightsDoColoredShadows) 
 1411         doColoredShadows(N); 
 1415     // Apply fog by blending over distance 
 1417         o_fragColor = fogBlend(v_P_VS, o_fragColor); 
 1419     // Apply gamma correction 
 1420     o_fragColor.rgb = pow(o_fragColor.rgb, vec3(u_oneOverGamma)); 
 1422     // Apply stereo eye separation 
 1423     if (u_camProjType > 1) 
 1424         doStereoSeparation(); 
 1429     vec4  matDiff  = u_matDiff;)"; 
 1431     vec4  matDiff  = pow(texture(u_matTextureDiffuse0, v_uv0), vec4(2.2));)"; 
 1433     vec4  matEmis  = u_matEmis;)"; 
 1435     vec4  matEmis  = pow(texture(u_matTextureEmissive0, v_uv0), vec4(2.2));)"; 
 1437     float matRough = u_matRough;)"; 
 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;)"; 
 1445     float matMetal = u_matMetal;)"; 
 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;)"; 
 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;)"; 
 1462     vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N) 
 1463     F0 = mix(F0, matDiff.rgb, matMetal); 
 1465     // Get the reflection from all lights into Lo 
 1466     vec3 Lo = vec3(0.0); 
 1467     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1471             if (u_lightPosVS[i].w == 0.0) 
 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, 
 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, 
 1498     vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N) 
 1499     F0 = mix(F0, matDiff.rgb, matMetal); 
 1501     // Get the reflection from all lights into Lo 
 1502     vec3 Lo = vec3(0.0); 
 1503     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1507             if (u_lightPosVS[i].w == 0.0) 
 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, 
 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, 
 1534     vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N) 
 1535     F0 = mix(F0, matDiff.rgb, matMetal); 
 1537     // Get the reflection from all lights into Lo 
 1538     vec3 Lo = vec3(0.0); 
 1539     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1543             if (u_lightPosVS[i].w == 0.0) 
 1545                 // We use the spot light direction as the light direction vector 
 1546                 vec3 S = normalize(-u_lightSpotDir[i].xyz); 
 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, 
 1559                 vec3 L = u_lightPosVS[i].xyz - v_P_VS; 
 1560                 vec3 S = u_lightSpotDir[i]; // normalized spot direction in VS 
 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, 
 1576     vec3 F0 = vec3(0.04); // Init Fresnel reflection at 90 deg. (0 to N) 
 1577     F0 = mix(F0, matDiff.rgb, matMetal); 
 1579     // Get the reflection from all lights into Lo 
 1580     vec3 Lo = vec3(0.0); 
 1581     for (int i = 0; i < NUM_LIGHTS; ++i) 
 1585             if (u_lightPosVS[i].w == 0.0) 
 1587                 // We use the spot light direction as the light direction vector 
 1588                 vec3 S = normalize(-v_spotDirTS[i]); 
 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, 
 1601                 vec3 L = v_lightDirTS[i]; // Vector from v_P to light in TS 
 1602                 vec3 S = normalize(-v_spotDirTS[i]); 
 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, 
 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; 
 1621     vec3 color   = ambient + matEmis.rgb + Lo; 
 1624     color = color / (color + vec3(1.0)); 
 1625     o_fragColor = vec4(color, 1.0); 
 1627     // For correct alpha blending overwrite alpha component 
 1628     o_fragColor.a = matDiff.a; 
 1631     // Build diffuse reflection from environment light map 
 1632     vec3 F = fresnelSchlickRoughness(max(dot(N, E), 0.0), F0, matRough); 
 1635     kD *= 1.0 - matMetal; 
 1636     vec3 irradiance = texture(u_skyIrradianceCubemap, N).rgb; 
 1637     vec3 diffuse    = kD * irradiance * matDiff.rgb; 
 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; 
 1646     vec3 color = ambient + matEmis.rgb + Lo; 
 1648     // Exposure tone mapping 
 1649     vec3 mapped = vec3(1.0) - exp(-color * u_skyExposure); 
 1650     o_fragColor = vec4(mapped, 1.0); 
 1652     // For correct alpha blending overwrite alpha component 
 1653     o_fragColor.a = matDiff.a; 
 1657     float x = (gl_FragCoord.x - u_camBkgdLeft) / u_camBkgdWidth; 
 1658     float y = (gl_FragCoord.y - u_camBkgdBottom) / u_camBkgdHeight; 
 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); 
 1663         o_fragColor = texture(u_matTextureDiffuse0, vec2(x, y)); 
 1665     vec3 N = normalize(v_N_VS);  // A input normal has not anymore unit length 
 1668     // Colorize cascaded shadows for debugging purpose 
 1669     if (u_lightsDoColoredShadows) 
 1670         doColoredShadows(N); 
 1673         for (int i = 0; i < NUM_LIGHTS; ++i) 
 1677                 if (u_lightPosVS[i].w == 0.0) 
 1679                     // We use the spot light direction as the light direction vector 
 1680                     vec3 S = normalize(-u_lightSpotDir[i].xyz); 
 1682                     // Test if the current fragment is in shadow 
 1683                     shadow = u_matGetsShadows ? shadowTest(i, N, S) : 0.0; 
 1687                     vec3 L = u_lightPosVS[i].xyz - v_P_VS; // Vector from v_P to light in VS 
 1689                     // Test if the current fragment is in shadow 
 1690                     shadow = u_matGetsShadows ? shadowTest(i, N, L) : 0.0; 
 1692                 o_fragColor = o_fragColor * min(1.0 - shadow + u_matAmbi.r, 1.0); 
 1726                                             SLbool      supportGPUSkinning,
 
 1727                                             string&     programName)
 
 1729     assert(mat && 
"No material pointer passed!");
 
 1730     assert(lights && !lights->empty() && 
"No lights passed!");
 
 1732     programName = 
"gen";
 
 1735         programName += 
"VideoBkgdDm";
 
 1737         programName += 
"Blinn";
 
 1739         programName += 
"Cook";
 
 1741         programName += 
"Custom";
 
 1747     for (
auto light : *lights)
 
 1749         if (light->positionWS().w == 0.0f)
 
 1751             if (light->doCascadedShadows())
 
 1752                 programName += 
"C" + std::to_string(light->shadowMap()->numCascades()); 
 
 1756         else if (light->spotCutOffDEG() < 180.0f)
 
 1760         if (light->createsShadows())
 
 1764     if (supportGPUSkinning)
 
 1765         programName += 
"-S";
 
 1790                                               string&     programName,
 
 1794     assert(mat && 
"No material pointer passed!");
 
 1795     programName = 
"gen";
 
 1798         programName += 
"Particle";
 
 1800         programName += 
"Custom";
 
 1805         programName += 
"-Draw";
 
 1808             programName += 
"-Inst";
 
 1811         GLint billboardType = mat->
ps()->billboardType();      
 
 1812         bool  AlOvLi        = mat->
ps()->doAlphaOverLT();      
 
 1813         bool  AlOvLiCu      = mat->
ps()->doAlphaOverLTCurve(); 
 
 1814         bool  SiOvLi        = mat->
ps()->doSizeOverLT();       
 
 1815         bool  SiOvLiCu      = mat->
ps()->doSizeOverLTCurve();  
 
 1816         bool  Co            = mat->
ps()->doColor();            
 
 1817         bool  CoOvLi        = mat->
ps()->doColorOverLT();      
 
 1818         bool  FlBoTex       = mat->
ps()->doFlipBookTexture();  
 
 1819         bool  WS            = mat->
ps()->doWorldSpace();       
 
 1820         bool  rot           = mat->
ps()->doRotation();         
 
 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";
 
 1834         bool counterGap = mat->
ps()->doCounterGap();      
 
 1835         bool acc        = mat->
ps()->doAcc();             
 
 1836         bool accDiffDir = mat->
ps()->doAccDiffDir();      
 
 1837         bool gravity    = mat->
ps()->doGravity();         
 
 1838         bool FlBoTex    = mat->
ps()->doFlipBookTexture(); 
 
 1839         bool rot        = mat->
ps()->doRotation();        
 
 1840         bool rotRange   = mat->
ps()->doRotRange();        
 
 1841         bool shape      = mat->
ps()->doShape();           
 
 1842         programName += 
"-Update";
 
 1843         if (counterGap) programName += 
"-CG";
 
 1844         if (rot) programName += 
"-RT";
 
 1845         if (rot) programName += rotRange ? 
"ra" : 
"co";
 
 1848             programName += 
"-AC";
 
 1849             programName += accDiffDir ? 
"di" : 
"co";
 
 1851         if (gravity) programName += 
"-GR";
 
 1852         if (FlBoTex) programName += 
"-FB";
 
 1853         if (shape) programName += 
"-SH";
 
 1865                                             SLbool      supportGPUSkinning)
 
 1867     assert(mat && 
"No material pointer passed!");
 
 1868     assert(!lights->empty() && 
"No lights passed!");
 
 1879     bool env = mat->
skybox() != 
nullptr;          
 
 1897             SL_EXIT_MSG(
"SLGLProgramGenerated::buildProgramCode: Unknown program for RM_Custom.");
 
 1900         SL_EXIT_MSG(
"SLGLProgramGenerated::buildProgramCode: Unknown Lighting Model.");
 
 1913     if (mat->
name() == 
"IBLMat")
 
 1915         std::cout << 
"build program code for IBLMat" << std::endl;
 
 1917     assert(mat && 
"No material pointer passed!");
 
 1937                                            SLbool      supportGPUSkinning)
 
 1939     assert(mat && lights);
 
 1959     bool sky  = mat->
skybox() != 
nullptr;
 
 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");
 
 2071                                             SLbool      supportGPUSkinning)
 
 2073     assert(mat && lights);
 
 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");
 
 2190     GLint billboardType = mat->
ps()->billboardType();      
 
 2191     bool  rot           = mat->
ps()->doRotation();         
 
 2192     bool  AlOvLi        = mat->
ps()->doAlphaOverLT();      
 
 2193     bool  Co            = mat->
ps()->doColor();            
 
 2194     bool  CoOvLi        = mat->
ps()->doColorOverLT();      
 
 2195     bool  AlOvLiCu      = mat->
ps()->doAlphaOverLTCurve(); 
 
 2196     bool  SiOvLi        = mat->
ps()->doSizeOverLT();       
 
 2197     bool  SiOvLiCu      = mat->
ps()->doSizeOverLTCurve();  
 
 2198     bool  FlBoTex       = mat->
ps()->doFlipBookTexture();  
 
 2325     GLint billboardType = mat->
ps()->billboardType();      
 
 2326     bool  rot           = mat->
ps()->doRotation();         
 
 2327     bool  AlOvLi        = mat->
ps()->doAlphaOverLT();      
 
 2328     bool  Co            = mat->
ps()->doColor();            
 
 2329     bool  CoOvLi        = mat->
ps()->doColorOverLT();      
 
 2330     bool  AlOvLiCu      = mat->
ps()->doAlphaOverLTCurve(); 
 
 2331     bool  SiOvLi        = mat->
ps()->doSizeOverLT();       
 
 2332     bool  SiOvLiCu      = mat->
ps()->doSizeOverLTCurve();  
 
 2333     bool  FlBoTex       = mat->
ps()->doFlipBookTexture();  
 
 2476     bool counterGap = mat->
ps()->doCounterGap();      
 
 2477     bool acc        = mat->
ps()->doAcc();             
 
 2478     bool accDiffDir = mat->
ps()->doAccDiffDir();      
 
 2479     bool gravity    = mat->
ps()->doGravity();         
 
 2480     bool FlBoTex    = mat->
ps()->doFlipBookTexture(); 
 
 2481     bool rot        = mat->
ps()->doRotation();        
 
 2482     bool rotRange   = mat->
ps()->doRotRange();        
 
 2483     bool shape      = mat->
ps()->doShape();           
 
 2579     setVariable(vertCode, 
"localPosition", 
"a_position");
 
 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 
 2615     for (
auto light : *lights)
 
 2617         if (light->createsShadows())
 
 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 
 2636     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2638         SLLight* light = lights->at(i);
 
 2645                 u_lightSm += 
"uniform mat4        u_lightSpace_" + std::to_string(i) + 
"[6];\n";
 
 2649                 u_lightSm += 
"uniform mat4        u_lightSpace_" + std::to_string(i) + 
"[" + std::to_string(shadowMap->
numCascades()) + 
"];\n";
 
 2653                 u_lightSm += 
"uniform mat4        u_lightSpace_" + std::to_string(i) + 
";\n";
 
 2662     string smDecl = 
"\n";
 
 2663     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2665         SLLight* light = lights->at(i);
 
 2670                 smDecl += 
"uniform samplerCube u_shadowMapCube_" + to_string(i) + 
";\n";
 
 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";
 
 2676                 smDecl += 
"uniform float       u_cascadesFactor_" + to_string(i) + 
";\n";
 
 2679                 smDecl += 
"uniform sampler2D   u_shadowMap_" + to_string(i) + 
";\n";
 
 2688     bool doCascadedSM = 
false;
 
 2689     for (
SLLight* light : *lights)
 
 2691         if (light->doCascadedShadows())
 
 2693             doCascadedSM = 
true;
 
 2698     string shadowTestCode = R
"( 
 2699 //----------------------------------------------------------------------------- 
 2700 int vectorToFace(vec3 vec) // Vector to process 
 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; 
 2708         return vec.z > 0.0 ? 4 : 5; 
 2710 //----------------------------------------------------------------------------- 
 2711 int getCascadesDepthIndex(in int i, int numCascades) 
 2716     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2718         SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 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";
 
 2728     shadowTestCode += R
"( 
 2729     float fi = u_camClipNear; 
 2732     for (int i = 0; i < numCascades-1; i++) 
 2735         fi = factor * u_camClipNear * pow((u_camClipFar/(factor*u_camClipNear)), float(i+1)/float(numCascades)); 
 2739     return numCascades-1; 
 2741 //----------------------------------------------------------------------------- 
 2742 float shadowTest(in int i, in vec3 N, in vec3 lightDir) 
 2744     if (u_lightCreatesShadows[i]) 
 2746         // Calculate position in light space 
 2748         vec3 lightToFragment = v_P_WS - u_lightPosWS[i].xyz; 
 2751     if (doCascadedSM > 0)
 
 2753         shadowTestCode += R
"( 
 2756         if (u_lightNumCascades[i] > 0) 
 2758             index = getCascadesDepthIndex(i, u_lightNumCascades[i]); 
 2760         for (
SLuint i = 0; i < lights->size(); ++i)
 
 2762             SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2764                 shadowTestCode += 
"    if (i == " + std::to_string(i) + 
") { lightSpace = u_lightSpace_" + std::to_string(i) + 
"[index]; }\n";
 
 2766         shadowTestCode += R
"( 
 2768         else if (u_lightUsesCubemap[i]) 
 2770         for (
SLuint i = 0; i < lights->size(); ++i)
 
 2772             SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2774                 shadowTestCode += 
"    if (i == " + std::to_string(i) + 
") { lightSpace = u_lightSpace_" + std::to_string(i) + 
"[vectorToFace(lightToFragment)]; }\n";
 
 2776         shadowTestCode += R
"( 
 2781         for (
SLuint i = 0; i < lights->size(); ++i)
 
 2783             SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2785                 shadowTestCode += 
"if (i == " + std::to_string(i) + 
") { lightSpace = u_lightSpace_" + std::to_string(i) + 
"}\n";
 
 2787         shadowTestCode += R
"( 
 2793         shadowTestCode += R
"( 
 2794         if (u_lightUsesCubemap[i]) 
 2797         for (
SLuint i = 0; i < lights->size(); ++i)
 
 2799             SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2801                 shadowTestCode += 
"            if (i == " + std::to_string(i) + 
") lightSpace = u_lightSpace_" + std::to_string(i) + 
"[vectorToFace(lightToFragment)];\n";
 
 2803         shadowTestCode += R
"( 
 2808         for (
SLuint i = 0; i < lights->size(); ++i)
 
 2810             SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2812                 shadowTestCode += 
"            if (i == " + std::to_string(i) + 
") lightSpace = u_lightSpace_" + std::to_string(i) + 
";\n";
 
 2814         shadowTestCode += R
"( 
 2819     shadowTestCode += R"( 
 2820         vec4 lightSpacePosition = lightSpace * vec4(v_P_WS, 1.0); 
 2822         // Normalize lightSpacePosition 
 2823         vec3 projCoords = lightSpacePosition.xyz / lightSpacePosition.w; 
 2825         // Convert to texture coordinates 
 2826         projCoords = projCoords * 0.5 + 0.5; 
 2828         float currentDepth = projCoords.z; 
 2830         // Look up depth from shadow map 
 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]); 
 2837         // Use percentage-closer filtering (PCF) for softer shadows (if enabled) 
 2838         if (u_lightDoSmoothShadows[i]) 
 2840             int level = u_lightSmoothShadowLevel[i]; 
 2844     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2846         SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2848             shadowTestCode += 
"            if (i == " + to_string(i) + 
") { texelSize = 1.0 / vec2(textureSize(u_shadowMap_" + to_string(i) + 
", 0)); }\n";
 
 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";
 
 2855             shadowTestCode += 
"            }\n";
 
 2858     shadowTestCode += R
"( 
 2859             for (int x = -level; x <= level; ++x) 
 2861                 for (int y = -level; y <= level; ++y) 
 2864     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2866         SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2868             shadowTestCode += 
"                 if (i == " + to_string(i) + 
") { closestDepth = texture(u_shadowMap_" + to_string(i) + 
", projCoords.xy + vec2(x, y) * texelSize).r; }\n";
 
 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";
 
 2878     shadowTestCode += R
"( 
 2879                     shadow += currentDepth - bias > closestDepth ? 1.0 : 0.0; 
 2882             shadow /= pow(1.0 + 2.0 * float(level), 2.0); 
 2886             if (u_lightUsesCubemap[i]) 
 2889     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2891         SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2893             shadowTestCode += 
"                if (i == " + to_string(i) + 
") closestDepth = texture(u_shadowMapCube_" + to_string(i) + 
", lightToFragment).r;\n";
 
 2895     shadowTestCode += R
"( 
 2897             else if (u_lightNumCascades[i] > 0) 
 2900     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2902         SLLight*     light     = lights->at(i);
 
 2903         SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 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 += 
"                }";
 
 2913     shadowTestCode += R
"( 
 2919     for (
SLuint i = 0; i < lights->size(); ++i)
 
 2921         SLShadowMap* shadowMap = lights->at(i)->shadowMap();
 
 2923             shadowTestCode += 
"                if (i == " + to_string(i) + 
") closestDepth = texture(u_shadowMap_" + to_string(i) + 
", projCoords.xy).r;\n";
 
 2926     shadowTestCode += R
"( 
 2929             // The fragment is in shadow if the light doesn't "see" it 
 2930             if (currentDepth > closestDepth + bias) 
 2940     return shadowTestCode;
 
 2949 #if defined(DEBUG) && defined(_DEBUG) 
 2956 #ifndef SL_EMSCRIPTEN 
 2960         SL_EXIT_MSG(
"SLGLProgramGenerated::addCodeToShader: SLGLProgramManager::configPath not existing");
 
 2966             SL_EXIT_MSG(
"SLGLProgramGenerated::addCodeToShader: Failed to created SLGLProgramManager::configPath/generatedShaders");
 
 2977                                        const std::string& name,
 
 2978                                        const std::string& value)
 
 2980     std::string placeholder = 
"${" + 
name + 
"}";
 
 2982     std::string::size_type pos = 0;
 
 2983     while ((pos = code.find(placeholder)) != std::string::npos)
 
 2985         code.replace(pos, placeholder.size(), value);
 
 2986         pos += value.size();
 
 2994     string header = 
"\nprecision highp float;\n";
 
 2995     header += 
"\n#define NUM_LIGHTS " + to_string(numLights) + 
"\n";
 
 3004     string header = 
"\nprecision highp float;\n";
 
#define SL_EXIT_MSG(message)
 
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 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 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
 
vector< SLLight * > SLVLight
STL vector of light pointers.
 
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.
 
static string configPath
Contains the global writable configuration path.
 
Encapsulation of an OpenGL shader object.
 
void file(SLstring strFile)
 
static SLstring removeComments(SLstring src)
SLGLShader::removeComments for C/C++ comments removal from shader code.
 
Abstract Light class for OpenGL light sources.
 
virtual SLbool doCascadedShadows() const
 
void createsShadows(SLbool createsShadows)
 
void shadowMap(SLShadowMap *shadowMap)
 
Defines a standard CG material with textures and a shader program.
 
void ps(SLParticleSystem *ps)
 
SLstring texturesString()
Returns a unique string that represent all textures used.
 
void reflectionModel(SLReflectionModel rm)
 
void skybox(SLSkybox *sb)
 
SLbool hasTextureTypeWithUVIndex(SLTextureType tt, SLuint texIndex, SLbyte uvIndex)
 
SLbool hasTextureType(SLTextureType tt)
 
SLbool usesUVIndex(SLbyte uvIndex)
Returns true if the specified uvIndex is used by one of the textures.
 
void name(const SLstring &Name)
 
SLstring _name
name of an object
 
const SLstring & name() const
 
Class for standard and cascaded shadow mapping.
 
void numCascades(int numCascades)
 
SLbool useCascaded() const
 
SLGLVDepthBuffer depthBuffers()
 
void useCubemap(SLbool useCubemap)
 
bool dirExists(const string &path)
Returns true if a directory exists.
 
bool makeDir(const string &path)
Creates a directory with given path.