Advertisement

Question about fog based on height

Started by February 20, 2016 08:12 PM
3 comments, last by lumx 8 years, 10 months ago

I am reading Inigo Quilez http://iquilezles.org/www/articles/fog/fog.htm about fog and I just cant understand few things when he talks about fog based on height.

He has a shader function there but I have problems understanding how to make it work and add that additional fog.

He uses this function to apply fog


vec3 applyFog( in vec3  rgb,       // original color of the pixel
               in float distance ) // camera to point distance
{
    float fogAmount = 1.0 - exp( -distance*b );
    vec3  fogColor  = vec3(0.5,0.6,0.7);
    return mix( rgb, fogColor, fogAmount );
}

then he has the other one based on height


vec3 applyFog( in vec3  rgb,      // original color of the pixel
               in float distance, // camera to point distance
               in vec3  rayOri,   // camera position
               in vec3  rayDir )  // camera to point vector
{
    float fogAmount = c * exp(-rayOri.y*b) * (1.0-exp( -distance*rayDir.y*b ))/rayDir.y;
    vec3  fogColor  = vec3(0.5,0.6,0.7);
    return mix( rgb, fogColor, fogAmount );
}

My questions is do i add them because so far i just cant make it work with my shader


#version 400 core
 
in vec3 Position;
in vec3 Normal;
//in vec4 positionToCamera;
//in float visibility;
 
uniform vec3 color;
uniform vec3 CameraPosition;
uniform float near;
uniform float far;
 
uniform vec3 fogColor;
uniform bool enableBlending;
 
uniform float c;
uniform float b;
 
uniform int fogType;
 
vec3 applyFogDepth( vec3  rgb,	// original color of the pixel
	 float distance,			// camera to point distance
	 vec3  rayOri,				// camera position
	 vec3  rayDir)				// camera to point vector
{
	//float cc = 1.0;
	//float bb = 1.1;
	float fogAmount = c * exp(-rayOri.y*b) * (1.0 - exp(-distance*rayDir.y*b)) / rayDir.y;
	return mix(rgb,  fogColor,  fogAmount );
}
 
// Fog with Sun factor
vec3 applyFogSun( vec3  rgb,// original color of the pixel
	 float distance,		// camera to point distance
	 vec3  rayDir,			// camera to point vector
	 vec3  sunDir)			// sun light direction
{
	float fogAmount = 1.0 - exp(-distance*b);
	float sunAmount = max(dot(rayDir, sunDir), 0.0);
 
	vec3 fog = mix(fogColor, // bluish
		vec3(1.0, 0.9, 0.7), // yellowish
		pow(sunAmount, 8.0));
 
	return mix(rgb, fog, fogAmount);
}
 
//Exponential fog
vec3 applyFog( vec3  rgb, // original color of the pixel
		 float distance)  // camera to point distance
{
	float fogAmount = 1.0 - exp(-distance*b);
	return mix(rgb, fogColor, fogAmount);
}
 
float LinearizeDepth(float depth)
{
	float z = depth * 2.0 - 1.0; // Back to NDC 
	return (2.0 * near * far) / (far + near - z * (far - near));
}
 
out vec4 gl_FragColor;
void main(void) {
 
	vec3 fog = vec3(0.0);
	//-5.0f, 900.0f, 400.0f camera coord
	vec3 lightPosition = vec3(0.0, 1200.0, -6000.0);
	vec3 lightDirection = normalize(lightPosition - Position);
	vec3 direction = normalize(CameraPosition - Position);
 
	float depth = LinearizeDepth(gl_FragCoord.z) / far;
	switch (fogType) {
		case 0:
			fog = applyFog(color, depth);
			break;
		case 1:
			fog = applyFogSun(color, depth, direction, lightDirection);
			break;
		case 2:
			//fog = mix(applyFog(color, depth), applyFogDepth(color, depth, CameraPosition, CameraPosition - Position), 0.5)   ;
			fog = applyFogDepth(color, depth, CameraPosition, CameraPosition - Position);
			break;
	}
 
	//calculate light
	float diff = max(dot(Normal, lightDirection), 0.0);
	vec3 diffuse = diff * color;
 
	float fogAmount = 1.0 - exp(-depth*b);
 
	vec3 finalColor = vec3(0.0);
	if (enableBlending)
		finalColor = mix(diffuse, fog, fogAmount);
	else
		finalColor = fog;
 
	gl_FragColor = vec4(finalColor,1.0);
	//gl_FragColor = vec4(vec3(LinearizeDepth(visibility) / far), 1.0f);
}

For something visual, it helps if a bit more description is supplied. Perhaps also pictures?

Advertisement

You just need one or the other of those functions. But the real issue is that you are calculating and applying fogAmount twice (once inside the fog function, and once in the main function).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

If there is another way to create shader that has more fog at lower parts in mainlans like UE Exponential Height Fog i would be happy to read about it.

