1
\$\begingroup\$

I am using the GLSL shader from this link, slightly modified and i got it working. The shader code is the following:

VS:

  vPosition = uMVMatrix * vec4(aVertexPosition, 1.0);        
  vTransformedNormal = uNMatrix * aVertexNormal;              
  gl_Position = uPMatrix * vPosition;                         

FS:

  float minLight = 0.01f;      
  float radius = sqrt(1.0 / (uAttenuationFactor * minLight));   
  float lightAdd = 0.0f;       
  float dist = distance(vPosition.xyz, (uMat4Identity * vec4(uLightPosition, 1.0)).xyz);  
  float att = clamp(1.0 - dist/radius, 0.0, 1.0);    
  vec3 surf2light = normalize((uMat4Identity * vec4(uLightPosition, 1.0)).xyz - vPosition.xyz);   
  vec3 norm = normalize(vTransformedNormal);     
  float diffuseCoefficient = max(0.0, dot(norm, surf2light));   
  lightAdd += att * (diffuseCoefficient + uSourceIntensity);    
  vec4 textureColor = texture2D(uTex0, vec2(vTextureCoord.s, vTextureCoord.t));  
  vec3 torch_output = lightAdd * uColorLight;     
  vec4 final_color = (vec4(torch_output, 1.0f) * textureColor) * vVertexColor;   
  gl_FragColor = final_color;  

The shader computes point lighting with attenuation and give very satisfactory results. Look at the pic:

point lighting

I give uAttenuationFactor = 0.4f and uSourceIntensity = 0.2f to get this result and it satisfies me. However, besides setting the light color, how i could modify the shader to fade-out to another color than black?? Anything i tried it just modifies the visible parts of the screen i.e. walls but the black remains unchanged. I would had liked to be able to set a grey color for rain or whitish for fog effect etc.

Thanx.

\$\endgroup\$
  • 1
    \$\begingroup\$ You could try applying a simple "fog" method. You could achieve that by simply using the depth buffer and coloring based on each depth value.. \$\endgroup\$ – Sidar Mar 1 '18 at 6:50
  • 1
    \$\begingroup\$ That is the normal way of handling transparent objects. Do opaque objects first, disable depth write then render from back to front. Otherwise see if you can discard the fragment based on alpha instead. \$\endgroup\$ – Sidar Mar 1 '18 at 10:08
  • 1
    \$\begingroup\$ Btw you could fake sprite fog by just taking the "real" distance from the cam and apply some sort of post processing. But I can't infringe on your setup =P \$\endgroup\$ – Sidar Mar 1 '18 at 13:05
  • 1
    \$\begingroup\$ I once made a fake fade effect by simply having quads move with the camera at a distance. The quad texture was a gradient from opaque to transparent ( bottom to top ). The quad was at a slight angle to create fake depth, duplicate the quad and place it a bit further from the original but a bit higher. See here \$\endgroup\$ – Sidar Mar 1 '18 at 15:28
  • 1
    \$\begingroup\$ Made the concept in Unity The gradient is a bit sloppy ( just grabbed the first one i found on google) I think if you're creative with the textures and perhaps add some post processing you could get a cool effect. \$\endgroup\$ – Sidar Mar 1 '18 at 15:50
1
\$\begingroup\$

After a number of hours, i finally found some shader way to mix both lighting and fog:

VS:

...
// fog                                 
uniform LOWP float uFogDistance;       
varying float vFogClampedDistance;    
void main() {
   ...
   // fog                          
   if (uFogDistance >= 0.0) {                                        
      vFogClampedDistance = clamp(gl_Position.z, 0.0, uFogDistance); 
   }                                                              
}

FS:

...
// fog                                 
uniform LOWP float uFogDistance;       
varying float vFogClampedDistance;    
void main() {
   ...
   // compute final_color by 'lighting'
   ...
   Vec4 textureColor = texture2D(uTex0, vec2(vTextureCoord.s, vTextureCoord.t));                
   if (uFogDistance == 0.0) {                                                                   
      gl_FragColor = ...use only lighting, not fog
   }                               
   else {                          
      gl_FragColor = mix(final_color, vec4(0.5,0.5,0.5,1.0), vFogClampedDistance/uFogDistance) * vec4(1.0,1.0,1.0,textureColor.a);   
   }                               

}

I am now able to both use the lighting shader wth attenuation, plus with a very simple fog effect which works on the lighting colors. Of course where both are mixing i have to be careful not to wash the graphics out: Take a look in pics:

enter image description here enter image description here

Even if i disable the lighting and use only black fog to simulate the lighting, the results resembles somehow those of lighting; while not perfect, they are blending nicely:

enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ Pretty neat and simple solution. Btw you can get rid of the if statement simply by applying one of these : theorangeduck.com/page/avoiding-shader-conditionals. Not sure how more optimized it would be but you're fine eitherway \$\endgroup\$ – Sidar Mar 2 '18 at 8:57
  • \$\begingroup\$ Thanx! Yes i know, i am using an uber shader which handles texturing, 2 types of lighting and now fog and i will certainly look for ways to avoid conditions, i will read the link, thanx =) I already optimized the fragment shader by removing the radius and the killer square root computation and instead moved it into a nice uniform. Frame rate is still 60ish even on my poor celeron laptop =) Having 2d sprites with autorotation helps a lot ;) \$\endgroup\$ – user6096479 Mar 2 '18 at 13:11
  • \$\begingroup\$ I want to clarify that I don't know how much actually gets optimized ( or not at all) but it's good to know those solutions exist. Btw you could check distance just by using the squares of your values. Unless you need the actual length then square root is probably what you need. \$\endgroup\$ – Sidar Mar 2 '18 at 13:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.