When implementing fog in webgl, the key point is how to calculate the distance from the object to the eye/camera. It depends on whether you want precise or approximate value for it.
Precise value
It is just the distance between 2 points(one is camera) in 3D space. We have several ways to express it:
Both the camera and object are in
world coordinate system
1
2
3
4
5
6
7
8
9// vertex shader
attribute vec4 a_position;
uniform mat4 u_modelMatrix; // model matrix for object
uniform vec4 u_cameraWorldPos; // camera pos in WC
vary float v_dist;
void main() {
gl_Position = u_mvpMatrix * a_position;
v_dist = distance(u_modelMatrix * a_position, u_cameraWorldPos);
}The object is in
view coordinate system
whose origin is the camera1
2
3
4
5
6
7
8
9
10
11// vertex shader
attribute vec4 a_position;
uniform mat4 u_modelMatrix; // model matrix for object
uniform mat4 u_viewMatrix; // view matrix for object
vary float v_dist;
void main() {
gl_Position = u_mvpMatrix * a_position;
vec4 viewPos = u_viewMatrix * u_modelMatrix * a_position;
v_dist = length(viewPos.xyz);
}
Approximate value
We commonly use
z
value as the approximate value for the distance. We also have several ways to express it.In
VC(view coordinate system)
1
2
3
4
5
6
7
8
9gl_Position = u_mvpMatrix * a_position;
// z is negative in VC, the camera is looking in -z direction
vec4 viewPos = u_viewMatrix * u_modelMatrix * a_position;
v_dist = -viewPos.z;
// OR if you review the perspective project matrix,
// you will find that the ultimate w value is just -z, so:
v_dist = gl_Position.w;In
window coordinate system
,z
value is between 0 and 1 and we can just use it.1
2// fragment shader
dist = gl_FragCoord.z;This is the cheapest one!