So far it has been 3 days that I am trying to fix and figure out how does non constant fog works, and I just cant see a solution so far.

I am sorry for some reason Firefox cashed my page and I thought there was no reply to my post.

Yes, I took fog density out to mix defuse light and fog. There is no other way I know now to do that better. The idea was to calculate fog density, then light from a directional light and at the end just mix those 2 with fog amount. So far it looks good.

The problem is that "applyFogDepth" function does not work. Its fog density function is always 0. Now I dont know if i did something wrong or I am missing something small from the article.

I have changed a bit the shader, now i calculate the fog amount outside of function and I use distance from camera for depth and not Z-buffer. Here it how it looks now.

My camera system is set to X is right, Y is up and Z- is forward


#version 400 core

in vec3 Position;
in vec3 Normal;
in vec4 viewSpace;
 

uniform vec3 color;
uniform vec3 CameraPosition;
uniform float near;
uniform float far;

uniform vec3 fogColor;
uniform bool enableBlending;

uniform float c;
uniform float b;

uniform int fogType;

vec3 applyFogDepth( vec3  rgb,	// original color of the pixel
	 float distance,			// camera to point distance
	 vec3  rayOri,				// camera position
	 vec3  rayDir)				// camera to point vector
{
	float fogAmount = c * exp(-rayOri.y*b) * (1.0 - exp(-distance*rayDir.y*b)) / rayDir.y;
	return mix(rgb,  fogColor,  fogAmount );
}

// Fog with Sun factor
vec3 applyFogSun( vec3  rgb,// original color of the pixel
	 float ammount,		// camera to point distance
	 vec3  rayDir,			// camera to point vector
	 vec3  sunDir)			// sun light direction
{
	float sunAmount = max(dot(rayDir, sunDir), 0.0);
	//these values are from Jeremy Birn's book "Digital Lighting & Rendering"
	vec3 sunColor = vec3(0.75, 0.746, 0.675); // sun at noon
	//vec3 sunColor = vec3(1.0, 0.9, 0.7); // yellow sun
	//vec3 sunColor = vec3(0.71, 0.49, 0.35); // sunrise sunset
	vec3 fog = mix(fogColor, // bluish
		sunColor, // yellowish
		pow(sunAmount, 8.0));
	
	return mix(rgb, fog, ammount);
}

//Exponential fog
vec3 applyFog( vec3  rgb, // original color of the pixel
		 float ammount)  // camera to point distance
{
	return mix(rgb, fogColor, ammount);
}

float LinearizeDepth(float depth)
{
	float z = depth * 2.0 - 1.0; // Back to NDC 
	return (2.0 * near * far) / (far + near - z * (far - near));
}

out vec4 gl_FragColor;
void main(void) {

	vec3 fog = vec3(0.0);
	//-5.0f, 900.0f, 400.0f camera coord
	vec3 lightPosition = vec3(0.0, 1200.0, -6000.0);
	//vec3 lightDirection = normalize(lightPosition - Position);
	vec3 direction = normalize(CameraPosition - Position);
	//float depth = abs(viewSpace.z) / far;

	float depth = length(viewSpace) / far;
	//float depth = LinearizeDepth(gl_FragCoord.z) / far;
	float fogAmount = 1.0 - exp(-depth*b);
	switch (fogType) {
		case 0:
			fog = applyFog(color, fogAmount);
			break;
		case 1:
			fog = applyFogSun(color, fogAmount, direction, normalize(lightPosition));
			break;
		case 2:
			//fog = mix(applyFog(color, depth), applyFogDepth(color, depth, CameraPosition, CameraPosition - Position), 0.5)   ;
			fog = (applyFog(color, fogAmount) + applyFogDepth(color, depth, CameraPosition, CameraPosition - Position)) / 2.0;
			break;
	}
	
	//calculate light
	float diff = max(dot(Normal, normalize(lightPosition)), 0.0);
	vec3 diffuse = diff * color;
	
	vec3 finalColor = vec3(0.0);
	if (enableBlending)
		finalColor = mix(diffuse, fog, fogAmount) ;
	else
		finalColor = fog;

	//float tt = t(color, 1.0 - (length(CameraPosition - Position) / far), CameraPosition, CameraPosition - Position);
	//vec4 testColor = vec4(vec3(depth ), 1.0);

	//gl_FragColor = testColor;
	gl_FragColor = vec4(finalColor,1.0);
}

Results look like this 

This is the first funciton
[attachment=30758:qst function.JPG]

This is the second function with sun factor added

[attachment=30755:2nd.JPG]

this is the third function. You can see that there is no fog applied to it.

[attachment=30756:3rd.JPG]

and this is again the third function but now with directional light.

[attachment=30757:4rth.JPG]

I am using a low ply mesh to avoid long reading times of OBJ file

This topic is closed to new replies.

Advertisement