From cff6d74148522ec768b989fb39470b4b6cf1a98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Sun, 28 Jan 2024 19:50:49 +0100 Subject: [PATCH] HDR lensflare was too bright but basic exponential hdr was not beautiful. Instead aces tonemapping solves this issue and increases the realism of the lighting Used angular radius of stars to fade the lensflare away when too close --- src/shaders/lensflare.glsl | 39 +++++++++++++++---- src/shaders/utils/camera.glsl | 3 +- .../atmosphericScatteringPostProcess.ts | 2 +- src/ts/postProcesses/uniforms.ts | 8 ++++ 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/shaders/lensflare.glsl b/src/shaders/lensflare.glsl index 208a688ef..3e319fa69 100644 --- a/src/shaders/lensflare.glsl +++ b/src/shaders/lensflare.glsl @@ -26,7 +26,7 @@ float getSun(vec2 uv){ } //from: https://www.shadertoy.com/view/XdfXRX -vec3 lensflares(vec2 uv, vec2 pos, out vec3 sunflare, out vec3 lensflare) +vec3 lensflares(vec2 uv, vec2 pos) { vec2 main = uv-pos; vec2 uvd = uv*(length(uv)); @@ -62,15 +62,15 @@ vec3 lensflares(vec2 uv, vec2 pos, out vec3 sunflare, out vec3 lensflare) float f62 = max(0.01-pow(length(uvx-0.325*pos), 1.6), .0)*3.0; float f63 = max(0.01-pow(length(uvx-0.35*pos), 1.6), .0)*5.0; - sunflare = vec3(f0); - lensflare = vec3(f2+f4+f5+f6, f22+f42+f52+f62, f23+f43+f53+f63); + vec3 sunflare = vec3(f0); + vec3 lensflare = vec3(f2+f4+f5+f6, f22+f42+f52+f62, f23+f43+f53+f63); return sunflare+lensflare; } // - +// based on https://www.shadertoy.com/view/XsGfWV vec3 anflares(vec2 uv, float threshold, float intensity, float stretch, float brightness) { threshold = 1.0 - threshold; @@ -102,11 +102,28 @@ vec3 anflares(vec2 uv, float intensity, float stretch, float brightness) return vec3(smoothstep(0.009, 0.0, length(uv)))*brightness; } +vec3 aces_tonemap(vec3 color){ + mat3 m1 = mat3( + 0.59719, 0.07600, 0.02840, + 0.35458, 0.90834, 0.13383, + 0.04823, 0.01566, 0.83777 + ); + mat3 m2 = mat3( + 1.60475, -0.10208, -0.00327, + -0.53108, 1.10813, -0.07276, + -0.07367, -0.00605, 1.07602 + ); + vec3 v = m1 * color; + vec3 a = v * (v + 0.0245786) - 0.000090537; + vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; + return clamp(m2 * (a / b), 0.0, 1.0); +} void main() { vec4 screenColor = texture(textureSampler, vUV); if (visibility == 0.0) { + screenColor.rgb = aces_tonemap(screenColor.rgb); gl_FragColor = screenColor; return; } @@ -128,8 +145,7 @@ void main() { vec3 col = screenColor.rgb; - vec3 sun, sunflare, lensflare; - vec3 flare = lensflares(uv*1.5, mouse*1.5, sunflare, lensflare); + vec3 flare = lensflares(uv*1.5, mouse*1.5); #ifdef CHEAP_FLARE vec3 anflare = pow(anflares(uv-mouse, 400.0, 0.5, 0.6), vec3(4.0)); @@ -139,13 +155,22 @@ void main() { vec3 anflare = pow(anflares(uv-mouse, 0.5, 400.0, 0.9, 0.1), vec3(4.0)); #endif - sun += getSun(uv-mouse) + (flare + anflare)*flareColor*2.0; + // if angular radius is to great, fade the anflare out + float angularRadius = object_radius / length(object_position - camera_position); + anflare *= smoothstep(0.1, 0.0, angularRadius); + + vec3 sun = getSun(uv-mouse) + (flare + anflare)*flareColor*2.0; // no lensflare when looking away from the sun sun *= smoothstep(0.0, 0.1, dot(objectDirection, rayDir)); + // no lensflare when too close to the sun + sun *= smoothstep(0.08, 0.0, angularRadius); + col += sun * visibility; + col = aces_tonemap(col); + // Output to screen gl_FragColor = vec4(col, screenColor.a); } \ No newline at end of file diff --git a/src/shaders/utils/camera.glsl b/src/shaders/utils/camera.glsl index f9d35dfb1..4e66ffbb7 100644 --- a/src/shaders/utils/camera.glsl +++ b/src/shaders/utils/camera.glsl @@ -21,4 +21,5 @@ uniform mat4 camera_view; uniform mat4 camera_inverseProjection; uniform mat4 camera_inverseView; uniform float camera_near; -uniform float camera_far; \ No newline at end of file +uniform float camera_far; +uniform float camera_fov; \ No newline at end of file diff --git a/src/ts/postProcesses/atmosphericScatteringPostProcess.ts b/src/ts/postProcesses/atmosphericScatteringPostProcess.ts index 683661ae8..c6194ec51 100644 --- a/src/ts/postProcesses/atmosphericScatteringPostProcess.ts +++ b/src/ts/postProcesses/atmosphericScatteringPostProcess.ts @@ -62,7 +62,7 @@ export class AtmosphericScatteringPostProcess extends UberPostProcess implements redWaveLength: 700 * (1 + centeredRand(planet.model.rng, 1300) / 6), greenWaveLength: 530 * (1 + centeredRand(planet.model.rng, 1310) / 6), blueWaveLength: 440 * (1 + centeredRand(planet.model.rng, 1320) / 6), - mieHaloRadius: 0.6 + mieHaloRadius: 0.65 }; const uniforms: ShaderUniforms = [ diff --git a/src/ts/postProcesses/uniforms.ts b/src/ts/postProcesses/uniforms.ts index c9a8c1f67..ff2fd262f 100644 --- a/src/ts/postProcesses/uniforms.ts +++ b/src/ts/postProcesses/uniforms.ts @@ -81,6 +81,14 @@ export function getActiveCameraUniforms(scene: Scene): ShaderUniforms { if (scene.activeCamera === null) throw new Error("No active camera"); return scene.activeCamera.maxZ; } + }, + { + name: "camera_fov", + type: UniformEnumType.Float, + get: () => { + if (scene.activeCamera === null) throw new Error("No active camera"); + return scene.activeCamera.fov; + } } ]; }