For example, given a terrain with an avatar on it with a camera far away overhead: is it possible to render the fog so that the avatar remains perfectly unfogged while the terrain around the avatar fades into the fog?
Sure, though as far as I know, you'll have to make your own shader rather than using the ones provided with three.js. There may be a way to customize them in this way, but if there is, I'm not familiar with it.
Check out this answer on doing fog as distance from the camera. The idea, as explained there, is to pass the camera position in as a uniform to the shader, then in the vertex shader on all your objects, you find the distance from the camera position to the vertex you're transforming. You then pass that distance along as a varying to the fragment shader, and you can figure out the distance per pixel, which you use to mix between a fogged color and the object's regular color. You can see that in this example from the OpenGL ES 2.0 Programming guide.
To change it to be based on distance from the character is simple: you just pass in the character position as the uniform that you're calculating distance from instead of the camera position (in that sample code, you would replace u_eyePos
with something like u_characterPos
and maybe change the varying from v_eyeDist
to v_characterDist
). Except for any name changes, the fragment shader can be exactly the same.
So, something like this (WARNING: NOT TESTED. you're going to have to fix this up to have three.js happy with using it. There are a ton of example of that, though, like this one):
vertex shader:
uniform mat4 matViewProjection;
uniform mat4 matView;
uniform vec4 u_characterPos;
attribute vec4 rm_Vertex;
attribute vec2 rm_TexCoord0;
varying vec2 v_texCoord;
varying float v_characterDist;
void main() {
// Transform vertex to view-space
vec4 vViewPos = matView * rm_Vertex;
// Compute the distance to character
v_characterDist = length(vViewPos - u_characterPos);
gl_Position = matViewProjection * rm_Vertex;
v_texCoord = rm_TexCoord0.xy;
}
fragment shader:
precision mediump float;
uniform vec4 u_fogColor;
uniform float u_fogMaxDist;
uniform float u_fogMinDist;
uniform sampler2D baseMap;
varying vec2 v_texCoord;
varying float v_characterDist;
float computeLinearFogFactor() {
float factor;
// Compute linear fog equation
factor = (u_fogMaxDist - v_characterDist) /
(u_fogMaxDist - u_fogMinDist );
// Clamp in the [0,1] range
factor = clamp(factor, 0.0, 1.0);
return factor;
}
void main() {
float fogFactor = computeLinearFogFactor();
vec4 fogColor = fogFactor * u_fogColor;
vec4 baseColor = texture2D(baseMap, v_texCoord);
// Compute final color as a lerp with fog factor
gl_FragColor = baseColor * fogFactor +
fogColor * (1.0 - fogFactor);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With