mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Initial implementation of 'Godrays'
This commit is contained in:
parent
cad8e895f2
commit
04f0d545da
3 changed files with 148 additions and 2 deletions
|
@ -1,13 +1,28 @@
|
|||
#define rendered texture0
|
||||
#define depthmap texture2
|
||||
|
||||
struct ExposureParams {
|
||||
float compensationFactor;
|
||||
};
|
||||
|
||||
uniform sampler2D rendered;
|
||||
uniform sampler2D depthmap;
|
||||
|
||||
uniform mediump float bloomStrength;
|
||||
uniform ExposureParams exposureParams;
|
||||
|
||||
uniform vec3 sunPositionScreen;
|
||||
uniform float sunBrightness;
|
||||
uniform vec3 moonPositionScreen;
|
||||
uniform float moonBrightness;
|
||||
|
||||
uniform vec3 dayLight;
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
uniform vec3 v_LightDirection;
|
||||
#else
|
||||
const vec3 v_LightDirection = vec3(0.0, -1.0, 0.0);
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES
|
||||
varying mediump vec2 varTexCoord;
|
||||
#else
|
||||
|
@ -18,6 +33,80 @@ centroid varying vec2 varTexCoord;
|
|||
varying float exposure; // linear exposure factor, see vertex shader
|
||||
#endif
|
||||
|
||||
const float far = 1000.;
|
||||
const float near = 1.;
|
||||
float mapDepth(float depth)
|
||||
{
|
||||
return min(1., 1. / (1.00001 - depth) / far);
|
||||
}
|
||||
|
||||
float noise(vec3 uvd) {
|
||||
return fract(dot(sin(uvd * vec3(13041.19699, 27723.29171, 61029.77801)), vec3(73137.11101, 37312.92319, 10108.89991)));
|
||||
}
|
||||
|
||||
float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth)
|
||||
{
|
||||
lightVec = 0.5 * lightVec / lightVec.z + 0.5;
|
||||
const float samples = 30.;
|
||||
float result = texture2D(depthmap, uv).r < 1. ? 0.0 : 1.0;
|
||||
float bias = noise(vec3(uv, rawDepth));
|
||||
vec2 samplepos;
|
||||
for (float i = 1.; i < samples; i++) {
|
||||
samplepos = mix(uv, lightVec.xy, (i + bias) / samples);
|
||||
if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.)
|
||||
result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0;
|
||||
}
|
||||
return result / samples;
|
||||
}
|
||||
|
||||
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
|
||||
{
|
||||
// Based on talk at 2002 Game Developers Conference by Naty Hoffman and Arcot J. Preetham
|
||||
const float beta_r0 = 1e-5; // Rayleigh scattering beta
|
||||
|
||||
// These factors are calculated based on expected value of scattering factor of 1e-5
|
||||
// for Nitrogen at 532nm (green), 2e25 molecules/m3 in atmosphere
|
||||
const vec3 beta_r0_l = vec3(3.3362176e-01, 8.75378289198826e-01, 1.95342379700656) * beta_r0; // wavelength-dependent scattering
|
||||
|
||||
const float atmosphere_height = 15000.; // height of the atmosphere in meters
|
||||
// sun/moon light at the ground level, after going through the atmosphere
|
||||
return exp(-beta_r0_l * atmosphere_height / (1e-5 - dot(v_LightDirection, vec3(0., 1., 0.))));
|
||||
}
|
||||
|
||||
vec3 applyVolumetricLight(vec3 color, vec2 uv, float rawDepth)
|
||||
{
|
||||
vec3 lookDirection = normalize(vec3(uv.x * 2. - 1., uv.y * 2. - 1., rawDepth));
|
||||
vec3 lightSourceTint = vec3(1.0, 0.98, 0.4);
|
||||
|
||||
const float boost = 4.0;
|
||||
float brightness = 0.;
|
||||
vec3 sourcePosition = vec3(-1., -1., -1);
|
||||
|
||||
if (sunPositionScreen.z > 0. && sunBrightness > 0.) {
|
||||
brightness = sunBrightness;
|
||||
sourcePosition = sunPositionScreen;
|
||||
}
|
||||
else if (moonPositionScreen.z > 0. && moonBrightness > 0.) {
|
||||
lightSourceTint = vec3(0.4, 0.9, 1.);
|
||||
brightness = moonBrightness * 0.05;
|
||||
sourcePosition = moonPositionScreen;
|
||||
}
|
||||
|
||||
float cameraDirectionFactor = pow(clamp(dot(sourcePosition, vec3(0., 0., 1.)), 0.0, 0.7), 2.5);
|
||||
float viewAngleFactor = pow(max(0., dot(sourcePosition, lookDirection)), 8.);
|
||||
|
||||
float lightFactor = brightness * sampleVolumetricLight(uv, sourcePosition, rawDepth) *
|
||||
(0.05 * cameraDirectionFactor + 0.95 * viewAngleFactor);
|
||||
|
||||
color = mix(color, boost * getDirectLightScatteringAtGround(v_LightDirection) * dayLight, lightFactor);
|
||||
|
||||
// if (sunPositionScreen.z < 0.)
|
||||
// color.rg += 1. - clamp(abs((2. * uv.xy - 1.) - sunPositionScreen.xy / sunPositionScreen.z) * 1000., 0., 1.);
|
||||
// if (moonPositionScreen.z < 0.)
|
||||
// color.rg += 1. - clamp(abs((2. * uv.xy - 1.) - moonPositionScreen.xy / moonPositionScreen.z) * 1000., 0., 1.);
|
||||
return color;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 uv = varTexCoord.st;
|
||||
|
@ -31,5 +120,9 @@ void main(void)
|
|||
color *= exposure;
|
||||
#endif
|
||||
|
||||
float rawDepth = texture2D(depthmap, uv).r;
|
||||
|
||||
color = applyVolumetricLight(color, uv, rawDepth);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0); // force full alpha to avoid holes in the image.
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue