diff --git a/data/scene/saturn/saturn.mod b/data/scene/saturn/saturn.mod index ed5fd6ee9b..54e79e56d7 100644 --- a/data/scene/saturn/saturn.mod +++ b/data/scene/saturn/saturn.mod @@ -49,6 +49,7 @@ return { Parent = "Saturn", Renderable = { Type = "RenderableRings", + Body = "SATURN BARYCENTER", Frame = "IAU_SATURN", Texture = "textures/saturn_rings.png", Size = { 0.140445100671159, 9.0 }, -- 140445.100671159km diff --git a/modules/base/rendering/renderablerings.cpp b/modules/base/rendering/renderablerings.cpp index ec486fec5f..bc3da200cd 100644 --- a/modules/base/rendering/renderablerings.cpp +++ b/modules/base/rendering/renderablerings.cpp @@ -39,9 +39,11 @@ namespace { const std::string KeySize = "Size"; const std::string KeyTexture = "Texture"; + const std::string KeyBody = "Body"; const std::string KeyFrame = "Frame"; const std::string KeyOrientation = "Orientation"; const std::string KeyOffset = "Offset"; + const std::string KeyNightFactor = "NightFactor"; const std::string KeyTransparency = "Transparency"; } @@ -52,6 +54,7 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) , _texturePath("texture", "Texture") , _size("size", "Size", glm::vec2(1.f, 1.f), glm::vec2(0.f), glm::vec2(1.f, 25.f)) , _offset("offset", "Texture Offset", glm::vec2(0.f, 1.f), glm::vec2(0.f), glm::vec2(1.f)) + , _nightFactor("nightFactor", "Night Factor", 0.33f, 0.f, 1.f) , _transparency("transparency", "Transparency", 0.15f, 0.f, 1.f) , _shader(nullptr) , _texture(nullptr) @@ -60,11 +63,17 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) , _quad(0) , _vertexPositionBuffer(0) , _planeIsDirty(false) + , _hasSunPosition(false) { glm::vec2 size; dictionary.getValue(KeySize, size); _size = size; + if (dictionary.hasKeyAndValue(KeyBody)) { + _body = dictionary.value(KeyBody); + _hasSunPosition = true; + } + if (dictionary.hasKeyAndValue(KeyFrame)) { _frame = dictionary.value(KeyFrame); } @@ -83,6 +92,11 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) _offset = off; } + if (dictionary.hasKeyAndValue(KeyNightFactor)) { + float v = dictionary.value(KeyNightFactor); + _nightFactor = v; + } + if (dictionary.hasKeyAndValue(KeyTransparency)) { float v = dictionary.value(KeyTransparency); _transparency = v; @@ -100,6 +114,8 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) [&](const ghoul::filesystem::File&) { _textureIsDirty = true; } ); + addProperty(_nightFactor); + addProperty(_transparency); setBoundingSphere(_size.value()); @@ -118,6 +134,10 @@ bool RenderableRings::initialize() { ); if (!_shader) return false; + + _shader->setIgnoreUniformLocationError( + ghoul::opengl::ProgramObject::IgnoreError::Yes + ); } glGenVertexArrays(1, &_quad); // generate array @@ -155,6 +175,13 @@ void RenderableRings::render(const RenderData& data) { _shader->setUniform("ModelTransform", glm::mat4(_orientation * _state)); _shader->setUniform("textureOffset", _offset); _shader->setUniform("transparency", _transparency); + + _shader->setUniform("hasSunPosition", _hasSunPosition); + if (_hasSunPosition) { + _shader->setUniform("_nightFactor", _nightFactor); + _shader->setUniform("sunPosition", _sunPosition); + } + setPscUniforms(*_shader.get(), data.camera, data.position); ghoul::opengl::TextureUnit unit; @@ -172,8 +199,9 @@ void RenderableRings::render(const RenderData& data) { } void RenderableRings::update(const UpdateData& data) { - if (_shader->isDirty()) + if (_shader->isDirty()) { _shader->rebuildFromFile(); + } if (_planeIsDirty) { createPlane(); @@ -188,6 +216,18 @@ void RenderableRings::update(const UpdateData& data) { if (!_frame.empty()) { _state = SpiceManager::ref().positionTransformMatrix(_frame, "GALACTIC", data.time); } + + if (!_body.empty()) { + double lt; + _sunPosition = SpiceManager::ref().targetPosition( + "SUN", + _body, + "GALACTIC", + {}, + data.time, + lt + ); + } } void RenderableRings::loadTexture() { diff --git a/modules/base/rendering/renderablerings.h b/modules/base/rendering/renderablerings.h index 2aa9754507..1836404e71 100644 --- a/modules/base/rendering/renderablerings.h +++ b/modules/base/rendering/renderablerings.h @@ -61,6 +61,7 @@ private: properties::StringProperty _texturePath; properties::Vec2Property _size; properties::Vec2Property _offset; + properties::FloatProperty _nightFactor; properties::FloatProperty _transparency; std::unique_ptr _shader; @@ -75,6 +76,10 @@ private: std::string _frame; glm::mat3 _orientation; glm::mat3 _state; + + std::string _body; + glm::vec3 _sunPosition; + bool _hasSunPosition; }; } // namespace openspace diff --git a/modules/base/shaders/rings_fs.glsl b/modules/base/shaders/rings_fs.glsl index e47daded3f..9b12688943 100644 --- a/modules/base/shaders/rings_fs.glsl +++ b/modules/base/shaders/rings_fs.glsl @@ -32,6 +32,10 @@ uniform sampler1D texture1; uniform vec2 textureOffset; uniform float transparency; +uniform bool hasSunPosition; +uniform vec3 sunPosition; +uniform float _nightFactor; + Fragment getFragment() { vec4 position = vs_position; float depth = pscDepth(position); @@ -62,6 +66,25 @@ Fragment getFragment() { diffuse.a = pow(colorValue / (3*transparency), 1); } + if (hasSunPosition) { + // The normal for the one plane depends on whether we are dealing + // with a front facing or back facing fragment + vec3 normal; + // The plane is oriented on the xz plane + // WARNING: This might not be the case for Uranus + if (gl_FrontFacing) { + normal = vec3(0.0, 1.0, 0.0); + } + else { + normal = vec3(0.0, -1.0, 0.0); + } + + // Reduce the color of the fragment by the user factor + // if we are facing away from the Sun + if (dot(sunPosition, normal) < 0) + diffuse.xyz *= _nightFactor; + } + Fragment frag; frag.color = diffuse; frag.depth = depth;