1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-15 18:57:08 +00:00

Update volumetrics

This commit is contained in:
Gefüllte Taubenbrust 2024-08-18 15:13:26 +02:00
parent 22ba7449f2
commit e6752008e0
17 changed files with 420 additions and 181 deletions

View file

@ -1,24 +1,49 @@
#define cloudsTexture texture0
#define sceneTexture texture1
#define depthmap texture2
uniform sampler2D cloudsTexture;
uniform sampler2D sceneTexture;
uniform sampler2D depthmap;
uniform vec2 texelSize0;
uniform vec3 dayLight;
uniform vec3 cloudColor;
varying vec2 screenspaceCoordinate;
varying vec3 relativePosition;
varying vec3 viewDirection;
varying vec3 sunTint;
varying float auroraFactor;
uniform vec3 cameraOffset;
uniform vec3 cameraPosition;
uniform float cameraNear;
uniform float cameraFar;
uniform float cloudHeight;
uniform float cloudThickness;
float getDepth(vec2 screenspacePosition) {
float depth = texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r;
return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar));
}
vec4 sampleClouds(vec2 uv) {
vec4 cloudsKey = texture2D(cloudsTexture, uv);
const vec3 darkColor = vec3(0.05, 0.1, 0.2);
//const vec3 darkColor = vec3(0.05, 0.1, 0.2);
vec3 darkColor = vec3(0.2, 0.4, 0.8) * dayLight;
const vec3 auroraDark = vec3(0., 0.5, 0.5);
const vec3 auroraBright = vec3(0., 0.5, .0);
//const vec3 auroraDark = vec3(0.);
//const vec3 auroraBright = vec3(0.);
return vec4(
mix(auroraDark, auroraBright, cloudsKey.b) * cloudsKey.b * max(0., 1. - cloudsKey.r) +
cloudsKey.r * (darkColor * max(0., 1. - cloudsKey.g) + dayLight * cloudsKey.g),
mix(auroraDark, auroraBright, cloudsKey.b) * cloudsKey.b * auroraFactor +
cloudsKey.r * cloudColor * (darkColor * max(0., 1. - cloudsKey.g) + dayLight * sunTint * cloudsKey.g),
cloudsKey.r);
}
@ -37,8 +62,22 @@ vec4 getClouds(vec2 uv) {
void main(void)
{
vec4 cloudsColor = getClouds(screenspaceCoordinate * 0.5 + 0.5);
vec3 viewVec = normalize(relativePosition);
vec3 position = cameraOffset + cameraPosition;
float depth = getDepth(screenspaceCoordinate) / normalize(viewDirection).z;
float bottomPlaneIntersect = max((cloudHeight - cameraPosition.y) / viewVec.y, 0.);
float topPlaneIntersect = max((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0.);
float minPlane = min(bottomPlaneIntersect, topPlaneIntersect);
vec4 sceneColor = texture2D(sceneTexture, screenspaceCoordinate * 0.5 + 0.5);
gl_FragColor = vec4(sceneColor.rgb * (1. - cloudsColor.a) + cloudsColor.rgb, 1.);
if (depth > minPlane) {
vec4 finalColor = getClouds(screenspaceCoordinate * 0.5 + 0.5);
gl_FragColor = vec4(sceneColor.rgb * (1. - finalColor.a) + finalColor.rgb, 1.);
} else {
gl_FragColor = sceneColor;
}
}

View file

@ -1,7 +1,48 @@
uniform mat4 mCameraProjInv;
uniform mat4 mCameraView;
uniform vec3 v_LightDirection;
uniform float f_timeofday;
varying vec3 relativePosition;
varying vec3 viewDirection;
varying vec2 screenspaceCoordinate;
varying vec3 sunTint;
varying float auroraFactor;
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.))));
}
// custom smoothstep implementation because it's not defined in glsl1.2
// https://docs.gl/sl4/smoothstep
float mtsmoothstep(in float edge0, in float edge1, in float x)
{
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
void main(void)
{
vec4 p = mCameraProjInv * inVertexPosition;
viewDirection = p.xyz / p.w;
relativePosition = (p.xyz / p.w) * mat3(mCameraView);
screenspaceCoordinate = inVertexPosition.xy;
auroraFactor = 1. - mtsmoothstep(0.13, 0.15, f_timeofday) * mtsmoothstep(0.87, 0.85, f_timeofday);
float tintFactor = mtsmoothstep(0.21, 0.24, f_timeofday) * mtsmoothstep(0.793, 0.753, f_timeofday);
sunTint = mix(vec3(1.0), getDirectLightScatteringAtGround(v_LightDirection), tintFactor);
gl_Position = inVertexPosition;
}

View file

@ -1,17 +0,0 @@
uniform float cloudDensity;
// Pseudorandom number generator
float rand(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}
// More random pseudorandom number generator;
float noise(vec2 p){
vec2 p2 = p + vec2(rand(p), rand(p.yx));
return rand(p2);
}
void main(void)
{
gl_FragColor = vec4(vec3(step(noise(floor(gl_FragCoord.xy * 0.25)), cloudDensity)), 1.);
}

View file

@ -1,4 +0,0 @@
void main(void)
{
gl_Position = inVertexPosition;
}

View file

@ -1,15 +0,0 @@
// Pseudorandom number generator
float rand(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}
// More random pseudorandom number generator;
float noise(vec2 p){
vec2 p2 = p + vec2(rand(p), rand(p.yx));
return rand(p2);
}
void main(void)
{
gl_FragColor = vec4(vec3(noise(gl_FragCoord.xy)), 1.);
}

View file

@ -1,4 +0,0 @@
void main(void)
{
gl_Position = inVertexPosition;
}

View file

@ -2,10 +2,13 @@
#define noiseTexture texture1
#define noiseTextureCoarse texture2
#define PROBING_ITERATIONS 30
#define ITERATIONS 50
#define LIGHT_ITERATIONS 10
#define LIGHT_DISTANCE 100.
#define AURORA_ITERATIONS 100
#define LIGHT_ITERATIONS 3
#define AURORA_ITERATIONS 80
// See clouds.cpp
#define CLOUD_SIZE 640.0
uniform sampler2D depthmap;
uniform sampler2D noiseTexture;
@ -19,17 +22,17 @@ uniform float cloudDensity;
varying vec3 relativePosition;
varying vec3 viewDirection;
uniform vec3 eyePosition;
uniform vec3 cameraOffset;
uniform vec3 cameraPosition;
uniform mat4 mCameraView;
uniform mat4 mCameraProjInv;
uniform float cameraNear;
uniform float cameraFar;
uniform vec2 cloudOffset;
uniform float cloudRadius;
varying vec2 screenspaceCoordinate;
varying float sunStrength;
uniform float fogDistance;
uniform float fogShadingParameter;
@ -41,7 +44,8 @@ uniform float animationTimer;
// Derived From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom)
// NOTE: `frag_coord` is in pixels (i.e. not normalized UV).
float screenSpaceDither(highp vec2 frag_coord) {
float screenSpaceDither(highp vec2 frag_coord)
{
// Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR.
highp float dither = dot(vec2(171.0, 231.0), frag_coord);
dither = fract(dither / 103.0);
@ -57,38 +61,47 @@ float mtsmoothstep(in float edge0, in float edge1, in float x)
return t * t * (3.0 - 2.0 * t);
}
float getDepth(vec2 screenspacePosition) {
float depth = texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r;
float toLinearDepth(float depth)
{
return cameraNear * cameraFar / (cameraFar + depth * (cameraNear - cameraFar));
}
float getRawDepth(vec2 screenspacePosition) {
float getDepth(vec2 screenspacePosition)
{
return texture2D(depthmap, screenspacePosition * 0.5 + 0.5).r;
}
float noise(vec3 p){
//p.y *= 1.;
float noise(vec3 p)
{
float y = floor(p.y);
float f1 = texture2D(noiseTexture, p.xz / 256. + y * 0.2).r;
float f2 = texture2D(noiseTexture, p.xz / 256. + y * 0.2 + 0.2).r;
return mix(f1, f2, fract(p.y));
}
float fnoise(vec3 p) {
float fnoise(vec3 p)
{
return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25;
}
float fnoise3(vec3 p) {
float fnoise3(vec3 p)
{
return noise(p * 4.) * 0.5 + noise(p * 8.) * 0.25 + noise(p * 16.) * 0.125;
}
float getAuroraDensity(vec3 position) {
float getAuroraDensity(vec3 position)
{
float density = pow(max(0., 1. - 10. * abs(fnoise3(vec3(position.x * 0.25, animationTimer, position.z * 0.25)) - 0.5)), 4.);
return 1.0 * density * mtsmoothstep(0.0, 0.05, position.y - 1.) * pow(1. - mtsmoothstep(0.05, 2.0, position.y - 1.), 4.);
return 0.7 * density * mtsmoothstep(0.0, 0.05, position.y - 1.) * pow(1. - mtsmoothstep(0.05, 2.0, position.y - 1.), 4.);
}
float getDensity(vec3 position) {
float density = texture2D(noiseTextureCoarse, position.xz / 2560. / 16.).r *
float getCoarse(vec3 position) {
return texture2D(noiseTextureCoarse, (position.xz - cloudOffset) * 0.5 / CLOUD_SIZE / cloudRadius).r;
}
float getDensity(vec3 position)
{
float density = texture2D(noiseTextureCoarse, (position.xz - cloudOffset) * 0.5 / CLOUD_SIZE / cloudRadius).r *
mtsmoothstep(0.0, cloudThickness * 0.2, position.y - cloudHeight) *
(1.0 - mtsmoothstep(cloudThickness * 0.5, cloudThickness, position.y - cloudHeight));
@ -97,17 +110,19 @@ float getDensity(vec3 position) {
return 0.04 * density;
}
float getBrightness(vec3 position, float bias) {
float getBrightness(vec3 position, float lightDistance)
{
float density = 0.;
for (int i = 0; i < LIGHT_ITERATIONS; i++) {
vec3 rayPosition = position - v_LightDirection * LIGHT_DISTANCE * (float(i) + bias) / float(LIGHT_ITERATIONS);
for (int i = 1; i <= LIGHT_ITERATIONS; i++) {
vec3 rayPosition = position - v_LightDirection * lightDistance * float(i) / float(LIGHT_ITERATIONS);
density += getDensity(rayPosition) * float(LIGHT_DISTANCE) / float(LIGHT_ITERATIONS);
density += getDensity(rayPosition) * float(lightDistance) / float(LIGHT_ITERATIONS);
}
return exp(-density);
}
float blend(float A, float B, float alphaA, float alphaB) {
float blend(float A, float B, float alphaA, float alphaB)
{
float alphaC = alphaA + (1. - alphaA) * alphaB;
return (alphaA * A + (1. - alphaA) * alphaB * B) / alphaC;
}
@ -116,11 +131,16 @@ void main(void)
{
vec3 viewVec = normalize(relativePosition);
vec3 position = cameraOffset + eyePosition;
vec3 position = cameraOffset + cameraPosition;
float depth = getDepth(screenspaceCoordinate) / normalize(viewDirection).z;
float bottomPlaneIntersect = clamp(min((cloudHeight - eyePosition.y) / viewVec.y, depth), 0., 4. * fogDistance);
float topPlaneIntersect = clamp(min((cloudHeight + cloudThickness - eyePosition.y) / viewVec.y, depth), 0., 4. * fogDistance);
float depth = toLinearDepth(getDepth(screenspaceCoordinate)) / normalize(viewDirection).z;
float bottomPlaneIntersect = clamp((cloudHeight - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance);
float topPlaneIntersect = clamp((cloudHeight + cloudThickness - cameraPosition.y) / viewVec.y, 0., 4. * fogDistance);
if ((bottomPlaneIntersect > depth + 5.0) != (topPlaneIntersect > depth + 5.0)) {
bottomPlaneIntersect = min(depth, bottomPlaneIntersect);
topPlaneIntersect = min(depth, topPlaneIntersect);
}
float startDepth = min(bottomPlaneIntersect, topPlaneIntersect);
float endDepth = max(bottomPlaneIntersect, topPlaneIntersect);
@ -129,17 +149,15 @@ void main(void)
vec3 color = vec3(0.);
float dx = (endDepth - startDepth) / float(ITERATIONS);
float density = 0.;
float auroraStartDepth = min(max(0., 1.0 / viewVec.y), 8.);
float auroraEndDepth = min(max(0., 3.0 / viewVec.y), 8.);
float rawDepth = getRawDepth(screenspaceCoordinate);
float rawDepth = getDepth(screenspaceCoordinate);
if (auroraEndDepth - auroraStartDepth > 0.1 && rawDepth >= 1.0) {
for (int i = 0; i < ITERATIONS; i++) {
vec3 rayPosition = viewVec * (auroraStartDepth + (auroraEndDepth - auroraStartDepth) * (float(i) + bias) / float(ITERATIONS));
for (int i = 0; i < AURORA_ITERATIONS; i++) {
vec3 rayPosition = viewVec * (auroraStartDepth + (auroraEndDepth - auroraStartDepth) * (float(i) + bias) / float(AURORA_ITERATIONS));
float localDensity = getAuroraDensity(rayPosition);
@ -150,33 +168,42 @@ void main(void)
}
color.b = density * (auroraEndDepth - auroraStartDepth) / float(AURORA_ITERATIONS);
float sunlightContribution = 0.;
float alpha = 0.;
float outScatter = 2. * (dot(v_LightDirection, viewVec) * 0.5 + 0.5);
float forwardScatter = 1. + 2. * pow(min(dot(v_LightDirection, viewVec), 0.), 4.);
density = 0.;
for (int i = 0; i < ITERATIONS; i++) {
vec3 rayPosition = eyePosition + viewVec * (startDepth + (endDepth - startDepth) * (float(i) + bias) / float(ITERATIONS));
float fogDepth = min(4. * fogDistance, startDepth + 2000.);
endDepth = min(endDepth, fogDepth);
float localDensity = getDensity(rayPosition) * dx;
float dx = (endDepth - startDepth) / float(ITERATIONS);
float lightDistance = cloudThickness * 0.5;
if (localDensity < 0.0001) continue;
if (endDepth - startDepth > 0.1) {
for (int i = 0; i < ITERATIONS; i++) {
vec3 rayPosition = cameraPosition + viewVec * (startDepth + (endDepth - startDepth) * (float(i) + bias) / float(ITERATIONS));
float clarity = clamp(fogShadingParameter - fogShadingParameter * length(rayPosition - eyePosition) / (4. * fogDistance), 0.0, 1.0);
float brightness = getBrightness(rayPosition, bias) * exp(-outScatter * localDensity);
sunlightContribution = blend(sunlightContribution, brightness, 1. - exp(-density), 1. - exp(-localDensity));
alpha = blend(alpha, clarity, 1. - exp(-density), 1. - exp(-localDensity));
float localDensity = getDensity(rayPosition) * dx;
density += localDensity;
if (localDensity < 0.0001) continue;
if (density > 10.0) break;
float clarity = clamp(fogShadingParameter - fogShadingParameter * length(rayPosition - cameraPosition) / (fogDepth), 0.0, 1.0);
float outScatterContribution = exp(-0.5 * outScatter * localDensity);
float brightness = getBrightness(rayPosition, lightDistance) * forwardScatter * outScatterContribution * sunStrength + (1. - outScatterContribution);
sunlightContribution = blend(sunlightContribution, brightness, 1. - exp(-density), 1. - exp(-localDensity));
alpha = blend(alpha, clarity, 1. - exp(-density), 1. - exp(-localDensity));
density += localDensity;
if (density > 10.0) break;
}
}
float forwardScatter = 1. + 4. * pow(min(dot(v_LightDirection, viewVec), 0.), 4.);
color.r = (1. - exp(-density)) * alpha;
color.g = sunlightContribution * forwardScatter;
color.g = sunlightContribution;
color.b *= exp(-density);
gl_FragColor = vec4(color, 1.0);
}

View file

@ -1,11 +1,18 @@
uniform mat4 mCameraProjInv;
uniform mat4 mCameraView;
uniform vec3 eyePosition;
uniform float f_timeofday;
varying vec3 relativePosition;
varying vec3 viewDirection;
varying vec2 screenspaceCoordinate;
varying float sunStrength;
float mtsmoothstep(in float edge0, in float edge1, in float x)
{
float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
void main(void)
{
@ -13,5 +20,18 @@ void main(void)
vec4 p = mCameraProjInv * inVertexPosition;
viewDirection = p.xyz / p.w;
relativePosition = (p.xyz / p.w) * mat3(mCameraView);
if (f_timeofday < 0.21) {
sunStrength =
(1.0 - mtsmoothstep(0.18, 0.21, f_timeofday));
} else if (f_timeofday >= 0.793) {
sunStrength =
mtsmoothstep(0.793, 0.823, f_timeofday);
} else {
sunStrength =
mtsmoothstep(0.21, 0.26, f_timeofday) *
(1.0 - mtsmoothstep(0.743, 0.793, f_timeofday));
}
gl_Position = inVertexPosition;
}