diff --git a/apps/OpenSpace-MinVR/main.cpp b/apps/OpenSpace-MinVR/main.cpp index c2d857cc7c..5931027dda 100644 --- a/apps/OpenSpace-MinVR/main.cpp +++ b/apps/OpenSpace-MinVR/main.cpp @@ -200,7 +200,6 @@ void Handler::onVREvent(const VRDataIndex& eventData) { if (button == MouseButton::Right && action == MouseAction::Press) { windowingGlobals.mouseButtons |= 1 << 2; } - using KM = KeyModifier; KM mod = KM::NoModifier; mod |= keyboardState.modifierShift ? KM::Shift : KM::NoModifier; diff --git a/data/assets/default.scene b/data/assets/default.scene index c6d3e2523c..46e59bf846 100644 --- a/data/assets/default.scene +++ b/data/assets/default.scene @@ -10,6 +10,11 @@ asset.onInitialize(function () openspace.globebrowsing.goToGeo("Earth", 58.5877, 16.1924, 20000000) openspace.markInterestingNodes({ "Earth", "Mars", "Moon", "Sun" }) + + -- HDR / Image options: + openspace.setPropertyValueSingle('RenderEngine.Gamma', 0.95); + openspace.setPropertyValueSingle('RenderEngine.HDRExposure', 3.7); + openspace.setPropertyValueSingle('RenderEngine.Saturation', 1.0); end) asset.onDeinitialize(function () diff --git a/data/assets/scene/digitaluniverse/milkyway.asset b/data/assets/scene/digitaluniverse/milkyway.asset index dff01194a4..83ee5c6f92 100644 --- a/data/assets/scene/digitaluniverse/milkyway.asset +++ b/data/assets/scene/digitaluniverse/milkyway.asset @@ -40,7 +40,8 @@ local sphere = { Orientation = "Inside", UseAdditiveBlending = true, MirrorTexture = true, - FadeOutThreshold = 0.025 + FadeOutThreshold = 0.025, + Background = true }, GUI = { Name = "Milky Way Sphere", diff --git a/data/assets/scene/solarsystem/planets/earth/atmosphere.asset b/data/assets/scene/solarsystem/planets/earth/atmosphere.asset index 641e3a0759..7b3197b84f 100644 --- a/data/assets/scene/solarsystem/planets/earth/atmosphere.asset +++ b/data/assets/scene/solarsystem/planets/earth/atmosphere.asset @@ -16,6 +16,7 @@ local Atmosphere = { PlanetRadius = 6377.0, PlanetAverageGroundReflectance = 0.1, GroundRadianceEmittion = 0.6, + SunIntensity = 6.9, Rayleigh = { Coefficients = { -- Wavelengths are given in 10^-9m diff --git a/data/assets/scene/solarsystem/planets/mars/atmosphere.asset b/data/assets/scene/solarsystem/planets/mars/atmosphere.asset index 2850e528ca..bffdc14094 100644 --- a/data/assets/scene/solarsystem/planets/mars/atmosphere.asset +++ b/data/assets/scene/solarsystem/planets/mars/atmosphere.asset @@ -16,6 +16,8 @@ local Atmosphere = { PlanetRadius = 3386.190, PlanetAverageGroundReflectance = 0.1, GroundRadianceEmittion = 0.37, + SunIntensity = 6.7, + MieScatteringExtinctionPropCoefficient = 0.23862, Rayleigh = { Coefficients = { -- Wavelengths are given in 10^-9m diff --git a/data/assets/scene/solarsystem/sun/glare.asset b/data/assets/scene/solarsystem/sun/glare.asset index c2c2e3a78f..8d13f5fa9a 100644 --- a/data/assets/scene/solarsystem/sun/glare.asset +++ b/data/assets/scene/solarsystem/sun/glare.asset @@ -15,7 +15,8 @@ local SunGlare = { Billboard = true, Texture = textures .. "/halo.png", BlendMode = "Additive", - RenderableType = "Transparent" + Opacity = 0.65, + RenderableType = "Transparency" }, Transform = { Translation = { diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h index b160cfcedb..aa99d10ad1 100644 --- a/include/openspace/rendering/abufferrenderer.h +++ b/include/openspace/rendering/abufferrenderer.h @@ -62,11 +62,28 @@ public: void setResolution(glm::ivec2 res) override; void setNAaSamples(int nAaSamples) override; + void setBlurrinessLevel(int level) override; void setHDRExposure(float hdrExposure) override; - void setHDRBackground(float hdrBackground) override; void setGamma(float gamma) override; + void setMaxWhite(float maxWhite) override; + void setToneMapOperator(int tmOp) override; + void setBloomThreMin(float minV) override; + void setBloomThreMax(float maxV) override; + void setBloomOrigFactor(float origFactor) override; + void setBloomNewFactor(float newFactor) override; + void setKey(float key) override; + void setYwhite(float white) override; + void setTmoSaturation(float sat) override; + void setHue(float hue) override; + void setValue(float value) override; + void setSaturation(float sat) override; + void setLightness(float lightness) override; + void setColorSpace(unsigned int colorspace) override; + + + void enableBloom(bool enable) override; + void enableHistogram(bool enable) override; - float hdrBackground() const override; int nAaSamples() const override; const std::vector& mSSAPattern() const override; @@ -131,11 +148,29 @@ private: GLuint _fragmentTexture; GLuint _vertexPositionBuffer; int _nAaSamples; + int _blurrinessLevel = 1; float _hdrExposure = 0.4f; float _hdrBackground = 2.8f; float _gamma = 2.2f; + float _maxWhite = 1.f; float _blackoutFactor; + bool _bloomEnabled = false; + float _bloomThresholdMin = 0.0; + float _bloomThresholdMax = 1.0; + float _bloomOrigFactor = 1.0; + float _bloomNewFactor = 1.0; + int _toneMapOperator = 0; + bool _histogramEnabled = false; + int _numberOfBins = 1024; // JCC TODO: Add a parameter control for this. + float _tmoKey = 0.18f; + float _tmoYwhite = 1e6f; + float _tmoSaturation = 1.0f; + float _hue = 1.f; + float _saturation = 1.f; + float _value = 1.f; + float _lightness = 1.f; + unsigned int _colorSpace = 1; std::vector _mSAAPattern; diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index cf954596d1..a86fbe2d0e 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -26,6 +26,7 @@ #define __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__ #include +#include #include #include @@ -58,6 +59,56 @@ struct UpdateStructures; class FramebufferRenderer : public Renderer, public RaycasterListener, public DeferredcasterListener { +private: + inline static const GLenum ColorAttachment0Array[1] = { + GL_COLOR_ATTACHMENT0 + }; + + inline static const GLenum ColorAttachment1Array[1] = { + GL_COLOR_ATTACHMENT1 + }; + + inline static const GLenum ColorAttachment01Array[2] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1 + }; + + inline static const GLenum ColorAttachment03Array[2] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT3 + }; + + inline static const GLenum ColorAttachment012Array[3] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2 + }; + + inline static const GLenum ColorAttachment0123Array[4] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3 + }; + + typedef struct { + GLuint _colorTexture; + GLuint _positionTexture; + GLuint _normalTexture; + GLuint _depthTexture; + GLuint _framebuffer; + } GBuffers; + + typedef struct { + GLuint framebuffer; + GLuint colorTexture[2]; + } PingPongBuffers; + + typedef struct { + GLuint _hdrFilteringFramebuffer; + GLuint _hdrFilteringTexture; + } HDRBuffers; + public: typedef std::map< VolumeRaycaster*, @@ -76,23 +127,22 @@ public: void updateResolution(); void updateRaycastData(); void updateDeferredcastData(); - void updateHDRData(); - void updateMSAASamplingPattern(); - + void updateHDRAndFiltering(); + void setResolution(glm::ivec2 res) override; void setNAaSamples(int nAaSamples) override; void setHDRExposure(float hdrExposure) override; - void setHDRBackground(float hdrBackground) override; void setGamma(float gamma) override; - - float hdrBackground() const override; + void setHue(float hue) override; + void setValue(float value) override; + void setSaturation(float sat) override; + int nAaSamples() const override; - const std::vector& mSSAPattern() const override; - + void disableHDR(bool disable) override; + void update() override; void performRaycasterTasks(const std::vector& tasks); - void performDeferredTasks(const std::vector& tasks, - float blackoutFactor); + void performDeferredTasks(const std::vector& tasks); void render(Scene* scene, Camera* camera, float blackoutFactor) override; /** @@ -106,6 +156,10 @@ public: virtual void deferredcastersChanged(Deferredcaster& deferredcaster, DeferredcasterListener::IsAttached isAttached) override; +private: + void resolveMSAA(float blackoutFactor); + void applyTMO(float blackoutFactor); + private: std::map _raycastData; RaycasterProgObjMap _exitPrograms; @@ -114,23 +168,28 @@ private: std::map _deferredcastData; DeferredcasterProgObjMap _deferredcastPrograms; - std::unique_ptr _hdrBackGroundProgram; + + std::unique_ptr _hdrFilteringProgram; + std::unique_ptr _tmoProgram; std::unique_ptr _resolveProgram; UniformCache(mainColorTexture, blackoutFactor, nAaSamples) _uniformCache; + + UniformCache(hdrFeedingTexture, blackoutFactor, hdrExposure, gamma, + Hue, Saturation, Value, nAaSamples) _hdrUniformCache; + GLint _defaultFBO; GLuint _screenQuad; GLuint _vertexPositionBuffer; - GLuint _mainColorTexture; - GLuint _mainPositionTexture; - GLuint _mainNormalTexture; - GLuint _mainDepthTexture; GLuint _exitColorTexture; - GLuint _mainFramebuffer; GLuint _exitDepthTexture; GLuint _exitFramebuffer; - GLuint _deferredFramebuffer; - GLuint _deferredColorTexture; + + GBuffers _gBuffers; + PingPongBuffers _pingPongBuffers; + HDRBuffers _hdrBuffers; + + unsigned int _pingPongIndex = 0u; bool _dirtyDeferredcastData; bool _dirtyRaycastData; @@ -139,12 +198,15 @@ private: glm::ivec2 _resolution = glm::ivec2(0); int _nAaSamples; - float _hdrExposure = 0.4f; - float _hdrBackground = 2.8f; - float _gamma = 2.2f; - - std::vector _mSAAPattern; - + bool _disableHDR = false; + + float _hdrExposure = 3.7f; + float _gamma = 0.95f; + float _maxWhite = 5.0f; + float _hue = 1.f; + float _saturation = 1.f; + float _value = 1.f; + ghoul::Dictionary _rendererData; }; diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 30b820a24c..0e6f0896ee 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -96,6 +96,7 @@ protected: properties::FloatProperty _opacity; properties::StringProperty _renderableType; + void setRenderBinFromOpacity(); void registerUpdateRenderBinFromOpacity(); private: diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 3ab7b9baaf..56caf5a961 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -34,6 +34,8 @@ #include #include +#include + namespace ghoul { class Dictionary; class SharedMemory; @@ -206,15 +208,21 @@ private: properties::FloatProperty _globalBlackOutFactor; properties::IntProperty _nAaSamples; + + properties::BoolProperty _disableHDRPipeline; properties::FloatProperty _hdrExposure; - properties::FloatProperty _hdrBackground; properties::FloatProperty _gamma; + + properties::FloatProperty _hue; + properties::FloatProperty _saturation; + properties::FloatProperty _value; + properties::FloatProperty _horizFieldOfView; properties::Vec3Property _globalRotation; properties::Vec3Property _screenSpaceRotation; properties::Vec3Property _masterRotation; - + uint64_t _frameNumber = 0; std::vector _programs; diff --git a/include/openspace/rendering/renderer.h b/include/openspace/rendering/renderer.h index 6afcc4cd14..3520a02195 100644 --- a/include/openspace/rendering/renderer.h +++ b/include/openspace/rendering/renderer.h @@ -51,12 +51,12 @@ public: virtual void setResolution(glm::ivec2 res) = 0; virtual void setNAaSamples(int nAaSamples) = 0; virtual void setHDRExposure(float hdrExposure) = 0; - virtual void setHDRBackground(float hdrBackground) = 0; virtual void setGamma(float gamma) = 0; - - virtual float hdrBackground() const = 0; + virtual void setHue(float hue) = 0; + virtual void setValue(float value) = 0; + virtual void setSaturation(float sat) = 0; virtual int nAaSamples() const = 0; - virtual const std::vector& mSSAPattern() const = 0; + virtual void disableHDR(bool disable) = 0; /** * Set raycasting uniforms on the program object, and setup raycasting. diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 9a7802b815..3e5dec47ad 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -147,7 +147,7 @@ AtmosphereDeferredcaster::AtmosphereDeferredcaster() , _ozoneHeightScale(0.f) , _mieHeightScale(0.f) , _miePhaseConstant(0.f) - , _sunRadianceIntensity(50.0f) + , _sunRadianceIntensity(5.f) , _rayleighScatteringCoeff(glm::vec3(0.f)) , _ozoneExtinctionCoeff(glm::vec3(0.f)) , _mieScatteringCoeff(glm::vec3(0.f)) diff --git a/modules/atmosphere/rendering/renderableatmosphere.cpp b/modules/atmosphere/rendering/renderableatmosphere.cpp index 159d9bb0f2..fd931c251f 100644 --- a/modules/atmosphere/rendering/renderableatmosphere.cpp +++ b/modules/atmosphere/rendering/renderableatmosphere.cpp @@ -265,7 +265,8 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) , _ozoneHeightScale(0.f) , _mieHeightScale(0.f) , _miePhaseConstant(0.f) - , _sunRadianceIntensity(50.f) + , _sunRadianceIntensity(5.f) + , _mieScattExtPropCoefProp(1.f) , _mieExtinctionCoeff(glm::vec3(0.f)) , _rayleighScatteringCoeff(glm::vec3(0.f)) , _ozoneExtinctionCoeff(glm::vec3(0.f)) @@ -403,6 +404,17 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) "Atmosphere Effects. Disabling atmosphere effects for this planet." ); } + + if (atmosphereDictionary.hasKey(SunIntensityInfo.identifier)) { + _sunRadianceIntensity = + atmosphereDictionary.value(SunIntensityInfo.identifier); + } + + if (atmosphereDictionary.hasKey(MieScatteringExtinctionPropCoeffInfo.identifier)) { + _mieScattExtPropCoefProp = atmosphereDictionary.value( + MieScatteringExtinctionPropCoeffInfo.identifier + ); + } if (!atmosphereDictionary.getValue( GroundRadianceEmittioninfo.identifier, @@ -628,8 +640,10 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) _mieScatteringCoeffZP.onChange(updateAtmosphere); addProperty(_mieScatteringCoeffZP); - _mieScatteringExtinctionPropCoefficientP = + _mieScatteringExtinctionPropCoefficientP = + _mieScattExtPropCoefProp != 1.f ? _mieScattExtPropCoefProp : _mieScatteringCoeff.x / _mieExtinctionCoeff.x; + _mieScatteringExtinctionPropCoefficientP.onChange(updateAtmosphere); addProperty(_mieScatteringExtinctionPropCoefficientP); diff --git a/modules/atmosphere/rendering/renderableatmosphere.h b/modules/atmosphere/rendering/renderableatmosphere.h index d86f068ca7..202933b593 100644 --- a/modules/atmosphere/rendering/renderableatmosphere.h +++ b/modules/atmosphere/rendering/renderableatmosphere.h @@ -122,6 +122,7 @@ private: float _mieHeightScale; float _miePhaseConstant; float _sunRadianceIntensity; + float _mieScattExtPropCoefProp; glm::vec3 _mieExtinctionCoeff; glm::vec3 _rayleighScatteringCoeff; diff --git a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl index dbcb6e2a40..f566b9055b 100644 --- a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl +++ b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl @@ -61,23 +61,14 @@ #include "floatoperations.glsl" -#include "hdr.glsl" #include "atmosphere_common.glsl" out vec4 renderTarget; in vec3 interpolatedNDCPos; uniform int nAaSamples; -uniform double msaaSamplePatter[48]; uniform int cullAtmosphere; -// The following uniforms are -// set into the current Renderer -// Background exposure hack -uniform float backgroundConstant; -uniform bool firstPaint; -uniform float atmExposure; - uniform sampler2D irradianceTexture; uniform sampler3D inscatterTexture; uniform sampler2DMS mainPositionTexture; @@ -92,8 +83,6 @@ uniform dmat4 dSgctProjectionToModelTransformMatrix; uniform dvec4 dCamPosObj; uniform dvec3 sunDirectionObj; -uniform float blackoutFactor; - /******************************************************************************* ***** ALL CALCULATIONS FOR ECLIPSE ARE IN METERS AND IN WORLD SPACE SYSTEM **** *******************************************************************************/ @@ -244,13 +233,6 @@ bool dAtmosphereIntersection(const dvec3 planetPosition, const dRay ray, const d void dCalculateRayRenderableGlobe(in int mssaSample, out dRay ray, out dvec4 planetPositionObjectCoords, out dvec4 cameraPositionInObject) { - // ====================================== - // ======= Avoiding Some Matrices ======= - - // Compute positions and directions in object space. - dvec2 samplePos = dvec2(msaaSamplePatter[mssaSample], - msaaSamplePatter[mssaSample+1]); - dvec4 clipCoords = dvec4(interpolatedNDCPos.xy, 1.0, 1.0); // Clip to Object Coords @@ -317,7 +299,7 @@ vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor // through the atmosphere. If this ray hits something inside the atmosphere, // we will subtract the attenuated scattering light from that path in the // current path. - vec4 inscatterRadiance = max(texture4D(inscatterTexture, r, mu, muSun, nu), 0.0); + vec4 inscatterRadiance = max(texture4D(inscatterTexture, r, mu, muSun, nu), 0.0); // After removing the initial path from camera pos to top of atmosphere (for an // observer in the space) we test if the light ray is hitting the atmosphere @@ -365,7 +347,7 @@ vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor if (abs(mu - muHorizon) < INTERPOLATION_EPS) { // We want an interpolation value close to 1/2, so the // contribution of each radiance value is almost the same - // or it has a havey weight if from above or below horizon + // or it has a heavy weight if from above or below horizon float interpolationValue = ((mu - muHorizon) + INTERPOLATION_EPS) / (2.0f * INTERPOLATION_EPS); //float t2 = t * t; @@ -426,10 +408,14 @@ vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor // we can change it on the fly with no precomputations) // return radiance * sunRadiance; vec3 finalScatteringRadiance = radiance * sunIntensity; + if (groundHit) { return finalScatteringRadiance; } else { - return ((r-Rg) * invRtMinusRg)*spaceColor.rgb * backgroundConstant + finalScatteringRadiance; + //return ((r-Rg) * invRtMinusRg)*spaceColor.rgb + finalScatteringRadiance; + return attenuation * spaceColor.rgb + finalScatteringRadiance; + // return attenuation * spaceColor.rgb + + // (vec3(1.0) - attenuation) * finalScatteringRadiance; } } @@ -536,9 +522,10 @@ vec3 sunColor(const vec3 x, const float t, const vec3 v, const vec3 s, const flo vec3(0.0f) : transmittanceLUT(r, mu)) : vec3(1.0f); // JCC: Change this function to a impostor texture with gaussian decay color weighted // by tge sunRadiance, transmittance and irradianceColor (11/03/2017) - float sunFinalColor = step(cos(M_PI / 650.0f), dot(v, s)) * sunRadiance * (1.0f- irradianceFactor); + float sunFinalColor = smoothstep(cos(M_PI / 500.0f), cos(M_PI / 900.0f), dot(v, s)) * + sunRadiance * (1.0f - irradianceFactor); - return transmittance * sunFinalColor; + return transmittance * sunFinalColor; } void main() { @@ -562,16 +549,9 @@ void main() { } nSamples = complex ? nAaSamples / 2 : 1; - // Performance variables: - //float Rt2 = Rt * Rt; // in Km - //float Rg2 = Rg * Rg; // in Km - - for (int i = 0; i < nSamples; i++) { // Color from G-Buffer - //vec4 color = texelFetch(mainColorTexture, fragCoords, i); vec4 color = colorArray[i]; - // Ray in object space dRay ray; dvec4 planetPositionObjectCoords = dvec4(0.0); @@ -635,9 +615,9 @@ void main() { pixelDepth *= 0.001; positionObjectsCoords.xyz *= 0.001; - if (position.xyz != vec3(0.0) && (pixelDepth < offset)) { + if (dot(position.xyz, vec3(1.0)) > 0.0 && (pixelDepth < offset)) { // ATM Occluded - Something in fron of ATM. - atmosphereFinalColor += vec4(HDR(color.xyz * backgroundConstant, atmExposure), color.a); + atmosphereFinalColor += color; } else { // Following paper nomenclature double t = offset; @@ -686,35 +666,26 @@ void main() { } // Final Color of ATM plus terrain: - vec4 finalRadiance = vec4(HDR(inscatterColor + groundColorV + sunColorV, atmExposure), 1.0); - + vec4 finalRadiance = vec4(inscatterColor + groundColorV + sunColorV, 1.0); + atmosphereFinalColor += finalRadiance; } } else { // no intersection - atmosphereFinalColor += vec4(HDR(color.xyz * backgroundConstant, atmExposure), color.a); + // Buffer color + atmosphereFinalColor += color; } } - renderTarget = atmosphereFinalColor / float(nSamples); - renderTarget.a *= blackoutFactor; - // if (complex) - // renderTarget = vec4(1.0, 0.0, 0.0, 1.0); + renderTarget = atmosphereFinalColor / float(nSamples); } else { // culling - if (firstPaint) { - vec4 bColor = vec4(0.0f); - for (int f = 0; f < nAaSamples; f++) { - bColor += texelFetch(mainColorTexture, fragCoords, f); - } - bColor /= float(nAaSamples); - renderTarget = vec4(HDR(bColor.xyz * backgroundConstant, atmExposure), bColor.a * blackoutFactor); - } - else { - discard; + vec4 bColor = vec4(0.0f); + for (int f = 0; f < nAaSamples; f++) { + bColor += texelFetch(mainColorTexture, fragCoords, f); } - //renderTarget = vec4(1.0, 0.0, 0.0, 1.0); - + bColor /= float(nAaSamples); + renderTarget = bColor; } } diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 277c9ccd0a..922e040a7f 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -127,7 +127,7 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) _blendMode.onChange([&]() { switch (_blendMode) { case BlendModeNormal: - setRenderBin(Renderable::RenderBin::Opaque); + setRenderBinFromOpacity(); break; case BlendModeAdditive: setRenderBin(Renderable::RenderBin::Transparent); @@ -137,6 +137,12 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) } }); + _opacity.onChange([&]() { + if (_blendMode == BlendModeNormal) { + setRenderBinFromOpacity(); + } + }); + if (dictionary.hasKey(BlendModeInfo.identifier)) { const std::string v = dictionary.value(BlendModeInfo.identifier); if (v == "Normal") { diff --git a/modules/base/rendering/renderableplane.h b/modules/base/rendering/renderableplane.h index 184d3f637a..a8be7ebe90 100644 --- a/modules/base/rendering/renderableplane.h +++ b/modules/base/rendering/renderableplane.h @@ -67,12 +67,14 @@ protected: virtual void bindTexture(); virtual void unbindTexture(); +protected: + properties::OptionProperty _blendMode; + private: void createPlane(); properties::BoolProperty _billboard; properties::FloatProperty _size; - properties::OptionProperty _blendMode; ghoul::opengl::ProgramObject* _shader = nullptr; diff --git a/modules/base/rendering/renderableplaneimagelocal.cpp b/modules/base/rendering/renderableplaneimagelocal.cpp index 170282cf89..a7ea7baf1d 100644 --- a/modules/base/rendering/renderableplaneimagelocal.cpp +++ b/modules/base/rendering/renderableplaneimagelocal.cpp @@ -85,6 +85,8 @@ RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& di "RenderablePlaneImageLocal" ); + addProperty(_blendMode); + _texturePath = absPath(dictionary.value(TextureInfo.identifier)); _textureFile = std::make_unique(_texturePath); diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 2fff2bc6a9..ef15ccba28 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -178,8 +178,9 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary) properties::OptionProperty::DisplayType::Dropdown ) { + + setRenderBin(RenderBin::Overlay); addProperty(_opacity); - registerUpdateRenderBinFromOpacity(); _translation = Translation::createFromDictionary( dictionary.value(KeyTranslation) @@ -289,7 +290,7 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) { if (usingFramebufferRenderer) { glDepthMask(false); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); } const bool renderLines = (_renderingModes == RenderingModeLines) | diff --git a/modules/base/rendering/renderabletrailorbit.cpp b/modules/base/rendering/renderabletrailorbit.cpp index f8a306a6d2..f92385d35f 100644 --- a/modules/base/rendering/renderabletrailorbit.cpp +++ b/modules/base/rendering/renderabletrailorbit.cpp @@ -100,8 +100,8 @@ namespace { constexpr openspace::properties::Property::PropertyInfo RenderableTypeInfo = { "RenderableType", "RenderableType", - "This value specifies if the plane should be rendered in the Background," - "Opaque, Transparent, or Overlay rendering step." + "This value specifies if the orbit should be rendered in the Background," + "Opaque, Transparent, or Overlay rendering step. Default is Transparent." }; } // namespace @@ -192,7 +192,7 @@ RenderableTrailOrbit::RenderableTrailOrbit(const ghoul::Dictionary& dictionary) } } else { - setRenderBin(Renderable::RenderBin::Opaque); + setRenderBin(Renderable::RenderBin::Overlay); } } diff --git a/modules/base/shaders/renderabletrail_fs.glsl b/modules/base/shaders/renderabletrail_fs.glsl index 9266fd2978..4482761a7e 100644 --- a/modules/base/shaders/renderabletrail_fs.glsl +++ b/modules/base/shaders/renderabletrail_fs.glsl @@ -46,8 +46,6 @@ Fragment getFragment() { frag.depth = vs_positionScreenSpace.w; frag.blend = BLEND_MODE_ADDITIVE; - vec4 depthCorrection = vec4(0.0, 0.0, 100.0, 0.0); - if (renderPhase == RenderPhasePoints) { // Use the length of the vector (dot(circCoord, circCoord)) as factor in the // smoothstep to gradually decrease the alpha on the edges of the point @@ -60,13 +58,9 @@ Fragment getFragment() { } frag.color.a = transparencyCorrection; - } + } - - // G-Buffer - // JCC: The depthCorrection here is a temporary tweak - // to fix precision problems. - frag.gPosition = vs_gPosition + depthCorrection; + frag.gPosition = vs_gPosition; // There is no normal here frag.gNormal = vec4(0.0, 0.0, -1.0, 1.0); diff --git a/modules/base/translation/timelinetranslation.h b/modules/base/translation/timelinetranslation.h index 0d528d36a6..304f1654b7 100644 --- a/modules/base/translation/timelinetranslation.h +++ b/modules/base/translation/timelinetranslation.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2019 * + * Copyright (c) 2014-2018 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * diff --git a/shaders/fragment.glsl b/shaders/fragment.glsl index 6e5c67a9e0..95efdb25ab 100644 --- a/shaders/fragment.glsl +++ b/shaders/fragment.glsl @@ -35,6 +35,7 @@ struct Fragment { float depth; uint blend; bool forceFboRendering; + bool disableLDR2HDR; }; #endif diff --git a/shaders/framebuffer/hdrAndFiltering.frag b/shaders/framebuffer/hdrAndFiltering.frag new file mode 100644 index 0000000000..cd943e2e14 --- /dev/null +++ b/shaders/framebuffer/hdrAndFiltering.frag @@ -0,0 +1,69 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2018 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +#include "hdr.glsl" + +#define HSV_COLOR 0u +#define HSL_COLOR 1u + +layout (location = 0) out vec4 finalColor; + +uniform float hdrExposure; +uniform float blackoutFactor; +uniform float gamma; +uniform float Hue; +uniform float Saturation; +uniform float Value; +uniform float Lightness; +uniform int nAaSamples; + +uniform sampler2DMS hdrFeedingTexture; + +in vec2 texCoord; + +void main() { + vec4 color = vec4(0.0); + + // Resolving... + for (int i = 0; i < nAaSamples; i++) { + color += texelFetch(hdrFeedingTexture, ivec2(gl_FragCoord), i); + } + + color /= nAaSamples; + color.rgb *= blackoutFactor; + + // Applies TMO + vec3 tColor = toneMappingOperator(color.rgb, hdrExposure); + + // Color control + vec3 hsvColor = rgb2hsv(tColor); + hsvColor.x = (hsvColor.x * Hue) > 360.f ? 360.f : (hsvColor.x * Hue); + hsvColor.y = (hsvColor.y * Saturation) > 1.f ? 1.f : (hsvColor.y * Saturation); + hsvColor.z = (hsvColor.z * Value) > 1.f ? 1.f : (hsvColor.z * Value); + + // Gamma Correction + finalColor = vec4(gammaCorrection(hsv2rgb(hsvColor), gamma), color.a); +} \ No newline at end of file diff --git a/shaders/framebuffer/hdrAndFiltering.vert b/shaders/framebuffer/hdrAndFiltering.vert new file mode 100644 index 0000000000..06506ba824 --- /dev/null +++ b/shaders/framebuffer/hdrAndFiltering.vert @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2018 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec4 position; +out vec2 texCoord; + +void main() { + texCoord = 0.5 + position.xy * 0.5; + gl_Position = position; +} diff --git a/shaders/framebuffer/renderframebuffer.frag b/shaders/framebuffer/renderframebuffer.frag index 045653eda3..e7e18698b5 100644 --- a/shaders/framebuffer/renderframebuffer.frag +++ b/shaders/framebuffer/renderframebuffer.frag @@ -25,14 +25,32 @@ #include "floatoperations.glsl" #include <#{fragmentPath}> +#define exposure #{rendererData.hdrExposure} +#define disableHDRPipeline #{rendererData.disableHDR} +#define DeltaError 0.013f +#define MaxValueColorBuffer 1E10 + layout(location = 0) out vec4 _out_color_; layout(location = 1) out vec4 gPosition; layout(location = 2) out vec4 gNormal; +layout(location = 3) out vec4 filterBuffer; void main() { - Fragment f = getFragment(); - _out_color_ = f.color; - gPosition = f.gPosition; - gNormal = f.gNormal; - gl_FragDepth = normalizeFloat(f.depth); + Fragment f = getFragment(); + + // Color is already in HDR space + if (f.disableLDR2HDR || (disableHDRPipeline == 1)) { + _out_color_ = f.color; + } else { + _out_color_ = vec4((log2(vec3(1.0) - (f.color.rgb - vec3(DeltaError)))/(-exposure)), f.color.a); + } + + _out_color_.x = isnan(_out_color_.x) ? MaxValueColorBuffer : _out_color_.x; + _out_color_.y = isnan(_out_color_.y) ? MaxValueColorBuffer : _out_color_.y; + _out_color_.z = isnan(_out_color_.z) ? MaxValueColorBuffer : _out_color_.z; + + gPosition = f.gPosition; + gNormal = f.gNormal; + + gl_FragDepth = normalizeFloat(f.depth); } diff --git a/shaders/framebuffer/resolveframebuffer.frag b/shaders/framebuffer/resolveframebuffer.frag index e3ff098396..39f2946dec 100644 --- a/shaders/framebuffer/resolveframebuffer.frag +++ b/shaders/framebuffer/resolveframebuffer.frag @@ -31,13 +31,13 @@ uniform int nAaSamples; uniform sampler2DMS mainColorTexture; void main() { - vec4 color = vec4(0.0); - for (int i = 0; i < nAaSamples; i++) { - color += texelFetch(mainColorTexture, ivec2(gl_FragCoord), i); - } + vec4 color = vec4(0.0); + for (int i = 0; i < nAaSamples; i++) { + color += texelFetch(mainColorTexture, ivec2(gl_FragCoord), i); + } - color /= nAaSamples; - color.rgb *= blackoutFactor; + color /= nAaSamples; + color.rgb *= blackoutFactor; - finalColor = vec4(color.rgb, 1.0); + finalColor = vec4(color.rgb, 1.0); } diff --git a/shaders/framebuffer/resolveframebuffer.vert b/shaders/framebuffer/resolveframebuffer.vert index ed5a92fde4..9167d4c640 100644 --- a/shaders/framebuffer/resolveframebuffer.vert +++ b/shaders/framebuffer/resolveframebuffer.vert @@ -26,14 +26,6 @@ in vec4 position; -// out vec2 texCoord; -// out vec3 vPosition; -// out vec4 worldPosition; - void main() { gl_Position = position; - // texCoord = 0.5 + position.xy * 0.5; - - // vPosition = position.xyz; - // worldPosition = position; } diff --git a/shaders/hdr.glsl b/shaders/hdr.glsl index 9c6dc62fae..033f805b48 100644 --- a/shaders/hdr.glsl +++ b/shaders/hdr.glsl @@ -21,93 +21,142 @@ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ - -uniform float gamma; -vec3 exponentialToneMapping(vec3 color, float exposure) { +const float HCV_EPSILON = 1e-7; +const float HSL_EPSILON = 1e-7; +const float HCY_EPSILON = 1e-7; + +// White given by D65 +const mat3 RGB2XYZ = mat3( + vec3(0.4124, 0.2126, 0.0193), + vec3(0.3576, 0.7152, 0.1192), + vec3(0.1805, 0.0722, 0.9505) + ); + +const mat3 XYZ2RGB = mat3( + vec3(3.2406, -0.9689, 0.0557), + vec3(-1.5372, 1.8758, -0.2040), + vec3(-0.4986, 0.0415, 1.0570) + ); + +// Gamma correction for linear RGB to sRGB +// See wiki: https://en.wikipedia.org/wiki/SRGB#The_sRGB_transfer_function_.28.22gamma.22.29 +const float gammaF(const float u) { + if (u < 0.0031308) { + return 12.92 * u; + } else { + return 1.055 * pow(u, 1.0/2.4) - 0.055; + } +} + +float invgammaF(const float u) { + if (u < 0.04045) { + return u / 12.92; + } else { + return pow((u+0.055)/1.055, 2.4); + } +} + +vec3 rgbToSRGB(const vec3 rgb) { + return vec3(gammaF(rgb.r), gammaF(rgb.g), gammaF(rgb.b)); +} + +vec3 srgbToRGB(const vec3 srgb) { + return vec3(invgammaF(srgb.r), invgammaF(srgb.g), invgammaF(srgb.b)); +} + +vec3 srgbToXYZ(const vec3 srgb) { + //return RGB2XYZ * srgb; + vec3 rgb = srgbToRGB(srgb); + return RGB2XYZ * rgb; +} + +vec3 XYZToSRGB(const vec3 XYZ) { + vec3 rgb = XYZ2RGB * XYZ; + return rgbToSRGB(rgb); +} + +// HSV code taken from http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl. +vec3 rgb2hsv(const vec3 c) +{ + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); + vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +// All components are in the range [0…1], including hue. +vec3 hsv2rgb(const vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +// Code to convert from rgb to hsl is licensed by: +/* +GLSL Color Space Utility Functions +(c) 2015 tobspr +------------------------------------------------------------------------------- +The MIT License (MIT) +Copyright (c) 2015 + +See top of the file for full license terms. +*/ + +// Converts from pure Hue to linear RGB +vec3 hue2rgb(float hue) +{ + float R = abs(hue * 6 - 3) - 1; + float G = 2 - abs(hue * 6 - 2); + float B = 2 - abs(hue * 6 - 4); + return clamp(vec3(R,G,B), 0, 1); +} +// Converts a value from linear RGB to HCV (Hue, Chroma, Value) +vec3 rgb2hcv(vec3 rgb) +{ + // Based on work by Sam Hocevar and Emil Persson + vec4 P = (rgb.g < rgb.b) ? vec4(rgb.bg, -1.0, 2.0/3.0) : vec4(rgb.gb, 0.0, -1.0/3.0); + vec4 Q = (rgb.r < P.x) ? vec4(P.xyw, rgb.r) : vec4(rgb.r, P.yzx); + float C = Q.x - min(Q.w, Q.y); + float H = abs((Q.w - Q.y) / (6 * C + HCV_EPSILON) + Q.z); + return vec3(H, C, Q.x); +} + +// Converts from HSL to linear RGB +vec3 hsl2rgb(vec3 hsl) +{ + vec3 rgb = hue2rgb(hsl.x); + float C = (1 - abs(2 * hsl.z - 1)) * hsl.y; + return (rgb - 0.5) * C + hsl.z; +} + +// Converts from linear rgb to HSL +vec3 rgb2hsl(vec3 rgb) +{ + vec3 HCV = rgb2hcv(rgb); + float L = HCV.z - HCV.y * 0.5; + float S = HCV.y / (1 - abs(L * 2 - 1) + HSL_EPSILON); + return vec3(HCV.x, S, L); +} + +vec3 exponentialToneMapping(vec3 color, const float exposure, const float gamma) { color *= exposure; - color.r = color.r < 1.413 ? pow(color.r * 0.38317, 1.0 / gamma) : 1.0 - exp(-color.r); - color.g = color.g < 1.413 ? pow(color.g * 0.38317, 1.0 / gamma) : 1.0 - exp(-color.g); - color.b = color.b < 1.413 ? pow(color.b * 0.38317, 1.0 / gamma) : 1.0 - exp(-color.b); + color.r = color.r < 1.413 ? pow(color.r * 0.38317, 1.0 / gamma) : 1.0 - exp2(-exposure * color.r); + color.g = color.g < 1.413 ? pow(color.g * 0.38317, 1.0 / gamma) : 1.0 - exp2(-exposure * color.g); + color.b = color.b < 1.413 ? pow(color.b * 0.38317, 1.0 / gamma) : 1.0 - exp2(-exposure * color.b); return color; } -vec3 linearToneMapping(vec3 color, float exposure) { - float tExposure = 0.08f; - color = clamp(tExposure * color, 0.f, 1.f); - color = pow(color, vec3(1.f / gamma)); - return color; +vec3 toneMappingOperator(vec3 color, const float exposure) { + return 1.0 - exp2(-exposure * color); } -vec3 simpleReinhardToneMapping(vec3 color, float exposure) { - float tExposure = 1.5f; - color *= tExposure/(1.f + color / tExposure); - color = pow(color, vec3(1.f / gamma)); - return color; -} - -vec3 lumaBasedReinhardToneMapping(vec3 color, float exposure) { - float luma = dot(color, vec3(0.2126f, 0.7152f, 0.0722f)); - float toneMappedLuma = luma / (1.f + luma); - color *= toneMappedLuma / luma; - color = pow(color, vec3(1.f / gamma)); - return color; -} - -vec3 whitePreservingLumaBasedReinhardToneMapping(vec3 color, float exposure) { - float white = 4.f; - //float luma = dot(color, vec3(0.2126f, 0.7152f, 0.0722f)); - float luma = dot(color, vec3(0.4126f, 0.9152f, 0.2722f)); - float toneMappedLuma = luma * (1.f + luma / (white * white)) / (1.f + luma); - color *= toneMappedLuma / luma; - color = pow(color, vec3(1.f / gamma)); - return color; -} - -vec3 RomBinDaHouseToneMapping(vec3 color, float exposure) { - color = exp( -1.f / ( 2.72f * color + 0.15f ) ); - color = pow(color, vec3(1.7f / gamma)); - return color; -} - -vec3 filmicToneMapping(vec3 color, float exposure) -{ - color = max(vec3(0.f), color - vec3(0.04f)); - color = (color * (6.2f * color + 0.5f)) / (color * (6.2f * color + 20.f) + 0.06f); - return color; -} - -vec3 Uncharted2ToneMapping(vec3 color, float exposure) { - float A = 0.15f; - float B = 0.5f; - float C = 0.1f; - float D = 0.2f; - float E = 0.02f; - float F = 0.3f; - float W = 11.2f; - float tExposure = 0.4f; - color *= tExposure; - color = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; - float white = ((W * (A * W + C * B) + D * E) / (W * (A * W + B) + D * F)) - E / F; - color /= white; - color = pow(color, vec3(1.0f / gamma)); - return color; -} - -vec3 jToneMapping(vec3 color, float exposure) { - return 1.0 - exp(-exposure * color); -} - -vec3 HDR(vec3 color, float exposure) { - //return exponentialToneMapping(color, exposure); - //return linearToneMapping(color, exposure); - //return simpleReinhardToneMapping(color, exposure); - //return lumaBasedReinhardToneMapping(color, exposure); - //return whitePreservingLumaBasedReinhardToneMapping(color, exposure); - //return RomBinDaHouseToneMapping(color, exposure); - //return filmicToneMapping(color, exposure); - //return Uncharted2ToneMapping(color, exposure); - return jToneMapping(color, exposure); -} +vec3 gammaCorrection(vec3 color, const float gamma) { + return pow(color, vec3(1.0f / gamma)); +} \ No newline at end of file diff --git a/src/interaction/navigationhandler.cpp b/src/interaction/navigationhandler.cpp index 387b9dcd8c..ee59dcb3c1 100644 --- a/src/interaction/navigationhandler.cpp +++ b/src/interaction/navigationhandler.cpp @@ -67,7 +67,7 @@ namespace openspace::interaction { ghoul::Dictionary -openspace::interaction::NavigationHandler::NavigationState::dictionary() const + openspace::interaction::NavigationHandler::NavigationState::dictionary() const { ghoul::Dictionary cameraDict; cameraDict.setValue(KeyPosition, position); @@ -94,7 +94,7 @@ openspace::interaction::NavigationHandler::NavigationState::dictionary() const } openspace::interaction::NavigationHandler::NavigationState::NavigationState( - const ghoul::Dictionary& dictionary) + const ghoul::Dictionary& dictionary) { const bool hasAnchor = dictionary.hasValue(KeyAnchor); const bool hasPosition = dictionary.hasValue(KeyPosition); @@ -130,13 +130,13 @@ openspace::interaction::NavigationHandler::NavigationState::NavigationState( } openspace::interaction::NavigationHandler::NavigationState::NavigationState( - std::string anchor, - std::string aim, - std::string referenceFrame, - glm::dvec3 position, - std::optional up, - double yaw, - double pitch) + std::string anchor, + std::string aim, + std::string referenceFrame, + glm::dvec3 position, + std::optional up, + double yaw, + double pitch) : anchor(std::move(anchor)) , aim(std::move(aim)) , referenceFrame(std::move(referenceFrame)) @@ -214,7 +214,8 @@ void NavigationHandler::updateCamera(double deltaTime) { applyNavigationState(_pendingNavigationState.value()); _orbitalNavigator.resetVelocities(); _pendingNavigationState.reset(); - } else if (!_playbackModeEnabled && _camera) { + } + else if (!_playbackModeEnabled && _camera) { if (_useKeyFrameInteraction) { _keyframeNavigator.updateCamera(*_camera, _playbackModeEnabled); } @@ -331,7 +332,7 @@ void NavigationHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActio } NavigationHandler::NavigationState NavigationHandler::navigationState( - const SceneGraphNode& referenceFrame) const + const SceneGraphNode& referenceFrame) const { const SceneGraphNode* anchor = _orbitalNavigator.anchorNode(); const SceneGraphNode* aim = _orbitalNavigator.aimNode(); @@ -355,7 +356,7 @@ NavigationHandler::NavigationState NavigationHandler::navigationState( // Need to compensate by redisual roll left in local rotation: const glm::dquat unroll = glm::angleAxis(eulerAngles.z, glm::dvec3(0, 0, 1)); const glm::dvec3 neutralUp = - glm::inverse(invNeutralRotation) * unroll * _camera->lookUpVectorCameraSpace(); + glm::inverse(invNeutralRotation) * unroll * _camera->lookUpVectorCameraSpace(); const glm::dmat3 invReferenceFrameTransform = glm::inverse(referenceFrame.worldRotationMatrix()); @@ -366,7 +367,7 @@ NavigationHandler::NavigationState NavigationHandler::navigationState( return NavigationState( _orbitalNavigator.anchorNode()->identifier(), _orbitalNavigator.aimNode() ? - _orbitalNavigator.aimNode()->identifier() : "", + _orbitalNavigator.aimNode()->identifier() : "", referenceFrame.identifier(), position, invReferenceFrameTransform * neutralUp, yaw, pitch @@ -374,7 +375,7 @@ NavigationHandler::NavigationState NavigationHandler::navigationState( } void NavigationHandler::saveNavigationState(const std::string& filepath, - const std::string& referenceFrameIdentifier) + const std::string& referenceFrameIdentifier) { const SceneGraphNode* referenceFrame = _orbitalNavigator.followingNodeRotation() ? _orbitalNavigator.anchorNode() : @@ -428,9 +429,9 @@ void NavigationHandler::loadNavigationState(const std::string& filepath) { } void NavigationHandler::setJoystickAxisMapping(int axis, - JoystickCameraStates::AxisType mapping, - JoystickCameraStates::AxisInvert shouldInvert, - JoystickCameraStates::AxisNormalize shouldNormalize) + JoystickCameraStates::AxisType mapping, + JoystickCameraStates::AxisInvert shouldInvert, + JoystickCameraStates::AxisNormalize shouldNormalize) { _orbitalNavigator.joystickStates().setAxisMapping( axis, @@ -441,9 +442,9 @@ void NavigationHandler::setJoystickAxisMapping(int axis, } void NavigationHandler::setWebsocketAxisMapping(int axis, - WebsocketCameraStates::AxisType mapping, - WebsocketCameraStates::AxisInvert shouldInvert, - WebsocketCameraStates::AxisNormalize shouldNormalize) + WebsocketCameraStates::AxisType mapping, + WebsocketCameraStates::AxisInvert shouldInvert, + WebsocketCameraStates::AxisNormalize shouldNormalize) { _orbitalNavigator.websocketStates().setAxisMapping( axis, @@ -455,7 +456,7 @@ void NavigationHandler::setWebsocketAxisMapping(int axis, JoystickCameraStates::AxisInformation -NavigationHandler::joystickAxisMapping(int axis) const + NavigationHandler::joystickAxisMapping(int axis) const { return _orbitalNavigator.joystickStates().axisMapping(axis); } @@ -469,9 +470,9 @@ float NavigationHandler::joystickAxisDeadzone(int axis) const { } void NavigationHandler::bindJoystickButtonCommand(int button, std::string command, - JoystickAction action, - JoystickCameraStates::ButtonCommandRemote remote, - std::string documentation) + JoystickAction action, + JoystickCameraStates::ButtonCommandRemote remote, + std::string documentation) { _orbitalNavigator.joystickStates().bindButtonCommand( button, diff --git a/src/rendering/abufferrenderer.cpp b/src/rendering/abufferrenderer.cpp index 5fbd5c9e46..e504658408 100644 --- a/src/rendering/abufferrenderer.cpp +++ b/src/rendering/abufferrenderer.cpp @@ -702,6 +702,14 @@ void ABufferRenderer::setNAaSamples(int nAaSamples) { _dirtyResolution = true; } +void ABufferRenderer::setBlurrinessLevel(int level) { + ghoul_assert( + level > 0 && nAaSamples < 4, + "Blurriness level has to be between 1 and 3" + ); + _blurrinessLevel = level; +} + void ABufferRenderer::setHDRExposure(float hdrExposure) { _hdrExposure = hdrExposure; if (_hdrExposure < 0.f) { @@ -710,15 +718,6 @@ void ABufferRenderer::setHDRExposure(float hdrExposure) { } } -void ABufferRenderer::setHDRBackground(float hdrBackground) { - _hdrBackground = hdrBackground; - if (_hdrBackground < 0.f) { - LERROR("HDR Background constant must be greater than zero."); - _hdrBackground = 1.0; - } -} - - void ABufferRenderer::setGamma(float gamma) { _gamma = gamma; if (_gamma < 0.f) { @@ -727,8 +726,72 @@ void ABufferRenderer::setGamma(float gamma) { } } -float ABufferRenderer::hdrBackground() const { - return _hdrBackground; +void ABufferRenderer::setMaxWhite(float maxWhite) { + _maxWhite = maxWhite; +} + +void ABufferRenderer::setToneMapOperator(int tmOp) { + _toneMapOperator = tmpOp; +}; + +void ABufferRenderer::setToneMapOperator(int tmOp) { + _toneMapOperator = tmOp; +} + +void ABufferRenderer::setBloomThreMin(float minV) { + _bloomThresholdMin = minV; +} + +void ABufferRenderer::setBloomThreMax(float maxV) { + _bloomThresholdMax = maxV; +} + +void ABufferRenderer::setBloomOrigFactor(float origFactor) { + _bloomOrigFactor = origFactor; +} + +void ABufferRenderer::setBloomNewFactor(float newFactor) { + _bloomNewFactor = newFactor; +} + +void ABufferRenderer::setKey(float key) { + _tmoKey = key; +} + +void ABufferRenderer::setYwhite(float white) { + _tmoYwhite = white; +} + +void ABufferRenderer::setTmoSaturation(float sat) { + _tmoSaturation = sat; +} + +void ABufferRenderer::setHue(float hue) { + _hue = hue; +} + +void ABufferRenderer::setValue(float value) { + _value = value; +} + +void ABufferRenderer::setSaturation(float sat) { + _saturation = sat; +} + +void ABufferRenderer::setLightness(float lightness) { + _lightness = lightness; +} + +void ABufferRenderer::setColorSpace(unsigned int colorspace) { + _colorSpace = colorspace; +} + +void ABufferRenderer::enableBloom(bool enable) { + _bloomEnabled = enable; +} + +void ABufferRenderer::enableHistogram(bool enable) { + _histogramEnabled = enable; } int ABufferRenderer::nAaSamples() const { diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 46ba8b8de7..61f23be178 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -55,6 +54,11 @@ namespace { "mainColorTexture", "blackoutFactor", "nAaSamples" }; + constexpr const std::array HDRUniformNames = { + "hdrFeedingTexture", "blackoutFactor", "hdrExposure", "gamma", + "Hue", "Saturation", "Value", "nAaSamples" + }; + constexpr const char* ExitFragmentShaderPath = "${SHADERS}/framebuffer/exitframebuffer.frag"; constexpr const char* RaycastFragmentShaderPath = @@ -121,57 +125,66 @@ void FramebufferRenderer::initialize() { glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr); glEnableVertexAttribArray(0); - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO); - // Main framebuffer - glGenTextures(1, &_mainColorTexture); - glGenTextures(1, &_mainDepthTexture); - glGenFramebuffers(1, &_mainFramebuffer); + // GBuffers + glGenTextures(1, &_gBuffers._colorTexture); + glGenTextures(1, &_gBuffers._depthTexture); + glGenTextures(1, &_gBuffers._positionTexture); + glGenTextures(1, &_gBuffers._normalTexture); + glGenFramebuffers(1, &_gBuffers._framebuffer); + // PingPong Buffers + // The first pingpong buffer shares the color texture with the renderbuffer: + _pingPongBuffers.colorTexture[0] = _gBuffers._colorTexture; + glGenTextures(1, &_pingPongBuffers.colorTexture[1]); + glGenFramebuffers(1, &_pingPongBuffers.framebuffer); + // Exit framebuffer glGenTextures(1, &_exitColorTexture); glGenTextures(1, &_exitDepthTexture); glGenFramebuffers(1, &_exitFramebuffer); - // Deferred framebuffer - glGenTextures(1, &_deferredColorTexture); - glGenTextures(1, &_mainPositionTexture); - glGenTextures(1, &_mainNormalTexture); - glGenFramebuffers(1, &_deferredFramebuffer); + // HDR / Filtering Buffers + glGenFramebuffers(1, &_hdrBuffers._hdrFilteringFramebuffer); + glGenTextures(1, &_hdrBuffers._hdrFilteringTexture); + // Allocate Textures/Buffers Memory updateResolution(); + updateRendererData(); updateRaycastData(); - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + //==============================// + //===== GBuffers Buffers =====// + //==============================// + glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers._framebuffer); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, - _mainColorTexture, + _gBuffers._colorTexture, 0 ); - // G-buffer glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, - _mainPositionTexture, + _gBuffers._positionTexture, 0 ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, - _mainNormalTexture, + _gBuffers._normalTexture, 0 ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, - _mainDepthTexture, + _gBuffers._depthTexture, 0 ); @@ -180,6 +193,41 @@ void FramebufferRenderer::initialize() { LERROR("Main framebuffer is not complete"); } + //==============================// + //===== PingPong Buffers =====// + //==============================// + glBindFramebuffer(GL_FRAMEBUFFER, _pingPongBuffers.framebuffer); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D_MULTISAMPLE, + _pingPongBuffers.colorTexture[0], + 0 + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT1, + GL_TEXTURE_2D_MULTISAMPLE, + _pingPongBuffers.colorTexture[1], + 0 + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D_MULTISAMPLE, + _gBuffers._depthTexture, + 0 + ); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Ping pong buffer is not complete"); + } + + //======================================// + //===== Volume Rendering Buffers =====// + //======================================// + // Builds Exit Framebuffer glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); glFramebufferTexture2D( GL_FRAMEBUFFER, @@ -201,26 +249,32 @@ void FramebufferRenderer::initialize() { LERROR("Exit framebuffer is not complete"); } - glBindFramebuffer(GL_FRAMEBUFFER, _deferredFramebuffer); + //===================================// + //===== HDR/Filtering Buffers =====// + //===================================// + glBindFramebuffer(GL_FRAMEBUFFER, _hdrBuffers._hdrFilteringFramebuffer); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - _deferredColorTexture, + _hdrBuffers._hdrFilteringTexture, 0 ); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("Deferred framebuffer is not complete"); + LERROR("HDR/Filtering framebuffer is not complete"); } // JCC: Moved to here to avoid NVidia: "Program/shader state performance warning" - updateHDRData(); + // Building programs + updateHDRAndFiltering(); updateDeferredcastData(); + _dirtyMsaaSamplingPattern = true; - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + // Sets back to default FBO + glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); _resolveProgram = ghoul::opengl::ProgramObject::Build( "Framebuffer Resolve", @@ -228,26 +282,41 @@ void FramebufferRenderer::initialize() { absPath("${SHADERS}/framebuffer/resolveframebuffer.frag") ); - ghoul::opengl::updateUniformLocations(*_resolveProgram, _uniformCache, UniformNames); + ghoul::opengl::updateUniformLocations( + *_resolveProgram, + _uniformCache, + UniformNames + ); + ghoul::opengl::updateUniformLocations( + *_hdrFilteringProgram, + _hdrUniformCache, + HDRUniformNames + ); global::raycasterManager.addListener(*this); global::deferredcasterManager.addListener(*this); + + // Default GL State for Blending + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } void FramebufferRenderer::deinitialize() { LINFO("Deinitializing FramebufferRenderer"); - glDeleteFramebuffers(1, &_mainFramebuffer); + glDeleteFramebuffers(1, &_gBuffers._framebuffer); glDeleteFramebuffers(1, &_exitFramebuffer); - glDeleteFramebuffers(1, &_deferredFramebuffer); + glDeleteFramebuffers(1, &_hdrBuffers._hdrFilteringFramebuffer); + glDeleteFramebuffers(1, &_pingPongBuffers.framebuffer); - glDeleteTextures(1, &_mainColorTexture); - glDeleteTextures(1, &_mainDepthTexture); + glDeleteTextures(1, &_gBuffers._colorTexture); + glDeleteTextures(1, &_gBuffers._depthTexture); - // DEBUG: deferred g-buffer - glDeleteTextures(1, &_deferredColorTexture); - glDeleteTextures(1, &_mainPositionTexture); - glDeleteTextures(1, &_mainNormalTexture); + glDeleteTextures(1, &_hdrBuffers._hdrFilteringTexture); + glDeleteTextures(1, &_gBuffers._positionTexture); + glDeleteTextures(1, &_gBuffers._normalTexture); + + glDeleteTextures(1, &_pingPongBuffers.colorTexture[1]); glDeleteTextures(1, &_exitColorTexture); glDeleteTextures(1, &_exitDepthTexture); @@ -271,14 +340,66 @@ void FramebufferRenderer::deferredcastersChanged(Deferredcaster&, _dirtyDeferredcastData = true; } -void FramebufferRenderer::update() { - if (_dirtyMsaaSamplingPattern) { - updateMSAASamplingPattern(); - } +void FramebufferRenderer::resolveMSAA(float blackoutFactor) { + _resolveProgram->activate(); + ghoul::opengl::TextureUnit mainColorTextureUnit; + mainColorTextureUnit.activate(); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture); + _resolveProgram->setUniform(_uniformCache.mainColorTexture, mainColorTextureUnit); + _resolveProgram->setUniform(_uniformCache.blackoutFactor, blackoutFactor); + _resolveProgram->setUniform(_uniformCache.nAaSamples, _nAaSamples); + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + _resolveProgram->deactivate(); +} + +void FramebufferRenderer::applyTMO(float blackoutFactor) { + const bool doPerformanceMeasurements = global::performanceManager.isEnabled(); + std::unique_ptr perfInternal; + + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::TMO" + ); + } + _hdrFilteringProgram->activate(); + + ghoul::opengl::TextureUnit hdrFeedingTextureUnit; + hdrFeedingTextureUnit.activate(); + glBindTexture( + GL_TEXTURE_2D_MULTISAMPLE, + _pingPongBuffers.colorTexture[_pingPongIndex] + ); + + _hdrFilteringProgram->setUniform( + _hdrUniformCache.hdrFeedingTexture, + hdrFeedingTextureUnit + ); + + + _hdrFilteringProgram->setUniform(_hdrUniformCache.blackoutFactor, blackoutFactor); + _hdrFilteringProgram->setUniform(_hdrUniformCache.hdrExposure, _hdrExposure); + _hdrFilteringProgram->setUniform(_hdrUniformCache.gamma, _gamma); + _hdrFilteringProgram->setUniform(_hdrUniformCache.Hue, _hue); + _hdrFilteringProgram->setUniform(_hdrUniformCache.Saturation, _saturation); + _hdrFilteringProgram->setUniform(_hdrUniformCache.Value, _value); + _hdrFilteringProgram->setUniform(_hdrUniformCache.nAaSamples, _nAaSamples); + + + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + _hdrFilteringProgram->deactivate(); +} + +void FramebufferRenderer::update() { if (_dirtyResolution) { updateResolution(); - updateMSAASamplingPattern(); } if (_dirtyRaycastData) { @@ -289,21 +410,24 @@ void FramebufferRenderer::update() { updateDeferredcastData(); } - // If the resolve dictionary changed (or a file changed on disk) - // then rebuild the resolve program. - if (_hdrBackGroundProgram && _hdrBackGroundProgram->isDirty()) { - _hdrBackGroundProgram->rebuildFromFile(); - } - if (_resolveProgram->isDirty()) { _resolveProgram->rebuildFromFile(); - ghoul::opengl::updateUniformLocations( *_resolveProgram, _uniformCache, UniformNames ); } + + if (_hdrFilteringProgram->isDirty()) { + _hdrFilteringProgram->rebuildFromFile(); + + ghoul::opengl::updateUniformLocations( + *_hdrFilteringProgram, + _hdrUniformCache, + HDRUniformNames + ); + } using K = VolumeRaycaster*; using V = std::unique_ptr; @@ -357,19 +481,60 @@ void FramebufferRenderer::update() { } void FramebufferRenderer::updateResolution() { - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture); + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA32F, + _resolution.x, + _resolution.y, + GL_TRUE + ); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._positionTexture); + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA32F, + _resolution.x, + _resolution.y, + GL_TRUE + ); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._normalTexture); glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, _nAaSamples, - GL_RGBA, + GL_RGBA32F, _resolution.x, _resolution.y, - true + GL_TRUE ); - // G-buffer - glBindTexture(GL_TEXTURE_2D, _deferredColorTexture); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._depthTexture); + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_DEPTH_COMPONENT32F, + _resolution.x, + _resolution.y, + GL_TRUE + ); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _pingPongBuffers.colorTexture[1]); + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA32F, + _resolution.x, + _resolution.y, + GL_TRUE + ); + + + // HDR / Filtering + glBindTexture(GL_TEXTURE_2D, _hdrBuffers._hdrFilteringTexture); glTexImage2D( GL_TEXTURE_2D, @@ -386,43 +551,12 @@ void FramebufferRenderer::updateResolution() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainPositionTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - _resolution.x, - _resolution.y, - true - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainNormalTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - _resolution.x, - _resolution.y, - true - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_DEPTH_COMPONENT32F, - _resolution.x, - _resolution.y, - true - ); - + // Volume Rendering Textures glBindTexture(GL_TEXTURE_2D, _exitColorTexture); glTexImage2D( GL_TEXTURE_2D, 0, - GL_RGBA16, + GL_RGBA16F, _resolution.x, _resolution.y, 0, @@ -577,339 +711,32 @@ void FramebufferRenderer::updateDeferredcastData() { _dirtyDeferredcastData = false; } -void FramebufferRenderer::updateHDRData() { - _hdrBackGroundProgram = ghoul::opengl::ProgramObject::Build( - "HDR Background Control", - absPath("${SHADERS}/framebuffer/hdrBackground.vert"), - absPath("${SHADERS}/framebuffer/hdrBackground.frag") + +void FramebufferRenderer::updateHDRAndFiltering() { + _hdrFilteringProgram = ghoul::opengl::ProgramObject::Build( + "HDR and Filtering Program", + absPath("${SHADERS}/framebuffer/hdrAndFiltering.vert"), + absPath("${SHADERS}/framebuffer/hdrAndfiltering.frag") ); using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; - _hdrBackGroundProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); - _hdrBackGroundProgram->setIgnoreUniformLocationError(IgnoreError::Yes); -} - -void FramebufferRenderer::updateMSAASamplingPattern() { - LDEBUG("Updating MSAA Sampling Pattern"); - - constexpr const int GridSize = 32; - GLfloat step = 2.f / static_cast(GridSize); - GLfloat sizeX = -1.f; - GLfloat sizeY = 1.0; - - constexpr const int NVertex = 4 * 6; - // openPixelSizeVertexData - GLfloat vertexData[GridSize * GridSize * NVertex]; - - // @CLEANUP(abock): Is this necessary? I was mucking about with the shader and it - // didn't make any visual difference. If it is necessary, the z and w - // components can be removed for sure since they are always 0, 1 and - // not used in the shader either - for (int y = 0; y < GridSize; ++y) { - for (int x = 0; x < GridSize; ++x) { - vertexData[y * GridSize * NVertex + x * NVertex] = sizeX; - vertexData[y * GridSize * NVertex + x * NVertex + 1] = sizeY - step; - vertexData[y * GridSize * NVertex + x * NVertex + 2] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 3] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 4] = sizeX + step; - vertexData[y * GridSize * NVertex + x * NVertex + 5] = sizeY; - vertexData[y * GridSize * NVertex + x * NVertex + 6] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 7] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 8] = sizeX; - vertexData[y * GridSize * NVertex + x * NVertex + 9] = sizeY; - vertexData[y * GridSize * NVertex + x * NVertex + 10] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 11] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 12] = sizeX; - vertexData[y * GridSize * NVertex + x * NVertex + 13] = sizeY - step; - vertexData[y * GridSize * NVertex + x * NVertex + 14] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 15] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 16] = sizeX + step; - vertexData[y * GridSize * NVertex + x * NVertex + 17] = sizeY - step; - vertexData[y * GridSize * NVertex + x * NVertex + 18] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 19] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 20] = sizeX + step; - vertexData[y * GridSize * NVertex + x * NVertex + 21] = sizeY; - vertexData[y * GridSize * NVertex + x * NVertex + 22] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 23] = 1.f; - - sizeX += step; - } - sizeX = -1.f; - sizeY -= step; - } - - GLuint pixelSizeQuadVAO = 0; - glGenVertexArrays(1, &pixelSizeQuadVAO); - glBindVertexArray(pixelSizeQuadVAO); - - GLuint pixelSizeQuadVBO = 0; - glGenBuffers(1, &pixelSizeQuadVBO); - glBindBuffer(GL_ARRAY_BUFFER, pixelSizeQuadVBO); - - glBufferData( - GL_ARRAY_BUFFER, - sizeof(GLfloat) * GridSize * GridSize * NVertex, - vertexData, - GL_STATIC_DRAW - ); - - // Position - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, nullptr); - glEnableVertexAttribArray(0); - - // Saves current state - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - - // Main framebuffer - GLuint pixelSizeTexture = 0; - GLuint pixelSizeFramebuffer = 0; - - glGenTextures(1, &pixelSizeTexture); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, pixelSizeTexture); - - constexpr const GLsizei OnePixel = 1; - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - OnePixel, - OnePixel, - true - ); - - glViewport(0, 0, OnePixel, OnePixel); - - glGenFramebuffers(1, &pixelSizeFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, pixelSizeFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D_MULTISAMPLE, - pixelSizeTexture, - 0 - ); - - GLenum textureBuffers[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, textureBuffers); - - glClearColor(0.f, 0.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("MSAA Sampling pattern framebuffer is not complete"); - return; - } - - std::unique_ptr pixelSizeProgram = - ghoul::opengl::ProgramObject::Build( - "OnePixel MSAA", - absPath("${SHADERS}/framebuffer/pixelSizeMSAA.vert"), - absPath("${SHADERS}/framebuffer/pixelSizeMSAA.frag") - ); - - pixelSizeProgram->activate(); - - // Draw sub-pixel grid - glEnable(GL_SAMPLE_SHADING); - glBindVertexArray(pixelSizeQuadVAO); - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - glDrawArrays(GL_TRIANGLES, 0, GridSize * GridSize * 6); - glBindVertexArray(0); - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SAMPLE_SHADING); - - pixelSizeProgram->deactivate(); - - // Now we render the Nx1 quad strip - GLuint nOneStripFramebuffer = 0; - GLuint nOneStripVAO = 0; - GLuint nOneStripVBO = 0; - GLuint nOneStripTexture = 0; - - sizeX = -1.f; - step = 2.f / static_cast(_nAaSamples); - - std::vectornOneStripVertexData(_nAaSamples * (NVertex + 12)); - - for (int x = 0; x < _nAaSamples; ++x) { - nOneStripVertexData[x * (NVertex + 12)] = sizeX; - nOneStripVertexData[x * (NVertex + 12) + 1] = -1.f; - nOneStripVertexData[x * (NVertex + 12) + 2] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 3] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 4] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 5] = 0.f; - - nOneStripVertexData[x * (NVertex + 12) + 6] = sizeX + step; - nOneStripVertexData[x * (NVertex + 12) + 7] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 8] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 9] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 10] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 11] = 1.f; - - nOneStripVertexData[x * (NVertex + 12) + 12] = sizeX; - nOneStripVertexData[x * (NVertex + 12) + 13] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 14] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 15] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 16] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 17] = 0.f; - - nOneStripVertexData[x * (NVertex + 12) + 18] = sizeX; - nOneStripVertexData[x * (NVertex + 12) + 19] = -1.f; - nOneStripVertexData[x * (NVertex + 12) + 20] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 21] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 22] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 23] = 0.f; - - nOneStripVertexData[x * (NVertex + 12) + 24] = sizeX + step; - nOneStripVertexData[x * (NVertex + 12) + 25] = -1.f; - nOneStripVertexData[x * (NVertex + 12) + 26] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 27] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 28] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 29] = 1.f; - - nOneStripVertexData[x * (NVertex + 12) + 30] = sizeX + step; - nOneStripVertexData[x * (NVertex + 12) + 31] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 32] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 33] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 34] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 35] = 1.f; - - sizeX += step; - } - - glGenVertexArrays(1, &nOneStripVAO); - glBindVertexArray(nOneStripVAO); - glGenBuffers(1, &nOneStripVBO); - glBindBuffer(GL_ARRAY_BUFFER, nOneStripVBO); - glBufferData( - GL_ARRAY_BUFFER, - sizeof(GLfloat) * _nAaSamples * (NVertex + 12), - nOneStripVertexData.data(), - GL_STATIC_DRAW - ); - - // position - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, nullptr); - glEnableVertexAttribArray(0); - - // texture coords - glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(GLfloat) * 6, - reinterpret_cast(sizeof(GLfloat) * 4) - ); - glEnableVertexAttribArray(1); - - // fbo texture buffer - glGenTextures(1, &nOneStripTexture); - glBindTexture(GL_TEXTURE_2D, nOneStripTexture); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA32F, - _nAaSamples, - OnePixel, - 0, - GL_RGBA, - GL_FLOAT, - nullptr - ); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glGenFramebuffers(1, &nOneStripFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, nOneStripFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - nOneStripTexture, - 0 - ); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("nOneStrip framebuffer is not complete"); - } - - glViewport(0, 0, _nAaSamples, OnePixel); - - std::unique_ptr nOneStripProgram = - ghoul::opengl::ProgramObject::Build( - "OneStrip MSAA", - absPath("${SHADERS}/framebuffer/nOneStripMSAA.vert"), - absPath("${SHADERS}/framebuffer/nOneStripMSAA.frag") - ); - - nOneStripProgram->activate(); - - ghoul::opengl::TextureUnit pixelSizeTextureUnit; - pixelSizeTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, pixelSizeTexture); - nOneStripProgram->setUniform("pixelSizeTexture", pixelSizeTextureUnit); - - // render strip - glDrawBuffers(1, textureBuffers); - - glClearColor(0.f, 1.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT); - glBindVertexArray(nOneStripVAO); - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - - for (int sample = 0; sample < _nAaSamples; ++sample) { - nOneStripProgram->setUniform("currentSample", sample); - glDrawArrays(GL_TRIANGLES, sample * 6, 6); - } - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glBindVertexArray(0); - - saveTextureToMemory(GL_COLOR_ATTACHMENT0, _nAaSamples, 1, _mSAAPattern); - // Convert back to [-1, 1] range and then scale for the current viewport size: - for (int d = 0; d < _nAaSamples; ++d) { - _mSAAPattern[d * 3] = (2.0 * _mSAAPattern[d * 3] - 1.0) / - static_cast(viewport[1]); - _mSAAPattern[(d * 3) + 1] = (2.0 * _mSAAPattern[(d * 3) + 1] - 1.0) / - static_cast(viewport[3]); - _mSAAPattern[(d * 3) + 2] = 0.0; - } - - nOneStripProgram->deactivate(); - - // Restores default state - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - - // Deletes unused buffers - glDeleteFramebuffers(1, &pixelSizeFramebuffer); - glDeleteTextures(1, &pixelSizeTexture); - glDeleteBuffers(1, &pixelSizeQuadVBO); - glDeleteVertexArrays(1, &pixelSizeQuadVAO); - - glDeleteFramebuffers(1, &nOneStripFramebuffer); - glDeleteTextures(1, &nOneStripTexture); - glDeleteBuffers(1, &nOneStripVBO); - glDeleteVertexArrays(1, &nOneStripVAO); - - _dirtyMsaaSamplingPattern = false; + //_hdrFilteringProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); + //_hdrFilteringProgram->setIgnoreUniformLocationError(IgnoreError::Yes); } void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFactor) { + // Set OpenGL default rendering state + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO); + glEnablei(GL_BLEND, 0); + glDisablei(GL_BLEND, 1); + glDisablei(GL_BLEND, 2); + + glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE); + + glEnable(GL_DEPTH_TEST); + + _pingPongIndex = 0; + + // Measurements cache variable const bool doPerformanceMeasurements = global::performanceManager.isEnabled(); std::unique_ptr perf; @@ -921,31 +748,13 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac if (!scene || !camera) { return; - } - - glEnable(GL_DEPTH_TEST); - - // Capture standard fbo - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - glEnable(GL_DEPTH_TEST); + } // deferred g-buffer - GLenum textureBuffers[3] = { - GL_COLOR_ATTACHMENT0, - GL_COLOR_ATTACHMENT1, - GL_COLOR_ATTACHMENT2, - }; - glDrawBuffers(3, textureBuffers); + glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers._framebuffer); + glDrawBuffers(3, ColorAttachment012Array); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnablei(GL_BLEND, 0); - glDisablei(GL_BLEND, 1); - glDisablei(GL_BLEND, 2); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - + Time time = global::timeManager.time(); RenderData data = { @@ -963,9 +772,8 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac scene->render(data, tasks); data.renderBinMask = static_cast(Renderable::RenderBin::Transparent); scene->render(data, tasks); - data.renderBinMask = static_cast(Renderable::RenderBin::Overlay); - scene->render(data, tasks); + // Run Volume Tasks { std::unique_ptr perfInternal; if (doPerformanceMeasurements) { @@ -976,36 +784,44 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac performRaycasterTasks(tasks.raycasterTasks); } - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - GLenum dBuffer[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, dBuffer); + if (!tasks.deferredcasterTasks.empty()) { + // We use ping pong rendering in order to be able to + // render to the same final buffer, multiple + // deferred tasks at same time (e.g. more than 1 ATM being seen at once) + glBindFramebuffer(GL_FRAMEBUFFER, _pingPongBuffers.framebuffer); + glDrawBuffers(1, &ColorAttachment01Array[_pingPongIndex]); - { std::unique_ptr perfInternal; if (doPerformanceMeasurements) { perfInternal = std::make_unique( "FramebufferRenderer::render::deferredTasks" - ); + ); } - performDeferredTasks(tasks.deferredcasterTasks, blackoutFactor); + performDeferredTasks(tasks.deferredcasterTasks); } + + glDrawBuffers(1, &ColorAttachment01Array[_pingPongIndex]); + glEnablei(GL_BLEND, 0); - if (tasks.deferredcasterTasks.empty()) { - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - _resolveProgram->activate(); + data.renderBinMask = static_cast(Renderable::RenderBin::Overlay); + scene->render(data, tasks); - ghoul::opengl::TextureUnit mainColorTextureUnit; - mainColorTextureUnit.activate(); + glDrawBuffer(GL_COLOR_ATTACHMENT0); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); - _resolveProgram->setUniform(_uniformCache.mainColorTexture, mainColorTextureUnit); - _resolveProgram->setUniform(_uniformCache.blackoutFactor, blackoutFactor); - _resolveProgram->setUniform(_uniformCache.nAaSamples, _nAaSamples); - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - _resolveProgram->deactivate(); + // Disabling depth test for filtering and hdr + glDisable(GL_DEPTH_TEST); + + // When applying the TMO, the result is saved to the default FBO to be displayed + // by the Operating System. Also, the resolve procedure is executed in this step. + glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); + glViewport(0, 0, _resolution.x, _resolution.y); + + if (_disableHDR) { + resolveMSAA(blackoutFactor); + } + else { + // Apply the selected TMO on the results and resolve the result for the default FBO + applyTMO(blackoutFactor); } } @@ -1023,7 +839,7 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector exitProgram->deactivate(); } - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers._framebuffer); glm::vec3 cameraPosition; bool isCameraInside = raycaster->isCameraInside( raycasterTask.renderData, @@ -1069,7 +885,7 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector ghoul::opengl::TextureUnit mainDepthTextureUnit; mainDepthTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._depthTexture); raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit); raycastProgram->setUniform("nAaSamples", _nAaSamples); @@ -1098,12 +914,9 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector } void FramebufferRenderer::performDeferredTasks( - const std::vector& tasks, - float blackoutFactor + const std::vector& tasks ) -{ - bool firstPaint = true; - +{ for (const DeferredcasterTask& deferredcasterTask : tasks) { Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster; @@ -1116,12 +929,22 @@ void FramebufferRenderer::performDeferredTasks( } if (deferredcastProgram) { + _pingPongIndex = _pingPongIndex == 0 ? 1 : 0; + int fromIndex = _pingPongIndex == 0 ? 1 : 0; + glDrawBuffers(1, &ColorAttachment01Array[_pingPongIndex]); + glDisablei(GL_BLEND, 0); + glDisablei(GL_BLEND, 1); + deferredcastProgram->activate(); // adding G-Buffer ghoul::opengl::TextureUnit mainDColorTextureUnit; mainDColorTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + //glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._colorTexture); + glBindTexture( + GL_TEXTURE_2D_MULTISAMPLE, + _pingPongBuffers.colorTexture[fromIndex] + ); deferredcastProgram->setUniform( "mainColorTexture", mainDColorTextureUnit @@ -1129,7 +952,7 @@ void FramebufferRenderer::performDeferredTasks( ghoul::opengl::TextureUnit mainPositionTextureUnit; mainPositionTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainPositionTexture); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._positionTexture); deferredcastProgram->setUniform( "mainPositionTexture", mainPositionTextureUnit @@ -1137,23 +960,14 @@ void FramebufferRenderer::performDeferredTasks( ghoul::opengl::TextureUnit mainNormalTextureUnit; mainNormalTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainNormalTexture); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _gBuffers._normalTexture); deferredcastProgram->setUniform( "mainNormalTexture", mainNormalTextureUnit ); deferredcastProgram->setUniform("nAaSamples", _nAaSamples); - // 48 = 16 samples * 3 coords - deferredcastProgram->setUniform("msaaSamplePatter", &_mSAAPattern[0], 48); - - deferredcastProgram->setUniform("firstPaint", firstPaint); - deferredcastProgram->setUniform("atmExposure", _hdrExposure); - deferredcastProgram->setUniform("backgroundConstant", _hdrBackground); - - deferredcastProgram->setUniform("blackoutFactor", blackoutFactor); - - + deferredcaster->preRaycast( deferredcasterTask.renderData, _deferredcastData[deferredcaster], @@ -1177,10 +991,6 @@ void FramebufferRenderer::performDeferredTasks( ); deferredcastProgram->deactivate(); - - if (firstPaint) { - firstPaint = false; - } } else { LWARNING( @@ -1211,36 +1021,42 @@ void FramebufferRenderer::setNAaSamples(int nAaSamples) { _dirtyMsaaSamplingPattern = true; } -void FramebufferRenderer::setHDRExposure(float hdrExposure) { - ghoul_assert(hdrExposure > 0.f, "HDR exposure must be greater than zero"); - _hdrExposure = hdrExposure; +void FramebufferRenderer::disableHDR(bool disable) { + _disableHDR = std::move(disable); } -void FramebufferRenderer::setHDRBackground(float hdrBackground) { - ghoul_assert(hdrBackground > 0.f, "HDR Background must be greater than zero"); - _hdrBackground = hdrBackground; +void FramebufferRenderer::setHDRExposure(float hdrExposure) { + ghoul_assert(hdrExposure > 0.f, "HDR exposure must be greater than zero"); + _hdrExposure = std::move(hdrExposure); + updateRendererData(); } void FramebufferRenderer::setGamma(float gamma) { ghoul_assert(gamma > 0.f, "Gamma value must be greater than zero"); - _gamma = gamma; + _gamma = std::move(gamma); } -float FramebufferRenderer::hdrBackground() const { - return _hdrBackground; +void FramebufferRenderer::setHue(float hue) { + _hue = std::move(hue); +} + +void FramebufferRenderer::setValue(float value) { + _value = std::move(value); +} + +void FramebufferRenderer::setSaturation(float sat) { + _saturation = std::move(sat); } int FramebufferRenderer::nAaSamples() const { return _nAaSamples; } -const std::vector& FramebufferRenderer::mSSAPattern() const { - return _mSAAPattern; -} - void FramebufferRenderer::updateRendererData() { ghoul::Dictionary dict; dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); + dict.setValue("hdrExposure", std::to_string(_hdrExposure)); + dict.setValue("disableHDR", std::to_string(_disableHDR)); _rendererData = dict; global::renderEngine.setRendererData(dict); } diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index efd779f686..ac019c4aca 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -211,6 +211,15 @@ void Renderable::onEnabledChange(std::function callback) { }); } +void Renderable::setRenderBinFromOpacity() { + if (_opacity > 0.f && _opacity < 1.f) { + setRenderBin(Renderable::RenderBin::Transparent); + } + else { + setRenderBin(Renderable::RenderBin::Opaque); + } +} + void Renderable::registerUpdateRenderBinFromOpacity() { _opacity.onChange([this](){ if (_opacity > 0.f && _opacity < 1.f) { diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 21bd00dbde..a0e7d11e3d 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -199,6 +199,14 @@ namespace { "rendering for the MSAA method." }; + constexpr openspace::properties::Property::PropertyInfo DisableHDRPipelineInfo = { + "DisableHDRPipeline", + "Disable HDR Rendering", + "If this value is enabled, the rendering will disable the HDR color handling " + "and the LDR color pipeline will be used. Be aware of possible over exposure " + "in the final colors." + }; + constexpr openspace::properties::Property::PropertyInfo HDRExposureInfo = { "HDRExposure", "HDR Exposure", @@ -206,13 +214,6 @@ namespace { "equivalent of an electronic image sensor." }; - constexpr openspace::properties::Property::PropertyInfo BackgroundExposureInfo = { - "Background Exposure", - "BackgroundExposure", - "This value determines the amount of light per unit area reaching the " - "equivalent of an electronic image sensor for the background image." - }; - constexpr openspace::properties::Property::PropertyInfo GammaInfo = { "Gamma", "Gamma Correction", @@ -220,6 +221,24 @@ namespace { "tristimulus values in the image." }; + constexpr openspace::properties::Property::PropertyInfo HueInfo = { + "Hue", + "Hue", + "Hue" + }; + + constexpr openspace::properties::Property::PropertyInfo SaturationInfo = { + "Saturation", + "Saturation", + "Saturation" + }; + + constexpr openspace::properties::Property::PropertyInfo ValueInfo = { + "Value", + "Value", + "Value" + }; + constexpr openspace::properties::Property::PropertyInfo HorizFieldOfViewInfo = { "HorizFieldOfView", "Horizontal Field of View", @@ -255,9 +274,12 @@ RenderEngine::RenderEngine() , _disableMasterRendering(DisableMasterInfo, false) , _globalBlackOutFactor(GlobalBlackoutFactorInfo, 1.f, 0.f, 1.f) , _nAaSamples(AaSamplesInfo, 4, 1, 8) - , _hdrExposure(HDRExposureInfo, 0.4f, 0.01f, 10.0f) - , _hdrBackground(BackgroundExposureInfo, 2.8f, 0.01f, 10.0f) - , _gamma(GammaInfo, 2.2f, 0.01f, 10.0f) + , _disableHDRPipeline(DisableHDRPipelineInfo, false) + , _hdrExposure(HDRExposureInfo, 3.7f, 0.01f, 10.0f) + , _gamma(GammaInfo, 0.86f, 0.01f, 5.0f) + , _hue(HueInfo, 180.f, 0.0f, 360.0f) + , _saturation(SaturationInfo, 1.f, 0.0f, 2.0f) + , _value(ValueInfo, 1.f, 0.0f, 2.0f) , _horizFieldOfView(HorizFieldOfViewInfo, 80.f, 1.f, 179.0f) , _globalRotation( GlobalRotationInfo, @@ -276,7 +298,7 @@ RenderEngine::RenderEngine() glm::vec3(0.f), glm::vec3(-glm::pi()), glm::vec3(glm::pi()) - ) + ) { _doPerformanceMeasurements.onChange([this](){ global::performanceManager.setEnabled(_doPerformanceMeasurements); @@ -295,20 +317,21 @@ RenderEngine::RenderEngine() }); addProperty(_nAaSamples); + _disableHDRPipeline.onChange([this]() { + if (_renderer) { + _renderer->disableHDR(_disableHDRPipeline); + } + }); + addProperty(_disableHDRPipeline); + + _hdrExposure.onChange([this]() { if (_renderer) { _renderer->setHDRExposure(_hdrExposure); } }); addProperty(_hdrExposure); - - _hdrBackground.onChange([this]() { - if (_renderer) { - _renderer->setHDRBackground(_hdrBackground); - } - }); - addProperty(_hdrBackground); - + _gamma.onChange([this]() { if (_renderer) { _renderer->setGamma(_gamma); @@ -316,6 +339,31 @@ RenderEngine::RenderEngine() }); addProperty(_gamma); + _hue.onChange([this]() { + if (_renderer) { + float pHue = (_hue + 180.f) / 360.f; + _renderer->setHue(pHue); + } + }); + + addProperty(_hue); + + _saturation.onChange([this]() { + if (_renderer) { + _renderer->setSaturation(_saturation); + } + }); + + addProperty(_saturation); + + _value.onChange([this]() { + if (_renderer) { + _renderer->setValue(_value); + } + }); + + addProperty(_value); + addProperty(_globalBlackOutFactor); addProperty(_applyWarping);