3D Using Shaders disables 3D Fog

Jase217

Member
I'm hoping this is only a simple thing to fix, In my 3D game I use the default GPU Fog to obscure things in the distance, I also use a shader to tint sections of rooms in my game with a certain colour to make it lighter or darker.

However if I use a shader on anything including just a normal passthrough shader, it will ignore the fog on whatever I use it on, leaving it fully visible in the distance. I'm guessing this is because the default shader doesn't take the fog into account? I'm still new to shaders so I'm not sure.

Is this something that can be fixed easily?
Here is the code for the shader I use to tint models.

Vertex:
Code:
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position;                  // (x,y,z)
//attribute vec3 in_Normal;                  // (x,y,z)     unused in this shader.
attribute vec4 in_Colour;                    // (r,g,b,a)
attribute vec2 in_TextureCoord;              // (u,v)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
    
    v_vColour = in_Colour;
    v_vTexcoord = in_TextureCoord;
}
Fragment:
Code:
//
// mask fragment shader
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec4 f_ChannelMask;
void main()
{
    gl_FragColor = (v_vColour * texture2D( gm_BaseTexture, v_vTexcoord )) * f_ChannelMask;
}
Is there anybody here with experience in shaders that knows how to make it take the standard fog into account?
 

GMWolf

aka fel666
If all your shader does is make things lighter or darker, why not just use the vertex colour for that, no custom shader needed.
 

Jase217

Member
I did that before, but once I create a vertex buffer once I would have to create it again to change the colours of the vertices, unless there's another way?
I want to be able to change the colour in real time during the game for lighting effects which is why I went with the shader.
 
M

Multimagyar

Guest
as far as I recall both in GMS1.4 and GMS2.1, the 3d fog only works on default shader, because it's coded into the default shader. You don't even need to data mine much in GMS1.4 to find the relevant shader it's just Game Maker studio folder in roaming and then shader and vshadercommon and fshadercommon has these answers for you how "game maker" calculates the light and the fog for you. But because of the custom shader GMS does not calculate the fog for you instead you either use the default or make the calculation yourself. Which is not hard. I'm not even sure if the GPU has a default instruction to calculate fog. Probably not.
 

Yal

GMC Memer
GMC Elder
as far as I recall both in GMS1.4 and GMS2.1, the 3d fog only works on default shader, because it's coded into the default shader. You don't even need to data mine much in GMS1.4 to find the relevant shader it's just Game Maker studio folder in roaming and then shader and vshadercommon and fshadercommon has these answers for you how "game maker" calculates the light and the fog for you. But because of the custom shader GMS does not calculate the fog for you instead you either use the default or make the calculation yourself. Which is not hard. I'm not even sure if the GPU has a default instruction to calculate fog. Probably not.
To elaborate on this a bit, the default shaders are in AppData/Roaming/<game maker version>/Shaders. This data is appended before any shader code of the same type you write, so all the functions and constants in the default shaders can be used in your custom shaders as well if you want. (Though it's probably safer to copypaste it and rename the functions since this is undocumented behavior and they're not exposed by the IDE, while the matrices and constants they use are documented in the manual). And obviously you should never edit these files directly or bad stuff will happen.

(This is also why you can't use the #version directive in GM's shaders - the first line isn't actually the first line of the shader code that's passed to the shader compiler)

The code (and which gm constants are available) is split a bit between vertex and frag shaders, if you just want to add fog the easiest is to compute the fog factor in the vertex shader and pass it as a varying float to the frag shader, then have the frag shader mix() the normal final output color with the gm_FogColor with the fog factor's value as the mixing factor... but only when pixel fog is enabled (gm_PS_FogEnabled is true). As I understand it, the number of vertex shader iterations doesn't need to match the number of fragment shader iterations (1 vertex shader run per vertex, 1 frag shader run per pixel, but usually each vertex has more than one pixel) and this is why you need to do the position computation separately from the pixel-color computation.

I'm aware I'm bumping a 3-year-old thread, I just figured I should clear things up a bit after being stuck on getting a shader to work with 3D fog and getting a nudge in the right direction by this reply - doesn't seem like there's a lot of answers floating around on using 3D shaders with GM and this is the #1 google hit on the topic.
 
Top