From f9a920c493ddbb4b1c8f0a1f81d9722c2af41b44 Mon Sep 17 00:00:00 2001 From: Mc-Pain Date: Thu, 18 Jan 2024 08:31:23 +0300 Subject: [PATCH] improve planet rings shaders (#5708) * improve planet rings shaders All rings are assumed to be icy 1) Each object in ring is darker depending of its phase (like Moon phases) 2) Each object shines brightly if sun is behind the ring (lot of low angle specular reflections) 3) Each object shines brightly if looking from the sun (simulating high geometric albedo > 1.0) * Move phase functions into a library * Fix black edges of planetary rings --- data/shaders/opengl/lib.glsl | 19 +++++++++++++++++++ data/shaders/opengl/planetrings.frag | 17 ++++++++++++++++- data/shaders/opengl/planetrings.vert | 2 ++ src/Planet.cpp | 4 ++-- 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/data/shaders/opengl/lib.glsl b/data/shaders/opengl/lib.glsl index 64d7c18f4c0..79d2b53c42b 100644 --- a/data/shaders/opengl/lib.glsl +++ b/data/shaders/opengl/lib.glsl @@ -12,6 +12,25 @@ struct Surface { float ambientOcclusion; }; +// Phase functions +// https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky/simulating-colors-of-the-sky.html +float miePhaseFunction(const float g, const float mu) +{ + /* + * Mie phase function: + */ + return 3.f / (8.f * 3.141592) * ((1.f - g * g) * (1.f + mu * mu)) / ((2.f + g * g) * pow(1.f + g * g - 2.f * g * mu, 1.5f)); +} + +float rayleighPhaseFunction(const float mu) +{ + /* + * Rayleigh phase function: + */ + return 3.f / (16.f * 3.141592) * (1 + mu * mu); +} + + // Currently used by: hopefully everything // Evaluates a standard blinn-phong diffuse+specular, with the addition of a // light intensity term to scale the lighting contribution based on (pre-calculated) diff --git a/data/shaders/opengl/planetrings.frag b/data/shaders/opengl/planetrings.frag index 6c067d0c1bc..ce235129055 100644 --- a/data/shaders/opengl/planetrings.frag +++ b/data/shaders/opengl/planetrings.frag @@ -7,6 +7,7 @@ uniform sampler2D texture0; in vec2 texCoord0; in vec4 texCoord1; +in vec4 varyingEyepos; out vec4 frag_color; @@ -16,10 +17,24 @@ void main(void) vec4 col = vec4(0.0); vec4 texCol = texture(texture0, texCoord0); + vec3 eyenorm = normalize(varyingEyepos.xyz); + for (int i=0; i= 1.0) + float muRev = dot(-normalize(vec3(uLight[i].position)), eyenorm); + float phaseReflect = miePhaseFunction(g, muRev); + + col = col + texCol * (diffuse + phaseThrough + phaseReflect) * uLight[i].diffuse; } } col.a = texCol.a; diff --git a/data/shaders/opengl/planetrings.vert b/data/shaders/opengl/planetrings.vert index bfc74a51f3e..cfde70992ef 100644 --- a/data/shaders/opengl/planetrings.vert +++ b/data/shaders/opengl/planetrings.vert @@ -6,6 +6,7 @@ out vec2 texCoord0; out vec4 texCoord1; +out vec4 varyingEyepos; void main(void) { @@ -13,4 +14,5 @@ void main(void) texCoord0 = a_uv0.xy; texCoord1 = a_vertex; + varyingEyepos = uViewMatrix * a_vertex; } diff --git a/src/Planet.cpp b/src/Planet.cpp index 110998653aa..a1f31b0467e 100644 --- a/src/Planet.cpp +++ b/src/Planet.cpp @@ -156,9 +156,9 @@ void Planet::GenerateRings(Graphics::Renderer *renderer) { Color *row; row = buf.get(); - std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLACK); + std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLANK); row = buf.get() + (RING_TEXTURE_LENGTH - 1) * RING_TEXTURE_WIDTH; - std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLACK); + std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLANK); } const vector3f texSize(RING_TEXTURE_WIDTH, RING_TEXTURE_LENGTH, 0.0f);