Sign in to follow this  
Arith

[solved] GLSL Fog

Recommended Posts

Arith    122
So, I'm writing a random terrain generator and I'm at the stage where I'm playing around with shaders. I've been trying for over a week to get fog to coexist with my lighting shader with very little to show for it. I've read leagues upon leagues of sites on the subject, including a few on this wonderful site to no avail. I've even found an excerpt from the orange book.. alas nothing. I'm very new to GLSL, and it's clear I need some individualized help. The shaders below amount to this; http://i138.photobucket.com/albums/q257/Serojin/mountains1.jpg Vertex Shader
varying vec3 lightDir,normal;
void main()
{
	normal = normalize(gl_NormalMatrix * gl_Normal);
	lightDir = normalize(vec3(gl_LightSource[0].position));
	gl_TexCoord[0] = gl_MultiTexCoord0;
	gl_Position = ftransform();
}


Fragment Shader
varying vec3 lightDir,normal;
uniform sampler2D tex;
void main()
{
	vec3 ct,cf;
	vec4 texel;
	vec3 color;
	float intensity,at,af;
	intensity = max(dot(lightDir,normalize(normal)),0.0);
	color = vec3(intensity/0.7,intensity/0.7,intensity/0.7);
	cf = intensity * (gl_FrontMaterial.diffuse).rgb; 
	af = gl_FrontMaterial.diffuse.a;
	texel = texture2D(tex, gl_TexCoord[0].st);
	ct = texel.rgb * color;
	at = texel.a;
	gl_FragColor = vec4(ct * cf, at * af);	
}


I've taken out everything having to do with fog in those shaders just to have a clean slate so to speak. All the sources I've come across gives me a good idea of the theory behind what to do, I just can't seem to get the actual implementation down. At this point in the project I'm only dealing with one texture and one light. Though, as a side question, if anyone has a really clear cut tutorial on multitexturing with glsl I'd love to see it. If anyone can help me out it would be greatly appreciated. [Edited by - Arith on March 20, 2010 4:21:21 PM]

Share this post


Link to post
Share on other sites
V-man    813
I use my own lighting (phong lighting and shading) and for fog, I do linear fog.
This is for 1 point light.


[VERTEX SHADER]

#version 110

//UNIFORM
uniform mat4 ProjectionModelviewMatrix;
uniform vec4 TexMatrix0_a;
uniform vec4 TexMatrix0_b;
uniform vec4 LightPosition0;
uniform mat4 ModelviewMatrix;

//VARYING
varying vec2 TexCoord0;
varying vec4 LightVector0; //xyz is lightvector and w is light distance from vertex
varying vec3 HalfVector0;
varying vec4 EyeNormal; //w is also FragmentDistance that we use in the fs


//GLOBALFUNCTION


void main()
{
vec3 eyeVertex;
vec3 lightVector, eyeVector;
float mysqrtdistance;


gl_Position = ProjectionModelviewMatrix * gl_Vertex;
TexCoord0.x = dot(TexMatrix0_a, gl_MultiTexCoord0);
TexCoord0.y = dot(TexMatrix0_b, gl_MultiTexCoord0);

eyeVertex = vec3(ModelviewMatrix * gl_Vertex);
EyeNormal.w = length(eyeVertex);
eyeVector = normalize(-eyeVertex);
lightVector = normalize(LightPosition0.xyz - eyeVertex);
LightVector0.xyz = lightVector;
mysqrtdistance = sqrt(distance(LightPosition0.xyz, eyeVertex));
LightVector0.w = mysqrtdistance * sqrt(mysqrtdistance);
HalfVector0 = lightVector + eyeVector; //No need to normalize the sum

EyeNormal.xyz = vec3(ModelviewMatrix * vec4(gl_Normal, 0.0));
}



[FRAGMENT SHADER]

#version 110

//UNIFORM
uniform sampler2D Texture0;
uniform vec4 AllLightAmbient_MaterialAmbient;
uniform vec4 LightMaterialDiffuse0;
uniform vec4 LightMaterialSpecular0;
uniform float MaterialShininess;
uniform float Light0LinearAttenuation0;
uniform vec4 FogColor; //FogColor. If w is 1.0, it means we don't want fogging. If 0.0, we want fogging enabled.
uniform float FogDensity; //FogDensity


//VARYING
varying vec2 TexCoord0;
varying vec4 LightVector0; //xyz is lightvector and w is light distance from vertex
varying vec3 HalfVector0;
varying vec4 EyeNormal; //w is also FragmentDistance that we use in the fs


