mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-18 10:59:18 -06:00
WIP: getting a more or less correct ring texture coordinate!
This commit is contained in:
@@ -38,6 +38,7 @@ out vec3 ellipsoidNormalCameraSpace;
|
||||
out vec3 levelWeights;
|
||||
out vec3 positionCameraSpace;
|
||||
out vec3 positionWorldSpace;
|
||||
out vec3 posObjSpace;
|
||||
|
||||
#if USE_ACCURATE_NORMALS
|
||||
out vec3 ellipsoidTangentThetaCameraSpace;
|
||||
@@ -133,6 +134,7 @@ void main() {
|
||||
ellipsoidNormalCameraSpace = mat3(modelViewTransform) * pair.normal;
|
||||
positionCameraSpace = vec3(modelViewTransform * vec4(pair.position, 1.0));
|
||||
positionWorldSpace = vec3(modelTransform * dvec4(pair.position, 1.0));
|
||||
posObjSpace = pair.position;
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
shadowCoords = vec4(shadowMatrix * dvec4(pair.position, 1.0));
|
||||
|
||||
@@ -38,6 +38,7 @@ out vec3 ellipsoidNormalCameraSpace;
|
||||
out vec3 levelWeights;
|
||||
out vec3 positionCameraSpace;
|
||||
out vec3 positionWorldSpace;
|
||||
out vec3 posObjSpace;
|
||||
|
||||
#if USE_ACCURATE_NORMALS
|
||||
out vec3 ellipsoidTangentThetaCameraSpace;
|
||||
@@ -117,6 +118,7 @@ void main() {
|
||||
ellipsoidNormalCameraSpace = patchNormalCameraSpace;
|
||||
positionCameraSpace = p;
|
||||
positionWorldSpace = vec3(inverseViewTransform * dvec4(p, 1.0));
|
||||
posObjSpace = vec3(inverseViewTransform * dvec4(p, 1.0));
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
shadowCoords = vec4(shadowMatrix * dvec4(p, 1.0));
|
||||
|
||||
@@ -52,6 +52,10 @@ uniform vec2 vertexResolution;
|
||||
#endif // SHOW_HEIGHT_RESOLUTION
|
||||
|
||||
uniform vec3 lightDirectionCameraSpace;
|
||||
uniform vec3 lightDirectionObjSpace;
|
||||
uniform vec3 lightDirectionWorldSpace;
|
||||
uniform mat4 modelViewTransform;
|
||||
uniform float ringSize;
|
||||
|
||||
#if PERFORM_SHADING
|
||||
uniform float orenNayarRoughness;
|
||||
@@ -70,10 +74,13 @@ uniform sampler1D ringTextureTransparency;
|
||||
uniform vec2 textureOffset;
|
||||
uniform vec3 sunPositionWorld; // NEW: world coordinates
|
||||
uniform vec3 camPositionWorld; // NEW: world coordinates
|
||||
|
||||
#endif // USE_RING_SHADOWS
|
||||
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
|
||||
in vec3 posObjSpace; // Fragment position in object space
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
|
||||
#define NSEclipseShadowsMinusOne #{nEclipseShadows}
|
||||
@@ -277,49 +284,44 @@ Fragment getFragment() {
|
||||
#if USE_RING_SHADOWS
|
||||
// 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(sunPositionWorld - positionWorldSpace); // Use world coordinates
|
||||
vec3 surfaceToSun = normalize(lightDirectionObjSpace); // Use world coordinates
|
||||
vec3 p = posObjSpace;
|
||||
|
||||
// Find intersection of light ray with ring plane (Y=0)
|
||||
// Ray equation: P = positionWorldSpace + t * surfaceToSun
|
||||
// For ring plane: P.y = 0, so t = -positionWorldSpace.y / surfaceToSun.y
|
||||
if (abs(surfaceToSun.y) > 0.001) { // Avoid division by zero
|
||||
float t = -positionWorldSpace.y / surfaceToSun.y;
|
||||
if (abs(surfaceToSun.y) > 1e-8) { // Avoid division by zero
|
||||
float t = -p.y / surfaceToSun.y;
|
||||
|
||||
if (t > 0.0) { // Ray intersects ring plane in front of surface
|
||||
vec3 ringIntersection = positionWorldSpace + t * surfaceToSun;
|
||||
vec3 ringIntersection = p + t * surfaceToSun;
|
||||
|
||||
// Calculate distance from ring center
|
||||
float ringRadius = length(ringIntersection.xz);
|
||||
// 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 / ringSize) - 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(camPositionWorld, sunPositionWorld);
|
||||
|
||||
// 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);
|
||||
// Sample appropriate ring texture based on viewing direction
|
||||
vec4 ringColor = mix(texture(ringTextureFwrd, texCoord), texture(ringTextureBckwrd, texCoord), lerpFactor);
|
||||
|
||||
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(camPositionWorld, sunPositionWorld);
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
if (t < 1000.0) {
|
||||
shadow = 0.0;
|
||||
}
|
||||
// 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.rgb = vec3(0.0, ringRadius / ringSize, 0.0);
|
||||
}
|
||||
|
||||
#endif // USE_RING_SHADOWS
|
||||
|
||||
if (shadow < 1.0) {
|
||||
frag.color.rgb = vec3(0.0, 1.0, 0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
frag.color.a *= opacity;
|
||||
|
||||
@@ -1232,8 +1232,8 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::No);
|
||||
}
|
||||
|
||||
const glm::mat4 modelViewTransform = glm::mat4(viewTransform * _cachedModelTransform);
|
||||
const glm::mat4 modelViewProjectionTransform =
|
||||
glm::mat4 modelViewTransform = glm::mat4(viewTransform * _cachedModelTransform);
|
||||
glm::mat4 modelViewProjectionTransform =
|
||||
data.camera.sgctInternal.projectionMatrix() * modelViewTransform;
|
||||
|
||||
// Upload the uniform variables
|
||||
@@ -1257,9 +1257,9 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
}
|
||||
|
||||
using namespace layers;
|
||||
const bool nightLayersActive =
|
||||
bool nightLayersActive =
|
||||
!_layerManager.layerGroup(Group::ID::NightLayers).activeLayers().empty();
|
||||
const bool waterLayersActive =
|
||||
bool waterLayersActive =
|
||||
!_layerManager.layerGroup(Group::ID::WaterMasks).activeLayers().empty();
|
||||
|
||||
if (nightLayersActive || waterLayersActive || _performShading) {
|
||||
@@ -1268,44 +1268,76 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
|
||||
const glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0));
|
||||
// @TODO (abock, 2020-04-14); This is just a bandaid for issue #1136. The better
|
||||
// way is to figure out with the uniform is optimized away. I assume that it is
|
||||
// because the shader doesn't get recompiled when the last layer of the night
|
||||
// or water is disabled; so the shader thinks it has to do the calculation, but
|
||||
// there are actually no layers left
|
||||
const glm::vec3 directionToSunObjSpace = glm::vec3(_cachedInverseModelTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0));
|
||||
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_localRenderer.program->setUniform(
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_globalRenderer.program->setUniform(
|
||||
"lightDirectionCameraSpace",
|
||||
-glm::normalize(directionToSunCameraSpace)
|
||||
);
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_globalRenderer.program->setUniform(
|
||||
"lightDirectionObjSpace",
|
||||
-glm::normalize(directionToSunObjSpace)
|
||||
);
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
// Local shader
|
||||
_localRenderer.program->setUniform(
|
||||
"projectionTransform",
|
||||
data.camera.sgctInternal.projectionMatrix()
|
||||
modelViewTransform = glm::mat4(viewTransform * _cachedModelTransform);
|
||||
modelViewProjectionTransform =
|
||||
data.camera.sgctInternal.projectionMatrix() * modelViewTransform;
|
||||
|
||||
|
||||
_globalRenderer.program->setUniform(
|
||||
"lightDirectionWorldSpace",
|
||||
glm::vec3(glm::normalize(directionToLightSource(data.modelTransform.translation, _lightSourceNode)))
|
||||
);
|
||||
|
||||
// Upload the uniform variables
|
||||
_localRenderer.program->setUniform(
|
||||
"modelViewProjectionTransform",
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
|
||||
_localRenderer.program->setUniform("modelViewTransform", modelViewTransform);
|
||||
|
||||
if (_useAccurateNormals && hasHeightLayer) {
|
||||
// Apply an extra scaling to the height if the object is scaled
|
||||
_localRenderer.program->setUniform(
|
||||
"heightScale",
|
||||
static_cast<float>(
|
||||
glm::compMax(data.modelTransform.scale) * data.camera.scaling()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
using namespace layers;
|
||||
nightLayersActive =
|
||||
!_layerManager.layerGroup(Group::ID::NightLayers).activeLayers().empty();
|
||||
waterLayersActive =
|
||||
!_layerManager.layerGroup(Group::ID::WaterMasks).activeLayers().empty();
|
||||
|
||||
if (nightLayersActive || waterLayersActive || _performShading) {
|
||||
const glm::dvec3 directionToSunWorldSpace =
|
||||
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
|
||||
|
||||
const glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0));
|
||||
// @TODO (abock, 2020-04-14); This is just a bandaid for issue #1136. The better
|
||||
// way is to figure out with the uniform is optimized away. I assume that it is
|
||||
// because the shader doesn't get recompiled when the last layer of the night
|
||||
// or water is disabled; so the shader thinks it has to do the calculation, but
|
||||
// there are actually no layers left
|
||||
const glm::vec3 directionToSunObjSpace = glm::vec3(_cachedInverseModelTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0));
|
||||
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_globalRenderer.program->setUniform(
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_localRenderer.program->setUniform(
|
||||
"lightDirectionCameraSpace",
|
||||
-glm::normalize(directionToSunCameraSpace)
|
||||
);
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_localRenderer.program->setUniform(
|
||||
"lightDirectionObjSpace",
|
||||
-glm::normalize(directionToSunObjSpace)
|
||||
);
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
int globalCount = 0;
|
||||
@@ -1517,6 +1549,7 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
|
||||
program.setUniform("textureOffset", _ringsComponent->textureOffset());
|
||||
program.setUniform("sunPositionObj", _ringsComponent->sunPositionObj());
|
||||
program.setUniform("camPositionObj", _ringsComponent->camPositionObj());
|
||||
program.setUniform("ringSize", (float)_ringsComponent->size());
|
||||
}
|
||||
}
|
||||
else if (_shadowMappingProperties.shadowMapping && _shadowComponent) {
|
||||
@@ -1696,8 +1729,8 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
|
||||
}
|
||||
|
||||
program.setUniform("textureOffset", _ringsComponent->textureOffset());
|
||||
program.setUniform("sunPositionObj", glm::vec3(0.0f));
|
||||
program.setUniform("camPositionWorld", data.camera.positionVec3()); // pass camera world position
|
||||
program.setUniform("sunPositionObj", _ringsComponent->sunPositionObj());
|
||||
program.setUniform("camPositionObj", _ringsComponent->camPositionObj());
|
||||
}
|
||||
}
|
||||
else if (_shadowMappingProperties.shadowMapping) {
|
||||
|
||||
Reference in New Issue
Block a user