Original Post
I was trying to implement GLSL per-pixel fog in my game engine. However, there is a problem. When I enable linear or exp2 fog, the whole scene goes black, and when I implement exp fog, nothing happens to the scene.
Here is the fragment shader code:
[source lang="cpp"]
#define FOG_OFF 0
#define FOG_LINEAR 1
#define FOG_EXP 2
#define FOG_EXP2 3
/* clipping plane (used here) */
uniform float clip_near;
uniform float clip_far;
/* texture */
uniform sampler2D tex;
uniform int use_texture;
/* fog */
uniform int fog_type;
uniform float fog_start;
uniform float fog_end;
uniform float fog_density;
uniform float fog_red;
uniform float fog_green;
uniform float fog_blue;
void main()
{
vec4 texel = texture2D(tex, gl_TexCoord[0].st);
vec4 color = gl_Color;
if (use_texture == 1)
{
color *= texel;
};
float fog_factor = 1.0;
vec4 fog_color = vec4(fog_red, fog_green, fog_blue, 1.0);
float z = gl_FragCoord.z / gl_FragCoord.w;
//float z = 1.0 - (gl_FragCoord.z / gl_FragCoord.w) / clip_far;
if (fog_type == FOG_LINEAR)
{
fog_factor = (fog_end-z)/(fog_end-fog_start);
};
if (fog_type == FOG_EXP)
{
fog_factor = exp(-(fog_density - z));
};
if (fog_type == FOG_EXP2)
{
fog_factor = exp2((-(fog_density - z))*(-(fog_density - z)));
};
fog_factor = clamp(fog_factor, 0.0, 1.0);
float alpha;
alpha = color[3];
color = mix(fog_color, color, fog_factor);
color[3] = alpha;
gl_FragColor = color;
}
[/source]
Here is the C code for setting fog parameters (it also sets up the OpenGL pipeline fog, for complicated reasons that I don't need to mention):
[source lang="cpp"]
void meEnableLinearFog(double start, double end, double density, MEVECTOR color)
{
fog_on = 1;
glFogf(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, (float)start);
glFogf(GL_FOG_END, (float)end);
glFogf(GL_FOG_DENSITY, (float)density);
float col[4];
col[0] = color.x;
col[1] = color.y;
col[2] = color.z;
col[3] = 1.0;
glFogfv(GL_FOG_COLOR, &col[0]);
me_shader_variablef("fog_start", (float)start);
me_shader_variablef("fog_end", (float)end);
me_shader_variablef("fog_density", (float)density);
me_shader_variablef("fog_red", (float)color.x);
me_shader_variablef("fog_green", (float)color.y);
me_shader_variablef("fog_blue", (float)color.z);
};
void meEnableExpFog(double start, double end, double density, MEVECTOR color)
{
fog_on = 2;
glFogf(GL_FOG_MODE, GL_EXP);
glFogf(GL_FOG_START, (float)start);
glFogf(GL_FOG_END, (float)end);
glFogf(GL_FOG_DENSITY, (float)density);
float col[4];
col[0] = color.x;
col[1] = color.y;
col[2] = color.z;
col[3] = 1.0;
glFogfv(GL_FOG_COLOR, &col[0]);
me_shader_variablef("fog_start", (float)start);
me_shader_variablef("fog_end", (float)end);
me_shader_variablef("fog_density", (float)density);
me_shader_variablef("fog_red", (float)color.x);
me_shader_variablef("fog_green", (float)color.y);
me_shader_variablef("fog_blue", (float)color.z);
};
void meEnableSquareFog(double start, double end, double density, MEVECTOR color)
{
fog_on = 3;
glFogf(GL_FOG_MODE, GL_EXP2);
glFogf(GL_FOG_START, (float)start);
glFogf(GL_FOG_END, (float)end);
glFogf(GL_FOG_DENSITY, (float)density);
float col[4];
col[0] = color.x;
col[1] = color.y;
col[2] = color.z;
col[3] = 1.0;
glFogfv(GL_FOG_COLOR, &col[0]);
me_shader_variablef("fog_start", (float)start);
me_shader_variablef("fog_end", (float)end);
me_shader_variablef("fog_density", (float)density);
me_shader_variablef("fog_red", (float)color.x);
me_shader_variablef("fog_green", (float)color.y);
me_shader_variablef("fog_blue", (float)color.z);
};
[/source]
The shader variable functions are as follows:
[source lang="cpp"]
void me_shader_variablei(const char *name, int value)
{
int location;
#ifdef ARB_SHADER
location = glGetUniformLocationARB(me_shader_program, name);
glUniform1iARB(location, value);
#else
location = glGetUniformLocation(me_shader_program, name);
glUniform1i(location, value);
#endif
};
void me_shader_variabled(const char *name, double value)
{
int location;
#ifdef ARB_SHADER
location = glGetUniformLocationARB(me_shader_program, name);
glUniform1dARB(location, value);
#else
location = glGetUniformLocation(me_shader_program, name);
glUniform1d(location, value);
#endif
};
void me_shader_variablef(const char *name, float value)
{
int location;
#ifdef ARB_SHADER
location = glGetUniformLocationARB(me_shader_program, name);
glUniform1fARB(location, value);
#else
location = glGetUniformLocation(me_shader_program, name);
glUniform1f(location, value);
#endif
};
[/source]
The code is compiled without the ARB_SHADER macro, so it uses the standard functions.
I'm sorry for posting so much code, but I really don't know where to start looking for the problem. I am very new to shaders.
Does anyone know what could be wrong? Thanks.
EDIT: Just fixed the equation error, I updated the code. Now when I enable the exp fog the whole scene turns black again.
Here is the fragment shader code:
[source lang="cpp"]
#define FOG_OFF 0
#define FOG_LINEAR 1
#define FOG_EXP 2
#define FOG_EXP2 3
/* clipping plane (used here) */
uniform float clip_near;
uniform float clip_far;
/* texture */
uniform sampler2D tex;
uniform int use_texture;
/* fog */
uniform int fog_type;
uniform float fog_start;
uniform float fog_end;
uniform float fog_density;
uniform float fog_red;
uniform float fog_green;
uniform float fog_blue;
void main()
{
vec4 texel = texture2D(tex, gl_TexCoord[0].st);
vec4 color = gl_Color;
if (use_texture == 1)
{
color *= texel;
};
float fog_factor = 1.0;
vec4 fog_color = vec4(fog_red, fog_green, fog_blue, 1.0);
float z = gl_FragCoord.z / gl_FragCoord.w;
//float z = 1.0 - (gl_FragCoord.z / gl_FragCoord.w) / clip_far;
if (fog_type == FOG_LINEAR)
{
fog_factor = (fog_end-z)/(fog_end-fog_start);
};
if (fog_type == FOG_EXP)
{
fog_factor = exp(-(fog_density - z));
};
if (fog_type == FOG_EXP2)
{
fog_factor = exp2((-(fog_density - z))*(-(fog_density - z)));
};
fog_factor = clamp(fog_factor, 0.0, 1.0);
float alpha;
alpha = color[3];
color = mix(fog_color, color, fog_factor);
color[3] = alpha;
gl_FragColor = color;
}
[/source]
Here is the C code for setting fog parameters (it also sets up the OpenGL pipeline fog, for complicated reasons that I don't need to mention):
[source lang="cpp"]
void meEnableLinearFog(double start, double end, double density, MEVECTOR color)
{
fog_on = 1;
glFogf(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, (float)start);
glFogf(GL_FOG_END, (float)end);
glFogf(GL_FOG_DENSITY, (float)density);
float col[4];
col[0] = color.x;
col[1] = color.y;
col[2] = color.z;
col[3] = 1.0;
glFogfv(GL_FOG_COLOR, &col[0]);
me_shader_variablef("fog_start", (float)start);
me_shader_variablef("fog_end", (float)end);
me_shader_variablef("fog_density", (float)density);
me_shader_variablef("fog_red", (float)color.x);
me_shader_variablef("fog_green", (float)color.y);
me_shader_variablef("fog_blue", (float)color.z);
};
void meEnableExpFog(double start, double end, double density, MEVECTOR color)
{
fog_on = 2;
glFogf(GL_FOG_MODE, GL_EXP);
glFogf(GL_FOG_START, (float)start);
glFogf(GL_FOG_END, (float)end);
glFogf(GL_FOG_DENSITY, (float)density);
float col[4];
col[0] = color.x;
col[1] = color.y;
col[2] = color.z;
col[3] = 1.0;
glFogfv(GL_FOG_COLOR, &col[0]);
me_shader_variablef("fog_start", (float)start);
me_shader_variablef("fog_end", (float)end);
me_shader_variablef("fog_density", (float)density);
me_shader_variablef("fog_red", (float)color.x);
me_shader_variablef("fog_green", (float)color.y);
me_shader_variablef("fog_blue", (float)color.z);
};
void meEnableSquareFog(double start, double end, double density, MEVECTOR color)
{
fog_on = 3;
glFogf(GL_FOG_MODE, GL_EXP2);
glFogf(GL_FOG_START, (float)start);
glFogf(GL_FOG_END, (float)end);
glFogf(GL_FOG_DENSITY, (float)density);
float col[4];
col[0] = color.x;
col[1] = color.y;
col[2] = color.z;
col[3] = 1.0;
glFogfv(GL_FOG_COLOR, &col[0]);
me_shader_variablef("fog_start", (float)start);
me_shader_variablef("fog_end", (float)end);
me_shader_variablef("fog_density", (float)density);
me_shader_variablef("fog_red", (float)color.x);
me_shader_variablef("fog_green", (float)color.y);
me_shader_variablef("fog_blue", (float)color.z);
};
[/source]
The shader variable functions are as follows:
[source lang="cpp"]
void me_shader_variablei(const char *name, int value)
{
int location;
#ifdef ARB_SHADER
location = glGetUniformLocationARB(me_shader_program, name);
glUniform1iARB(location, value);
#else
location = glGetUniformLocation(me_shader_program, name);
glUniform1i(location, value);
#endif
};
void me_shader_variabled(const char *name, double value)
{
int location;
#ifdef ARB_SHADER
location = glGetUniformLocationARB(me_shader_program, name);
glUniform1dARB(location, value);
#else
location = glGetUniformLocation(me_shader_program, name);
glUniform1d(location, value);
#endif
};
void me_shader_variablef(const char *name, float value)
{
int location;
#ifdef ARB_SHADER
location = glGetUniformLocationARB(me_shader_program, name);
glUniform1fARB(location, value);
#else
location = glGetUniformLocation(me_shader_program, name);
glUniform1f(location, value);
#endif
};
[/source]
The code is compiled without the ARB_SHADER macro, so it uses the standard functions.
I'm sorry for posting so much code, but I really don't know where to start looking for the problem. I am very new to shaders.
Does anyone know what could be wrong? Thanks.
EDIT: Just fixed the equation error, I updated the code. Now when I enable the exp fog the whole scene turns black again.