diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 181390083a..3e98be8cc6 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -131,6 +131,7 @@ protected: SceneGraphNode* parent() const noexcept; bool automaticallyUpdatesRenderBin() const noexcept; + bool hasOverrideRenderBin() const noexcept; RenderBin _renderBin = RenderBin::Opaque; @@ -146,6 +147,7 @@ private: SceneGraphNode* _parent = nullptr; const bool _shouldUpdateIfDisabled = false; bool _automaticallyUpdateRenderBin = true; + bool _hasOverrideRenderBin = false; // We only want the SceneGraphNode to be able manipulate the parent, so we don't want // to provide a set method for this. Otherwise, anyone might mess around with our diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index b34ab5247d..2479ca13c0 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -73,12 +73,12 @@ namespace { GL_COLOR_ATTACHMENT2, }; - constexpr std::array UniformNames = { + constexpr std::array UniformNames = { "nLightSources", "lightDirectionsViewSpace", "lightIntensities", "modelViewTransform", "normalTransform", "projectionTransform", "performShading", "ambientIntensity", "diffuseIntensity", "specularIntensity", "performManualDepthTest", "gBufferDepthTexture", - "resolution" + "resolution", "opacity" }; constexpr std::array UniformOpacityNames = { @@ -273,7 +273,7 @@ documentation::Documentation RenderableModel::Documentation() { } RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) + : Renderable(dictionary, { .automaticallyUpdateRenderBin = false }) , _enableAnimation(EnableAnimationInfo, false) , _ambientIntensity(AmbientIntensityInfo, 0.2f, 0.f, 1.f) , _diffuseIntensity(DiffuseIntensityInfo, 1.f, 0.f, 1.f) @@ -781,6 +781,21 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) { false ); + if (hasOverrideRenderBin()) { + // If override render bin is set then use the opacity values as normal + _program->setUniform( + _uniformCache.opacity, + opacity() + ); + } + else { + // Otherwise reset + _program->setUniform( + _uniformCache.opacity, + 1.f + ); + } + _geometry->render(*_program); } else { @@ -832,6 +847,12 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) { glm::vec2(global::windowDelegate->currentDrawBufferResolution()) ); + // Make sure opacity in first pass is always 1 + _program->setUniform( + _uniformCache.opacity, + 1.f + ); + // Render Pass 1 // Render all parts of the model into the new framebuffer without opacity _geometry->render(*_program); @@ -910,17 +931,20 @@ void RenderableModel::update(const UpdateData& data) { ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames); } - // Only render two pass if the model is in any way transparent - const float o = opacity(); - if ((o >= 0.f && o < 1.f) || _geometry->isTransparent()) { - setRenderBin(Renderable::RenderBin::PostDeferredTransparent); - _shouldRenderTwice = true; - } - else { - setRenderBin(_originalRenderBin); - _shouldRenderTwice = false; + if (!hasOverrideRenderBin()) { + // Only render two pass if the model is in any way transparent + const float o = opacity(); + if ((o >= 0.f && o < 1.f) || _geometry->isTransparent()) { + setRenderBin(Renderable::RenderBin::PostDeferredTransparent); + _shouldRenderTwice = true; + } + else { + setRenderBin(_originalRenderBin); + _shouldRenderTwice = false; + } } + if (_geometry->hasAnimation() && !_animationStart.empty()) { double relativeTime; double now = data.time.j2000Seconds(); diff --git a/modules/base/rendering/renderablemodel.h b/modules/base/rendering/renderablemodel.h index be2203f466..11b11e0155 100644 --- a/modules/base/rendering/renderablemodel.h +++ b/modules/base/rendering/renderablemodel.h @@ -106,7 +106,7 @@ private: modelViewTransform, normalTransform, projectionTransform, performShading, ambientIntensity, diffuseIntensity, specularIntensity, performManualDepthTest, gBufferDepthTexture, - resolution) _uniformCache; + resolution, opacity) _uniformCache; std::vector> _lightSources; diff --git a/modules/base/shaders/model_fs.glsl b/modules/base/shaders/model_fs.glsl index 857b365b3c..8b6d2eced5 100644 --- a/modules/base/shaders/model_fs.glsl +++ b/modules/base/shaders/model_fs.glsl @@ -44,6 +44,7 @@ uniform bool has_color_specular; uniform sampler2D texture_diffuse; uniform sampler2D texture_normal; uniform sampler2D texture_specular; +uniform float opacity = 1.0; uniform vec4 color_diffuse; uniform vec4 color_specular; @@ -63,7 +64,7 @@ Fragment getFragment() { frag.gPosition = vs_positionCameraSpace; frag.gNormal = vec4(vs_normalViewSpace, 0.0); frag.disableLDR2HDR = true; - frag.color.a = 1.0; + frag.color.a = opacity; if (performManualDepthTest) { // gl_FragCoord.x goes from 0 to resolution.x and gl_FragCoord.y goes from 0 to @@ -160,6 +161,6 @@ Fragment getFragment() { frag.color.rgb = diffuseAlbedo.rgb; } - frag.color.a = diffuseAlbedo.a; + frag.color.a = diffuseAlbedo.a * opacity; return frag; } diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 8c8c15c4af..aa5309b6eb 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -150,6 +150,7 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary, Settings settings) if (p.renderBinMode.has_value()) { _automaticallyUpdateRenderBin = false; + _hasOverrideRenderBin = true; setRenderBin(codegen::map(*p.renderBinMode)); } @@ -326,4 +327,8 @@ bool Renderable::automaticallyUpdatesRenderBin() const noexcept { return _automaticallyUpdateRenderBin; } +bool Renderable::hasOverrideRenderBin() const noexcept { + return _hasOverrideRenderBin; +} + } // namespace openspace