From fd5c126e15404feab7d7bbf2db9e5cc153fe3f6e Mon Sep 17 00:00:00 2001 From: benpm Date: Tue, 24 Jun 2025 19:33:51 -0600 Subject: [PATCH] first attempt. doesn't build :P --- .../globebrowsing/shaders/renderer_fs.glsl | 72 +++++++++----- modules/globebrowsing/src/renderableglobe.cpp | 94 +++++++++++++++++-- modules/globebrowsing/src/ringscomponent.cpp | 32 +++++++ modules/globebrowsing/src/ringscomponent.h | 14 ++- 4 files changed, 178 insertions(+), 34 deletions(-) diff --git a/modules/globebrowsing/shaders/renderer_fs.glsl b/modules/globebrowsing/shaders/renderer_fs.glsl index f00641ab81..2d598f3694 100644 --- a/modules/globebrowsing/shaders/renderer_fs.glsl +++ b/modules/globebrowsing/shaders/renderer_fs.glsl @@ -60,12 +60,16 @@ uniform float ambientIntensity; #if SHADOW_MAPPING_ENABLED -#define NSSamplesMinusOne #{nShadowSamples} -#define NSSamples (NSSamplesMinusOne + 1) +// Ring texture projection uniforms +uniform sampler1D ringTextureFwrd; +uniform sampler1D ringTextureBckwrd; +uniform sampler1D ringTextureUnlit; +uniform sampler1D ringTextureColor; +uniform sampler1D ringTextureTransparency; +uniform vec2 textureOffset; +uniform vec3 sunPositionObj; +uniform vec3 camPositionObj; -in vec4 shadowCoords; -uniform sampler2DShadow shadowMapTexture; -uniform float zFightingPercentage; #endif // SHADOW_MAPPING_ENABLED #if USE_ECLIPSE_SHADOWS @@ -269,27 +273,45 @@ Fragment getFragment() { #if SHADOW_MAPPING_ENABLED float shadow = 1.0; - if (shadowCoords.w > 1) { - vec4 normalizedShadowCoords = shadowCoords; - normalizedShadowCoords.z = normalizeFloat(zFightingPercentage * normalizedShadowCoords.w); - normalizedShadowCoords.xy = normalizedShadowCoords.xy / normalizedShadowCoords.w; - normalizedShadowCoords.w = 1.0; - - float sum = 0; - #for i in 0..#{nShadowSamples} - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-NSSamples + #{i}, -NSSamples + #{i})); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-NSSamples + #{i}, 0)); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-NSSamples + #{i}, NSSamples - #{i})); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, -NSSamples + #{i})); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, NSSamples - #{i})); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, -NSSamples + #{i})); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, 0)); - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, NSSamples - #{i})); - #endfor - sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(0, 0)); - shadow = sum / (8.0 * NSSamples + 1.f); + + // Calculate ring shadow by projecting ring texture directly onto surface + // Assume ring lies in the XZ plane (Y=0) in object space + vec3 surfaceToSun = normalize(sunPositionObj - positionCameraSpace); + + // Find intersection of light ray with ring plane (Y=0) + // Ray equation: P = positionCameraSpace + t * surfaceToSun + // For ring plane: P.y = 0, so t = -positionCameraSpace.y / surfaceToSun.y + if (abs(surfaceToSun.y) > 0.001) { // Avoid division by zero + float t = -positionCameraSpace.y / surfaceToSun.y; + + if (t > 0.0) { // Ray intersects ring plane in front of surface + vec3 ringIntersection = positionCameraSpace + t * surfaceToSun; + + // Calculate distance from ring center + float ringRadius = length(ringIntersection.xz); + + // Convert radius to texture coordinate based on ring texture mapping + // Radius \in [textureOffset.x, textureOffset.y] maps to texCoord \in [0,1] + float texCoord = (ringRadius - textureOffset.x) / (textureOffset.y - textureOffset.x); + + if (texCoord >= 0.0 && texCoord <= 1.0) { + // Sample ring transparency texture + vec4 transparency = texture(ringTextureTransparency, texCoord); + // Determine which side of ring we're viewing from (matches ring shader logic) + float lerpFactor = dot(camPositionObj, sunPositionObj); + + // Sample appropriate ring texture based on viewing direction + vec4 ringColor = mix(texture(ringTextureFwrd, texCoord), texture(ringTextureBckwrd, texCoord), lerpFactor); + + // Calculate shadow factor based on ring opacity + float ringOpacity = transparency.a; + shadow = 1.0 - ringOpacity; + shadow = clamp(shadow + 0.3, 0.0, 1.0); // Add ambient light similar to original + } + } } - frag.color.xyz *= shadow < 0.99 ? clamp(shadow + 0.3, 0.0, 1.0) : shadow; + + frag.color.xyz *= shadow; #endif frag.color.a *= opacity; diff --git a/modules/globebrowsing/src/renderableglobe.cpp b/modules/globebrowsing/src/renderableglobe.cpp index 2f550172d0..3cc9296f2e 100644 --- a/modules/globebrowsing/src/renderableglobe.cpp +++ b/modules/globebrowsing/src/renderableglobe.cpp @@ -1441,9 +1441,7 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData& if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) { calculateEclipseShadows(program, data, ShadowCompType::GLOBAL_SHADOW); - } - - // Shadow Mapping + } // Shadow Mapping ghoul::opengl::TextureUnit shadowMapUnit; if (_shadowMappingProperties.shadowMapping && shadowData.shadowDepthTexture != 0) { // Adding the model transformation to the final shadow matrix so we have a @@ -1462,6 +1460,49 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData& "zFightingPercentage", _shadowMappingProperties.zFightingPercentage ); + + // Bind ring textures for direct projection when rings component is available + if (_ringsComponent && _ringsComponent->isEnabled() && _ringsComponent->isReady()) { + ghoul::opengl::TextureUnit ringTextureFwrdUnit; + ghoul::opengl::TextureUnit ringTextureBckwrdUnit; + ghoul::opengl::TextureUnit ringTextureUnlitUnit; + ghoul::opengl::TextureUnit ringTextureColorUnit; + ghoul::opengl::TextureUnit ringTextureTransparencyUnit; + + if (_ringsComponent->ringTextureFwrd()) { + ringTextureFwrdUnit.activate(); + _ringsComponent->ringTextureFwrd()->bind(); + program.setUniform("ringTextureFwrd", ringTextureFwrdUnit); + } + + if (_ringsComponent->ringTextureBckwrd()) { + ringTextureBckwrdUnit.activate(); + _ringsComponent->ringTextureBckwrd()->bind(); + program.setUniform("ringTextureBckwrd", ringTextureBckwrdUnit); + } + + if (_ringsComponent->ringTextureUnlit()) { + ringTextureUnlitUnit.activate(); + _ringsComponent->ringTextureUnlit()->bind(); + program.setUniform("ringTextureUnlit", ringTextureUnlitUnit); + } + + if (_ringsComponent->ringTextureColor()) { + ringTextureColorUnit.activate(); + _ringsComponent->ringTextureColor()->bind(); + program.setUniform("ringTextureColor", ringTextureColorUnit); + } + + if (_ringsComponent->ringTextureTransparency()) { + ringTextureTransparencyUnit.activate(); + _ringsComponent->ringTextureTransparency()->bind(); + program.setUniform("ringTextureTransparency", ringTextureTransparencyUnit); + } + + program.setUniform("textureOffset", _ringsComponent->textureOffset()); + program.setUniform("sunPositionObj", _ringsComponent->sunPositionObj()); + program.setUniform("camPositionObj", _ringsComponent->camPositionObj()); + } } else if (_shadowMappingProperties.shadowMapping && _shadowComponent) { shadowMapUnit.activate(); @@ -1581,9 +1622,7 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) { calculateEclipseShadows(program, data, ShadowCompType::LOCAL_SHADOW); - } - - // Shadow Mapping + } // Shadow Mapping ghoul::opengl::TextureUnit shadowMapUnit; if (_shadowMappingProperties.shadowMapping && shadowData.shadowDepthTexture != 0) { // Adding the model transformation to the final shadow matrix so we have a @@ -1602,6 +1641,49 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d "zFightingPercentage", _shadowMappingProperties.zFightingPercentage ); + + // Bind ring textures for direct projection when rings component is available + if (_ringsComponent && _ringsComponent->isEnabled() && _ringsComponent->isReady()) { + ghoul::opengl::TextureUnit ringTextureFwrdUnit; + ghoul::opengl::TextureUnit ringTextureBckwrdUnit; + ghoul::opengl::TextureUnit ringTextureUnlitUnit; + ghoul::opengl::TextureUnit ringTextureColorUnit; + ghoul::opengl::TextureUnit ringTextureTransparencyUnit; + + if (_ringsComponent->ringTextureFwrd()) { + ringTextureFwrdUnit.activate(); + _ringsComponent->ringTextureFwrd()->bind(); + program.setUniform("ringTextureFwrd", ringTextureFwrdUnit); + } + + if (_ringsComponent->ringTextureBckwrd()) { + ringTextureBckwrdUnit.activate(); + _ringsComponent->ringTextureBckwrd()->bind(); + program.setUniform("ringTextureBckwrd", ringTextureBckwrdUnit); + } + + if (_ringsComponent->ringTextureUnlit()) { + ringTextureUnlitUnit.activate(); + _ringsComponent->ringTextureUnlit()->bind(); + program.setUniform("ringTextureUnlit", ringTextureUnlitUnit); + } + + if (_ringsComponent->ringTextureColor()) { + ringTextureColorUnit.activate(); + _ringsComponent->ringTextureColor()->bind(); + program.setUniform("ringTextureColor", ringTextureColorUnit); + } + + if (_ringsComponent->ringTextureTransparency()) { + ringTextureTransparencyUnit.activate(); + _ringsComponent->ringTextureTransparency()->bind(); + program.setUniform("ringTextureTransparency", ringTextureTransparencyUnit); + } + + program.setUniform("textureOffset", _ringsComponent->textureOffset()); + program.setUniform("sunPositionObj", _ringsComponent->sunPositionObj()); + program.setUniform("camPositionObj", _ringsComponent->camPositionObj()); + } } else if (_shadowMappingProperties.shadowMapping) { shadowMapUnit.activate(); diff --git a/modules/globebrowsing/src/ringscomponent.cpp b/modules/globebrowsing/src/ringscomponent.cpp index d98b4c7492..1026ab29da 100644 --- a/modules/globebrowsing/src/ringscomponent.cpp +++ b/modules/globebrowsing/src/ringscomponent.cpp @@ -867,4 +867,36 @@ double RingsComponent::size() const { return _size; } +ghoul::opengl::Texture* RingsComponent::ringTextureFwrd() const { + return _textureForwards.get(); +} + +ghoul::opengl::Texture* RingsComponent::ringTextureBckwrd() const { + return _textureBackwards.get(); +} + +ghoul::opengl::Texture* RingsComponent::ringTextureUnlit() const { + return _textureUnlit.get(); +} + +ghoul::opengl::Texture* RingsComponent::ringTextureColor() const { + return _textureColor.get(); +} + +ghoul::opengl::Texture* RingsComponent::ringTextureTransparency() const { + return _textureTransparency.get(); +} + +glm::vec2 RingsComponent::textureOffset() const { + return _offset; +} + +glm::vec3 RingsComponent::sunPositionObj() const { + return _sunPosition; +} + +glm::vec3 RingsComponent::camPositionObj() const { + return _camPositionObjectSpace; +} + } // namespace openspace diff --git a/modules/globebrowsing/src/ringscomponent.h b/modules/globebrowsing/src/ringscomponent.h index 63aeaed122..433c0d501d 100644 --- a/modules/globebrowsing/src/ringscomponent.h +++ b/modules/globebrowsing/src/ringscomponent.h @@ -69,11 +69,19 @@ public: ); void update(const UpdateData& data); - static documentation::Documentation Documentation(); - - bool isEnabled() const; + static documentation::Documentation Documentation(); bool isEnabled() const; double size() const; + // Texture access methods for globe rendering + ghoul::opengl::Texture* ringTextureFwrd() const; + ghoul::opengl::Texture* ringTextureBckwrd() const; + ghoul::opengl::Texture* ringTextureUnlit() const; + ghoul::opengl::Texture* ringTextureColor() const; + ghoul::opengl::Texture* ringTextureTransparency() const; + glm::vec2 textureOffset() const; + glm::vec3 sunPositionObj() const; + glm::vec3 camPositionObj() const; + private: void loadTexture(); void createPlane();