mirror of
https://github.com/PixelGuys/Cubyz.git
synced 2025-08-03 03:06:55 -04:00
96 lines
3.6 KiB
GLSL
96 lines
3.6 KiB
GLSL
#version 460
|
|
|
|
layout(location = 0) out vec4 fragColor;
|
|
|
|
layout(location = 0) in vec2 texCoords;
|
|
layout(location = 1) flat in vec3[4] directions;
|
|
|
|
layout(binding = 3) uniform sampler2D color;
|
|
|
|
layout(binding = 4) uniform sampler2D depthTexture;
|
|
uniform float zNear;
|
|
uniform float zFar;
|
|
uniform vec2 tanXY;
|
|
|
|
layout(binding = 5) uniform sampler2D bloomColor;
|
|
|
|
struct Fog {
|
|
vec3 color;
|
|
float density;
|
|
float fogLower;
|
|
float fogHigher;
|
|
};
|
|
|
|
uniform Fog fog;
|
|
|
|
uniform ivec3 playerPositionInteger;
|
|
uniform vec3 playerPositionFraction;
|
|
|
|
float zFromDepth(float depthBufferValue) {
|
|
return zNear*zFar/(depthBufferValue*(zNear - zFar) + zFar);
|
|
}
|
|
|
|
float densityIntegral(float dist, float zStart, float zDist, float fogLower, float fogHigher) {
|
|
// The density is constant until fogLower, then gets smaller linearly until reaching fogHigher, past which there is no fog.
|
|
if(zDist < 0) {
|
|
zStart += zDist;
|
|
zDist = -zDist;
|
|
}
|
|
if(abs(zDist) < 0.001) {
|
|
zDist = 0.001;
|
|
}
|
|
float beginLower = min(fogLower, zStart);
|
|
float endLower = min(fogLower, zStart + zDist);
|
|
float beginMid = max(fogLower, min(fogHigher, zStart));
|
|
float endMid = max(fogLower, min(fogHigher, zStart + zDist));
|
|
float midIntegral = -0.5*(endMid - fogHigher)*(endMid - fogHigher)/(fogHigher - fogLower) - -0.5*(beginMid - fogHigher)*(beginMid - fogHigher)/(fogHigher - fogLower);
|
|
if(fogHigher == fogLower) midIntegral = 0;
|
|
|
|
return (endLower - beginLower + midIntegral)/zDist*dist;
|
|
}
|
|
|
|
float calculateFogDistance(float dist, float densityAdjustment, float zStart, float zScale, float fogDensity, float fogLower, float fogHigher) {
|
|
float distCameraTerrain = densityIntegral(dist*densityAdjustment, zStart, zScale*dist*densityAdjustment, fogLower, fogHigher)*fogDensity;
|
|
float distFromCamera = 0;
|
|
float distFromTerrain = distFromCamera - distCameraTerrain;
|
|
if(distCameraTerrain < 10) { // Resolution range is sufficient.
|
|
return distFromTerrain;
|
|
} else {
|
|
// Here we have a few options to deal with this. We could for example weaken the fog effect to fit the entire range.
|
|
// I decided to keep the fog strength close to the camera and far away, with a fog-free region in between.
|
|
// I decided to this because I want far away fog to work (e.g. a distant ocean) as well as close fog(e.g. the top surface of the water when the player is under it)
|
|
if(distFromTerrain > -5 && dist != 0) {
|
|
return distFromTerrain;
|
|
} else if(distFromCamera < 5) {
|
|
return distFromCamera - 10;
|
|
} else {
|
|
return -5;
|
|
}
|
|
}
|
|
}
|
|
|
|
vec3 applyFrontfaceFog(float fogDistance, vec3 fogColor, vec3 inColor) {
|
|
float fogFactor = exp(fogDistance);
|
|
inColor *= fogFactor;
|
|
inColor += fogColor;
|
|
inColor -= fogColor*fogFactor;
|
|
return inColor;
|
|
}
|
|
|
|
void main() {
|
|
fragColor = texture(color, texCoords);
|
|
fragColor += texture(bloomColor, texCoords);
|
|
vec2 clampedTexCoords = (floor(texCoords*vec2(textureSize(color, 0))) + 0.5)/vec2(textureSize(color, 0));
|
|
vec3 direction = clampedTexCoords.x*(
|
|
clampedTexCoords.y*directions[0] + (1 - clampedTexCoords.y)*directions[1]
|
|
) + (1 - clampedTexCoords.x)*(
|
|
clampedTexCoords.y*directions[2] + (1 - clampedTexCoords.y)*directions[3]
|
|
);
|
|
float densityAdjustment = sqrt(dot(tanXY*(clampedTexCoords*2 - 1), tanXY*(clampedTexCoords*2 - 1)) + 1);
|
|
float dist = zFromDepth(texture(depthTexture, texCoords).r);
|
|
float fogDistance = calculateFogDistance(dist, densityAdjustment, playerPositionFraction.z, normalize(direction).z, fog.density, fog.fogLower - playerPositionInteger.z, fog.fogHigher - playerPositionInteger.z);
|
|
fragColor.rgb = applyFrontfaceFog(fogDistance, fog.color, fragColor.rgb);
|
|
float maxColor = max(1.0, max(fragColor.r, max(fragColor.g, fragColor.b)));
|
|
fragColor.rgb = fragColor.rgb/maxColor;
|
|
}
|