//GLOBALFUNCTION

//eyeNormal must be normalized already
//lightVector must be normalized already. xyz is lightvector and w is light distance from vertex
//halfVector must be normalized already
//
//output diffuse color and output specular color
//Then do diffuse * texture_color + specular
//diffuse.a = material_diffuse.a
void ComputePointLight(out vec4 diffuseColor, out vec4 specularColor, in vec3 eyeNormal, in vec4 lightVector, in vec3 halfVector, in vec4 lightMaterialDiffuse, in vec4 lightMaterialSpecular, in float light0LinearAttenuation0)
{
float dotProduct;
float atten;

atten = 1.0 / (light0LinearAttenuation0 * lightVector.w);

dotProduct = clamp(dot(eyeNormal, lightVector.xyz), 0.0, 1.0);
diffuseColor = dotProduct * lightMaterialDiffuse * atten;

specularColor = vec4(0.0);
dotProduct = clamp(dot(eyeNormal, halfVector), 0.0, 1.0);
if(dotProduct>0.0)
specularColor = pow(dotProduct, MaterialShininess) * lightMaterialSpecular * atten;
}

void main()
{
vec4 texel, diffuseColor, specularColor;
vec4 ColorSum;
vec3 eyeNormal, halfVector;
vec4 lightVector;
float fogFactor;

texel = texture2D(Texture0, TexCoord0);

eyeNormal = normalize(EyeNormal.xyz);
lightVector.xyz = normalize(LightVector0.xyz);
lightVector.w = LightVector0.w;
halfVector = normalize(HalfVector0);


ComputePointLight(diffuseColor, specularColor, eyeNormal, lightVector, halfVector, LightMaterialDiffuse0, LightMaterialSpecular0, Light0LinearAttenuation0);
ColorSum = (AllLightAmbient_MaterialAmbient + diffuseColor) * texel + specularColor;

fogFactor = max(FogColor.a, exp(-(FogDensity * EyeNormal.w)));
ColorSum = mix(FogColor, ColorSum, fogFactor);

ColorSum.a = texel.a * LightMaterialDiffuse0.a;

gl_FragColor = clamp(ColorSum, 0.0, 1.0);
}

Share this post


Link to post
Share on other sites
Arith    122
Alright, so I achieved what I wanted. A friend, Zhasha showed me a good way to do what I was ultimately trying to do (which was blend that hard edge at the vanishing point -- see the first picture I posted) So, thanks to his help here is the result (the camera is elevated to show more of the blending)
http://i138.photobucket.com/albums/q257/Serojin/fog.jpg

And here are the new shaders. I realize they aren't gold, indeed I'm still learning and playing around with things. It does what I want;

Vertex Shader

varying vec3 lightDir,normal;
varying vec4 pt;

void main()
{
normal = normalize(gl_NormalMatrix * gl_Normal);
lightDir = normalize(vec3(gl_LightSource[0].position));
gl_TexCoord[0] = gl_MultiTexCoord0;
pt = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = pt;
gl_FrontColor = gl_Color;
}



Fragment Shader

varying vec3 lightDir,normal;
uniform sampler2D tex;

const float far = 5000.0;
const float margin = far - (far/2.0);
varying vec4 pt;

void main()
{


vec3 ct,cf;
vec4 texel;
vec3 color;
float intensity,at,af;

float alpha = 1.0;
if (pt.z > margin) alpha = 1.0 - ((pt.z-margin)/(far-margin));



float bright = 0.35;
intensity = max(dot(lightDir,normalize(normal)),0.0);
color = vec3(intensity/bright,intensity/bright,intensity/bright);
cf = intensity * (gl_FrontMaterial.diffuse).rgb;
af = gl_FrontMaterial.diffuse.a;
texel = texture2D(tex, gl_TexCoord[0].st);
ct = texel.rgb * color;
at = texel.a;
gl_FragColor = vec4(ct * cf, at * af) * alpha;
}



Thanks V-Man for your input, unfortunately it was a bit over my head. Still learning the basics of GLSL while playing with working code -- fun times. Thanks again

Arith

Share this post


Link to post
Share on other sites
V-man    813
It's pretty simple for fog alone. It is these 2 lines that do the job in the FS
fogFactor = max(FogColor.a, exp(-(FogDensity * EyeNormal.w)));
ColorSum = mix(FogColor, ColorSum, fogFactor);

plus 1 or 2 lines in the VS.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this