diff --git a/data/assets/scene/digitaluniverse/stars.asset b/data/assets/scene/digitaluniverse/stars.asset index 939667f169..72c4c14bb9 100644 --- a/data/assets/scene/digitaluniverse/stars.asset +++ b/data/assets/scene/digitaluniverse/stars.asset @@ -29,7 +29,10 @@ local object = { Type = "RenderableStars", File = speck .. "/stars.speck", Texture = textures .. "/halo.png", - ColorMap = colorLUT .. "/colorbv.cmap" + ColorMap = colorLUT .. "/colorbv.cmap", + MagnitudeExponent = 19, + BillboardSize = 30, + Sharpness = 1.3 }, GuiPath = "/Milky Way/Stars" } diff --git a/include/openspace/interaction/orbitalnavigator.h b/include/openspace/interaction/orbitalnavigator.h index 38c569b34b..b6ace82be8 100644 --- a/include/openspace/interaction/orbitalnavigator.h +++ b/include/openspace/interaction/orbitalnavigator.h @@ -84,13 +84,22 @@ private: properties::FloatProperty _minimumAllowedDistance; properties::FloatProperty _sensitivity; + properties::BoolProperty _useAdaptiveStereoscopicDepth; + properties::FloatProperty _stereoscopicDepthOfFocusSurface; + properties::FloatProperty _staticViewScaleExponent; + + properties::FloatProperty _rotateToFocusInterpolationTime; + properties::FloatProperty _stereoInterpolationTime; + MouseStates _mouseStates; SceneGraphNode* _focusNode = nullptr; glm::dvec3 _previousFocusNodePosition; glm::dquat _previousFocusNodeRotation; + double _currentCameraToSurfaceDistance; Interpolator _rotateToFocusNodeInterpolator; + Interpolator _cameraToSurfaceDistanceInterpolator; Interpolator _followRotationInterpolator; /** @@ -125,6 +134,11 @@ private: glm::dquat interpolateLocalRotation(double deltaTime, const glm::dquat& localCameraRotation); + + double interpolateCameraToSurfaceDistance(double deltaTime, + double currentDistance, + double targetDistance); + /** * Translates the horizontal direction. If far from the focus object, this will * result in an orbital rotation around the object. This function does not affect the @@ -193,6 +207,14 @@ private: const glm::dvec3& cameraPosition, const SurfacePositionHandle& positionHandle); + /** + * Get the vector from the camera to the surface of the focus object in world space. + */ + glm::dvec3 cameraToSurfaceVector( + const glm::dvec3& cameraPos, + const glm::dvec3& centerPos, + const SurfacePositionHandle& posHandle); + /** * Calculates a SurfacePositionHandle given a camera position in world space. */ diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index 470abafe84..506c2b1e25 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -82,6 +82,8 @@ public: void update() override; void render(float blackoutFactor, bool doPerformanceMeasurements) override; + void performRaycasterTasks(const std::vector& tasks); + void performDeferredTasks(const std::vector& tasks); /** * Update render data diff --git a/include/openspace/util/camera.h b/include/openspace/util/camera.h index 71dd85a0bc..d691f1181f 100644 --- a/include/openspace/util/camera.h +++ b/include/openspace/util/camera.h @@ -91,7 +91,7 @@ public: void setPositionVec3(Vec3 pos); void setFocusPositionVec3(Vec3 pos); void setRotation(Quat rotation); - void setScaling(glm::vec2 scaling); + void setScaling(float scaling); void setMaxFov(float fov); void setParent(SceneGraphNode* parent); @@ -101,17 +101,19 @@ public: // Accessors // Remove Vec3 from the name when psc is gone const Vec3& positionVec3() const; + const Vec3 eyePositionVec3() const; const Vec3& unsynchedPositionVec3() const; const Vec3& focusPositionVec3() const; const Vec3& viewDirectionWorldSpace() const; const Vec3& lookUpVectorCameraSpace() const; const Vec3& lookUpVectorWorldSpace() const; - const glm::vec2& scaling() const; const Mat4& viewRotationMatrix() const; + const Mat4& viewScaleMatrix() const; const Quat& rotationQuaternion() const; float maxFov() const; float sinMaxFov() const; SceneGraphNode* parent() const; + float scaling() const; // @TODO this should simply be called viewMatrix! // Or it needs to be changed so that it actually is combined. Right now it is @@ -170,6 +172,7 @@ public: psc unsynchedPosition() const; // [[deprecated("Replaced by Camera::focusPositionVec3()")]] psc focusPosition() const; + const glm::mat4& sceneMatrix() const; // @TODO use Camera::SgctInternal interface instead // [[deprecated("Replaced by Camera::SgctInternal::viewMatrix()")]] const glm::mat4& viewMatrix() const; @@ -186,10 +189,9 @@ private: SyncData _position; SyncData _rotation; - SyncData _scaling; + SyncData _scaling; SceneGraphNode* _parent; - // _focusPosition to be removed Vec3 _focusPosition; float _maxFov; @@ -198,6 +200,7 @@ private: mutable Cached _cachedViewDirection; mutable Cached _cachedLookupVector; mutable Cached _cachedViewRotationMatrix; + mutable Cached _cachedViewScaleMatrix; mutable Cached _cachedCombinedViewMatrix; mutable Cached _cachedSinMaxFov; diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 741477e8a0..e36fdb5511 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -247,17 +247,6 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& renderData, program.setUniform(_uniformCache2.dInverseModelTransformMatrix, inverseModelMatrix); program.setUniform(_uniformCache2.dModelTransformMatrix, _modelTransform); - /* - // The following scale comes from PSC transformations. - float fScaleFactor = renderData.camera.scaling().x * - pow(10.f, renderData.camera.scaling().y); - glm::dmat4 dfScaleCamTransf = glm::scale(glm::dvec3(fScaleFactor)); - program.setUniform( - "dInverseScaleTransformMatrix", - glm::inverse(dfScaleCamTransf) - ); - */ - // Eye Space in OS to Eye Space in SGCT glm::dmat4 dSgctEye2OSEye = glm::inverse( glm::dmat4(renderData.camera.viewMatrix())); diff --git a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl index 77b1fb2f83..4a0559a0bc 100644 --- a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl +++ b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl @@ -90,6 +90,7 @@ uniform dmat4 dInverseSGCTEyeToTmpRotTransformMatrix; uniform dmat4 dInverseSgctProjectionToModelTransformMatrix; uniform dvec4 dObjpos; +uniform dvec3 dCamRigPos; uniform dvec3 dCampos; uniform dvec4 dCamPosObj; uniform dvec3 sunDirectionObj; @@ -248,9 +249,7 @@ void dCalculateRayRenderableGlobe(in int mssaSample, out dRay ray, // ====================================== // ======= Avoiding Some Matrices ======= - // NDC to clip coordinates (gl_FragCoord.w = 1.0/w_clip) - // Using the interpolated coords: - // Assuming Red Book is right: z_ndc e [0, 1] and not [-1, 1] + // Compute positions and directions in world space. dvec2 samplePos = dvec2(msaaSamplePatter[mssaSample], msaaSamplePatter[mssaSample+1]); dvec4 clipCoords = dvec4(interpolatedNDCPos.xy + samplePos, interpolatedNDCPos.z, 1.0) / gl_FragCoord.w; @@ -297,6 +296,9 @@ vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor out vec3 attenuation, const vec3 fragPosObj, const double maxLength, const double pixelDepth, const vec4 spaceColor, const float sunIntensity) { + + const float INTERPOLATION_EPS = 0.004f; // precision const from Brunetton + vec3 radiance; r = length(x); @@ -328,7 +330,7 @@ vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor float mu0 = dot(x0, v) * invr0; bool groundHit = false; - if ((pixelDepth > 0.0) && (pixelDepth < maxLength)) { + if ((pixelDepth > INTERPOLATION_EPS) && (pixelDepth < maxLength)) { t = float(pixelDepth); groundHit = true; @@ -361,7 +363,6 @@ vec3 inscatterRadiance(inout vec3 x, inout float t, inout float irradianceFactor // In order to avoid imprecision problems near horizon, // we interpolate between two points: above and below horizon - const float INTERPOLATION_EPS = 0.004f; // precision const from Brunetton 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 diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index bf30e43fb2..be3e7e17f3 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -217,7 +217,7 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) { glm::vec3 directionToSun = glm::normalize(_sunPos - data.modelTransform.translation); glm::vec3 directionToSunViewSpace = - glm::mat3(data.camera.combinedViewMatrix()) * directionToSun; + glm::normalize(glm::mat3(data.camera.combinedViewMatrix()) * directionToSun); _programObject->setUniform( _uniformCache.directionToSunViewSpace, diff --git a/modules/globebrowsing/rendering/chunkrenderer.cpp b/modules/globebrowsing/rendering/chunkrenderer.cpp index 20c0e3d376..6f5c977397 100644 --- a/modules/globebrowsing/rendering/chunkrenderer.cpp +++ b/modules/globebrowsing/rendering/chunkrenderer.cpp @@ -263,7 +263,7 @@ void ChunkRenderer::setCommonUniforms(ghoul::opengl::ProgramObject& programObjec glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform * glm::dvec4(directionToSunWorldSpace, 0)); programObject.setUniform( - "lightDirectionCameraSpace", -directionToSunCameraSpace); + "lightDirectionCameraSpace", -glm::normalize(directionToSunCameraSpace)); } if (chunk.owner().generalProperties().performShading) { @@ -374,7 +374,7 @@ void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& da { // Apply an extra scaling to the height if the object is scaled programObject->setUniform( - "heightScale", static_cast(data.modelTransform.scale)); + "heightScale", static_cast(data.modelTransform.scale * data.camera.scaling())); } setCommonUniforms(*programObject, chunk, data); @@ -469,7 +469,7 @@ void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& dat if (_layerManager->layerGroup(layergroupid::HeightLayers).activeLayers().size() > 0) { // Apply an extra scaling to the height if the object is scaled programObject->setUniform( - "heightScale", static_cast(data.modelTransform.scale)); + "heightScale", static_cast(data.modelTransform.scale * data.camera.scaling())); } setCommonUniforms(*programObject, chunk, data); diff --git a/modules/imgui/imguimodule.cpp b/modules/imgui/imguimodule.cpp index 0a17c7da73..c1fb84a8d9 100644 --- a/modules/imgui/imguimodule.cpp +++ b/modules/imgui/imguimodule.cpp @@ -176,8 +176,10 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { WindowWrapper& wrapper = OsEng.windowWrapper(); bool showGui = wrapper.hasGuiWindow() ? wrapper.isGuiWindow() : true; if (wrapper.isMaster() && showGui) { + const glm::ivec2 windowSize = wrapper.currentWindowSize(); + const glm::ivec2 resolution = wrapper.currentWindowResolution(); + glm::vec2 mousePosition = wrapper.mousePosition(); - glm::ivec2 windowSize = wrapper.currentWindowSize(); uint32_t mouseButtons = wrapper.mouseButtons(2); double dt = std::max(wrapper.averageDeltaTime(), 0.0); @@ -190,7 +192,7 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { gui.startFrame( static_cast(dt), glm::vec2(windowSize), - wrapper.dpiScaling(), + resolution / windowSize, mousePosition, mouseButtons ); diff --git a/modules/space/rendering/renderablestars.cpp b/modules/space/rendering/renderablestars.cpp index 36b25de8da..e7f04183e3 100644 --- a/modules/space/rendering/renderablestars.cpp +++ b/modules/space/rendering/renderablestars.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -100,25 +101,24 @@ namespace { "stars." }; - static const openspace::properties::Property::PropertyInfo TransparencyInfo = { - "Transparency", - "Transparency", - "This value is a multiplicative factor that is applied to the transparency of " - "all stars." + static const openspace::properties::Property::PropertyInfo MagnitudeExponentInfo = { + "MagnitudeExponent", + "MagnitudeExponent", + "Adjust star magnitude by 10^MagnitudeExponent. " + "Stars closer than this distance are given full opacity. " + "Farther away, stars dim proportionally to the logarithm of their distance." }; - static const openspace::properties::Property::PropertyInfo ScaleFactorInfo = { - "ScaleFactor", - "Scale Factor", - "This value is used as a multiplicative factor that is applied to the apparent " - "size of each star." + static const openspace::properties::Property::PropertyInfo SharpnessInfo = { + "Sharpness", + "Sharpness", + "Adjust star sharpness" }; - static const openspace::properties::Property::PropertyInfo MinBillboardSizeInfo = { - "MinBillboardSize", - "Min Billboard Size", - "This value is used as a lower limit on the size of stars that are rendered. Any " - "stars that have a smaller apparent size will be discarded entirely." + static const openspace::properties::Property::PropertyInfo BillboardSizeInfo = { + "BillboardSize", + "Billboard Size", + "Set the billboard size of all stars" }; } // namespace @@ -163,22 +163,22 @@ documentation::Documentation RenderableStars::Documentation() { ColorOptionInfo.description }, { - TransparencyInfo.identifier, + MagnitudeExponentInfo.identifier, new DoubleVerifier, Optional::Yes, - TransparencyInfo.description + MagnitudeExponentInfo.description }, { - ScaleFactorInfo.identifier, + SharpnessInfo.identifier, new DoubleVerifier, Optional::Yes, - ScaleFactorInfo.description + SharpnessInfo.description }, { - MinBillboardSizeInfo.identifier, + BillboardSizeInfo.identifier, new DoubleVerifier, Optional::Yes, - MinBillboardSizeInfo.description + BillboardSizeInfo.description } } }; @@ -194,9 +194,9 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) , _colorTextureIsDirty(true) , _colorOption(ColorOptionInfo, properties::OptionProperty::DisplayType::Dropdown) , _dataIsDirty(true) - , _alphaValue(TransparencyInfo, 1.f, 0.f, 1.f) - , _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 10.f) - , _minBillboardSize(MinBillboardSizeInfo, 1.f, 1.f, 100.f) + , _magnitudeExponent(MagnitudeExponentInfo, 19.f, 0.f, 30.f) + , _sharpness(SharpnessInfo, 1.f, 0.f, 5.f) + , _billboardSize(BillboardSizeInfo, 30.f, 1.f, 100.f) , _program(nullptr) , _speckFile("") , _nValuesPerStar(0) @@ -259,26 +259,26 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) ); addProperty(_colorTexturePath); - if (dictionary.hasKey(TransparencyInfo.identifier)) { - _alphaValue = static_cast( - dictionary.value(TransparencyInfo.identifier) + if (dictionary.hasKey(MagnitudeExponentInfo.identifier)) { + _magnitudeExponent = static_cast( + dictionary.value(MagnitudeExponentInfo.identifier) ); } - addProperty(_alphaValue); + addProperty(_magnitudeExponent); - if (dictionary.hasKey(ScaleFactorInfo.identifier)) { - _scaleFactor = static_cast( - dictionary.value(ScaleFactorInfo.identifier) - ); + if (dictionary.hasKey(SharpnessInfo.identifier)) { + _sharpness = static_cast( + dictionary.value(SharpnessInfo.identifier) + ); } - addProperty(_scaleFactor); + addProperty(_sharpness); - if (dictionary.hasKey(MinBillboardSizeInfo.identifier)) { - _minBillboardSize = static_cast( - dictionary.value(MinBillboardSizeInfo.identifier) + if (dictionary.hasKey(BillboardSizeInfo.identifier)) { + _billboardSize = static_cast( + dictionary.value(BillboardSizeInfo.identifier) ); } - addProperty(_minBillboardSize); + addProperty(_billboardSize); } RenderableStars::~RenderableStars() {} @@ -295,14 +295,15 @@ void RenderableStars::initializeGL() { absPath("${MODULE_SPACE}/shaders/star_ge.glsl") ); + _uniformCache.model = _program->uniformLocation("model"); _uniformCache.view = _program->uniformLocation("view"); + _uniformCache.viewScaling = _program->uniformLocation("viewScaling"); _uniformCache.projection = _program->uniformLocation("projection"); _uniformCache.colorOption = _program->uniformLocation("colorOption"); - _uniformCache.alphaValue = _program->uniformLocation("alphaValue"); - _uniformCache.scaleFactor = _program->uniformLocation("scaleFactor"); - _uniformCache.minBillboardSize = _program->uniformLocation("minBillboardSize"); + _uniformCache.magnitudeExponent = _program->uniformLocation("magnitudeExponent"); + _uniformCache.sharpness = _program->uniformLocation("sharpness"); + _uniformCache.billboardSize = _program->uniformLocation("billboardSize"); _uniformCache.screenSize = _program->uniformLocation("screenSize"); - _uniformCache.scaling = _program->uniformLocation("scaling"); _uniformCache.psfTexture = _program->uniformLocation("psfTexture"); _uniformCache.colorTexture = _program->uniformLocation("colorTexture"); @@ -329,28 +330,34 @@ void RenderableStars::deinitializeGL() { } void RenderableStars::render(const RenderData& data, RendererTasks&) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDepthMask(false); + _program->activate(); - // @Check overwriting the scaling from the camera; error as parsec->meter conversion - // is done twice? ---abock - glm::vec2 scaling = glm::vec2(1, -19); + glm::mat4 model = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * + glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); - _program->setUniform(_uniformCache.view, data.camera.viewMatrix()); - _program->setUniform(_uniformCache.projection, data.camera.projectionMatrix()); + glm::mat4 view = data.camera.combinedViewMatrix(); + glm::mat4 projection = data.camera.projectionMatrix(); + float viewScaling = data.camera.scaling(); + + _program->setUniform(_uniformCache.model, model); + _program->setUniform(_uniformCache.view, view); + _program->setUniform(_uniformCache.projection, projection); + _program->setUniform(_uniformCache.viewScaling, viewScaling); _program->setUniform(_uniformCache.colorOption, _colorOption); - _program->setUniform(_uniformCache.alphaValue, _alphaValue); - _program->setUniform(_uniformCache.scaleFactor, _scaleFactor); - _program->setUniform(_uniformCache.minBillboardSize, _minBillboardSize); + _program->setUniform(_uniformCache.magnitudeExponent, _magnitudeExponent); + _program->setUniform(_uniformCache.sharpness, _sharpness); + _program->setUniform(_uniformCache.billboardSize, _billboardSize); _program->setUniform( _uniformCache.screenSize, glm::vec2(OsEng.renderEngine().renderingResolution()) ); - setPscUniforms(*_program.get(), data.camera, data.position); - _program->setUniform(_uniformCache.scaling, scaling); - ghoul::opengl::TextureUnit psfUnit; psfUnit.activate(); _pointSpreadFunctionTexture->bind(); @@ -369,6 +376,7 @@ void RenderableStars::render(const RenderData& data, RendererTasks&) { _program->deactivate(); glDepthMask(true); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void RenderableStars::update(const UpdateData&) { @@ -555,14 +563,15 @@ void RenderableStars::update(const UpdateData&) { if (_program->isDirty()) { _program->rebuildFromFile(); + _uniformCache.model = _program->uniformLocation("model"); _uniformCache.view = _program->uniformLocation("view"); + _uniformCache.viewScaling = _program->uniformLocation("viewScaling"); _uniformCache.projection = _program->uniformLocation("projection"); _uniformCache.colorOption = _program->uniformLocation("colorOption"); - _uniformCache.alphaValue = _program->uniformLocation("alphaValue"); - _uniformCache.scaleFactor = _program->uniformLocation("scaleFactor"); - _uniformCache.minBillboardSize = _program->uniformLocation("minBillboardSize"); + _uniformCache.magnitudeExponent = _program->uniformLocation("magnitudeExponent"); + _uniformCache.sharpness = _program->uniformLocation("sharpness"); + _uniformCache.billboardSize = _program->uniformLocation("billboardSize"); _uniformCache.screenSize = _program->uniformLocation("screenSize"); - _uniformCache.scaling = _program->uniformLocation("scaling"); _uniformCache.psfTexture = _program->uniformLocation("psfTexture"); _uniformCache.colorTexture = _program->uniformLocation("colorTexture"); } @@ -742,51 +751,20 @@ bool RenderableStars::saveCachedFile(const std::string& file) const { void RenderableStars::createDataSlice(ColorOption option) { _slicedData.clear(); - // This is only temporary until the scalegraph is in place ---abock - float minDistance = std::numeric_limits::max(); - float maxDistance = -std::numeric_limits::max(); - - for (size_t i = 0; i < _fullData.size(); i+=_nValuesPerStar) { - float distLy = _fullData[i + 6]; - //if (distLy < 20.f) { - minDistance = std::min(minDistance, distLy); - maxDistance = std::max(maxDistance, distLy); - //} - } - for (size_t i = 0; i < _fullData.size(); i+=_nValuesPerStar) { glm::vec3 p = glm::vec3(_fullData[i + 0], _fullData[i + 1], _fullData[i + 2]); - - // This is only temporary until the scalegraph is in place. It places all stars - // on a sphere with a small variation in the distance to account for blending - // issues ---abock - //if (p != glm::vec3(0.f)) - // p = glm::normalize(p); - - //float distLy = _fullData[i + 6]; - //float normalizedDist = (distLy - minDistance) / (maxDistance - minDistance); - //float distance = 18.f - normalizedDist / 1.f ; - - - //psc position = psc(glm::vec4(p, distance)); - - // Convert parsecs -> meter - psc position = psc(glm::vec4(p * 0.308567756f, 17)); - - //position[1] *= parsecsToMetersFactor[0]; - //position[2] *= parsecsToMetersFactor[0]; - //position[3] += parsecsToMetersFactor[1]; + p *= openspace::distanceconstants::Parsec; switch (option) { case ColorOption::Color: { union { ColorVBOLayout value; - std::array data; + std::array data; } layout; layout.value.position = { { - position[0], position[1], position[2], position[3] + p[0], p[1], p[2], 1.0 } }; #ifdef USING_STELLAR_TEST_GRID @@ -809,11 +787,11 @@ void RenderableStars::createDataSlice(ColorOption option) { { union { VelocityVBOLayout value; - std::array data; + std::array data; } layout; layout.value.position = { { - position[0], position[1], position[2], position[3] + p[0], p[1], p[2], 1.0 } }; layout.value.bvColor = _fullData[i + 3]; @@ -833,11 +811,11 @@ void RenderableStars::createDataSlice(ColorOption option) { { union { SpeedVBOLayout value; - std::array data; + std::array data; } layout; layout.value.position = { { - position[0], position[1], position[2], position[3] + p[0], p[1], p[2], 1.0 } }; layout.value.bvColor = _fullData[i + 3]; diff --git a/modules/space/rendering/renderablestars.h b/modules/space/rendering/renderablestars.h index fd2cd92e5a..3e8ced2282 100644 --- a/modules/space/rendering/renderablestars.h +++ b/modules/space/rendering/renderablestars.h @@ -86,13 +86,13 @@ private: properties::OptionProperty _colorOption; bool _dataIsDirty; - properties::FloatProperty _alphaValue; - properties::FloatProperty _scaleFactor; - properties::FloatProperty _minBillboardSize; + properties::FloatProperty _magnitudeExponent; + properties::FloatProperty _sharpness; + properties::FloatProperty _billboardSize; std::unique_ptr _program; - UniformCache(view, projection, colorOption, alphaValue, scaleFactor, - minBillboardSize, screenSize, scaling, psfTexture, colorTexture) _uniformCache; + UniformCache(model, view, viewScaling, projection, colorOption, magnitudeExponent, sharpness, + billboardSize, screenSize, scaling, psfTexture, colorTexture) _uniformCache; std::string _speckFile; diff --git a/modules/space/shaders/star_fs.glsl b/modules/space/shaders/star_fs.glsl index 9ee5b90c4f..0c53b621b2 100644 --- a/modules/space/shaders/star_fs.glsl +++ b/modules/space/shaders/star_fs.glsl @@ -23,7 +23,7 @@ ****************************************************************************************/ #include "fragment.glsl" -#include "PowerScaling/powerScaling_fs.hglsl" +#include "floatoperations.glsl" // keep in sync with renderablestars.h:ColorOption enum const int COLOROPTION_COLOR = 0; @@ -32,9 +32,9 @@ const int COLOROPTION_SPEED = 2; uniform sampler2D psfTexture; uniform sampler1D colorTexture; -uniform float minBillboardSize; -uniform float alphaValue; +uniform float magnitudeExponent; +uniform float sharpness; uniform int colorOption; in vec4 vs_position; @@ -43,13 +43,7 @@ in vec3 ge_brightness; in vec3 ge_velocity; in float ge_speed; in vec2 texCoord; -in float billboardSize; - -#include "fragment.glsl" -//#include "PowerScaling/powerScaling_fs.hglsl" - -uniform vec2 magnitudeClamp; - +in float ge_observationDistance; vec4 bv2rgb(float bv) { // BV is [-0.4,2.0] @@ -60,7 +54,7 @@ vec4 bv2rgb(float bv) { Fragment getFragment() { // Something in the color calculations need to be changed because before it was dependent // on the gl blend functions since the abuffer was not involved - + vec4 color = vec4(0.0); switch (colorOption) { case COLOROPTION_COLOR: @@ -77,19 +71,15 @@ Fragment getFragment() { vec4 textureColor = texture(psfTexture, texCoord); vec4 fullColor = vec4(color.rgb, textureColor.a); - fullColor.a *= alphaValue; + fullColor.a = pow(fullColor.a, sharpness); - vec4 position = vs_position; - // This has to be fixed when the scale graph is in place ---emiax - position.w = 15; + float d = magnitudeExponent - log(ge_observationDistance) / log(10.0); + fullColor.a *= clamp(d, 0.0, 1.0); Fragment frag; frag.color = fullColor; - frag.depth = pscDepth(position); - - // G-Buffer + frag.depth = safeLength(vs_position); frag.gPosition = ge_gPosition; - // There is no normal here frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); if (fullColor.a == 0) { diff --git a/modules/space/shaders/star_ge.glsl b/modules/space/shaders/star_ge.glsl index b6fc81b941..3b2b95573c 100644 --- a/modules/space/shaders/star_ge.glsl +++ b/modules/space/shaders/star_ge.glsl @@ -24,15 +24,14 @@ #version __CONTEXT__ -#include "PowerScaling/powerScalingMath.hglsl" +#include "floatoperations.glsl" layout(points) in; -in vec4 psc_position[]; + in vec3 vs_brightness[]; in vec3 vs_velocity[]; in vec4 vs_gPosition[]; in float vs_speed[]; -in vec4 cam_position[]; layout(triangle_strip, max_vertices = 4) out; @@ -42,12 +41,11 @@ out vec3 ge_brightness; out vec3 ge_velocity; out float ge_speed; out vec2 texCoord; -out float billboardSize; - -uniform mat4 projection; +out float ge_observationDistance; +uniform float viewScaling; uniform float scaleFactor; -uniform float minBillboardSize; +uniform float billboardSize; uniform vec2 screenSize; const vec2 corners[4] = vec2[4]( @@ -57,50 +55,27 @@ const vec2 corners[4] = vec2[4]( vec2(1.0, 0.0) ); - void main() { - // JCC: We want to display the Sun. - // if ((psc_position[0].x == 0.0) && - // (psc_position[0].y == 0.0) && - // (psc_position[0].z == 0.0)) - // { - // return; - // } - ge_brightness = vs_brightness[0]; ge_velocity = vs_velocity[0]; ge_speed = vs_speed[0]; float absoluteMagnitude = vs_brightness[0].z; - float modifiedSpriteSize = - exp((-30.623 - absoluteMagnitude) * 0.462) * scaleFactor * 2000; - vec4 projPos[4]; - for (int i = 0; i < 4; ++i) { - vec4 p1 = gl_in[0].gl_Position; - p1.xy += vec2(modifiedSpriteSize * (corners[i] - vec2(0.5))); - projPos[i] = projection * p1; - } - - // Calculate the positions of the lower left and upper right corners of the - // billboard in screen-space - vec2 ll = (((projPos[1].xy / projPos[1].w) + 1.0) / 2.0) * screenSize; - vec2 ur = (((projPos[2].xy / projPos[2].w) + 1.0) / 2.0) * screenSize; - - // The billboard is smaller than one pixel, we can discard it - float sizeInPixels = length(ll - ur); - if (sizeInPixels < minBillboardSize) { - return; - } + vec4 projectedPoint = gl_in[0].gl_Position; + vec2 starSize = vec2(billboardSize) / screenSize * projectedPoint.w; for (int i = 0; i < 4; i++) { vs_position = gl_in[0].gl_Position; - gl_Position = projPos[i]; + gl_Position = projectedPoint + vec4(starSize * (corners[i] - 0.5), 0.0, 0.0); + gl_Position.z = 0.0; + texCoord = corners[i]; // G-Buffer ge_gPosition = vs_gPosition[0]; - billboardSize = sizeInPixels; + ge_observationDistance = safeLength(vs_gPosition[0] / viewScaling); + EmitVertex(); } diff --git a/modules/space/shaders/star_vs.glsl b/modules/space/shaders/star_vs.glsl index 7ff61c0f5e..594bcfbc5a 100644 --- a/modules/space/shaders/star_vs.glsl +++ b/modules/space/shaders/star_vs.glsl @@ -31,30 +31,24 @@ in vec3 in_brightness; in vec3 in_velocity; in float in_speed; -out vec4 psc_position; out vec3 vs_brightness; out vec3 vs_velocity; out float vs_speed; out vec4 vs_gPosition; +uniform mat4 model; uniform mat4 view; uniform mat4 projection; - void main() { - vec4 p = in_position; - psc_position = p; vs_brightness = in_brightness; vs_velocity = in_velocity; vs_speed = in_speed; - vec4 tmp = p; - vec4 position = pscTransform(tmp, mat4(1.0)); - - // G-Buffer - vs_gPosition = view * (vec4(1E19, 1E19, 1E19, 1.0) * position); - - position = view * position; - - gl_Position = position; + vec3 modelPosition = in_position.xyz; + + vec4 viewPosition = view * model * vec4(modelPosition, 1.0); + + vs_gPosition = viewPosition; + gl_Position = projection * vs_gPosition; } diff --git a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp index ae5f31066c..3bb4fd0473 100644 --- a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp @@ -556,7 +556,7 @@ void RenderablePlanetProjection::render(const RenderData& data, RendererTasks&) _projectionComponent.generateMipMap(); } - _camScaling = data.camera.scaling(); + _camScaling = glm::vec2(1, 0); // Unit scaling _up = data.camera.lookUpVectorCameraSpace(); if (_capture && _projectionComponent.doesPerformProjection()) { diff --git a/src/engine/wrapper/sgctwindowwrapper.cpp b/src/engine/wrapper/sgctwindowwrapper.cpp index fef3b7b9ff..d9f2801978 100644 --- a/src/engine/wrapper/sgctwindowwrapper.cpp +++ b/src/engine/wrapper/sgctwindowwrapper.cpp @@ -51,7 +51,7 @@ namespace { namespace openspace { SGCTWindowWrapper::SGCTWindowWrapper() - : _eyeSeparation(EyeSeparationInfo, 0.f, 0.f, 10.f) + : _eyeSeparation(EyeSeparationInfo, 0.f, 0.f, 0.2f) , _showStatsGraph(ShowStatsGraphInfo, false) { _showStatsGraph.onChange([this](){ diff --git a/src/interaction/orbitalnavigator.cpp b/src/interaction/orbitalnavigator.cpp index 6642f22ebe..f95c9fb7b7 100644 --- a/src/interaction/orbitalnavigator.cpp +++ b/src/interaction/orbitalnavigator.cpp @@ -84,6 +84,49 @@ namespace { "Minimum allowed distance", "" // @TODO Missing documentation }; + + static const openspace::properties::Property::PropertyInfo + StereoInterpolationTimeInfo = { + "StereoInterpolationTime", + "Stereo interpolation time", + "The time to interpolate to a new stereoscopic depth " + "when the focus node is changed" + }; + + static const openspace::properties::Property::PropertyInfo + RotateToFocusInterpolationTimeInfo = { + "RotateToFocusInterpolationTime", + "Rotate to focus interpolation time", + "The time to interpolate the camera rotation " + "when the focus node is changed" + }; + + static const openspace::properties::Property::PropertyInfo + UseAdaptiveStereoscopicDepthInfo = { + "UseAdaptiveStereoscopicDepth", + "Adaptive Steroscopic Depth", + "Dynamically adjust the view scaling based on the distance to the surface of " + "the focus node. If enabled, view scale will be set to " + "StereoscopicDepthOfFocusSurface / distance. " + "If disabled, view scale will be set to 10^StaticViewScaleExponent." + }; + + static const openspace::properties::Property::PropertyInfo + StaticViewScaleExponentInfo = { + "StaticViewScaleExponent", + "Static View Scale Exponent", + "Statically scale the world by 10^StaticViewScaleExponent. " + "Only used if UseAdaptiveStereoscopicDepthInfo is set to false." + }; + + static const openspace::properties::Property::PropertyInfo + StereoscopicDepthOfFocusSurfaceInfo = { + "StereoscopicDepthOfFocusSurface", + "Stereoscopic depth of the surface in focus", + "Set the stereoscopically perceived distance (in meters) to the surface of " + "the focus node. " + "Only used if UseAdaptiveStereoscopicDepthInfo is set to true." + }; } // namespace namespace openspace::interaction { @@ -107,6 +150,11 @@ OrbitalNavigator::OrbitalNavigator() , _minimumAllowedDistance(MinimumDistanceInfo, 10.0f, 0.0f, 10000.f) , _sensitivity(SensitivityInfo, 15.0f, 1.0f, 50.f) , _mouseStates(_sensitivity * pow(10.0, -4), 1 / (_friction.friction + 0.0000001)) + , _useAdaptiveStereoscopicDepth(UseAdaptiveStereoscopicDepthInfo, true) + , _staticViewScaleExponent(StaticViewScaleExponentInfo, 0.f, -30, 10) + , _stereoscopicDepthOfFocusSurface(StereoscopicDepthOfFocusSurfaceInfo, 8, 0.25, 100) + , _rotateToFocusInterpolationTime(RotateToFocusInterpolationTimeInfo, 2.0, 0.0, 10.0) + , _stereoInterpolationTime(StereoInterpolationTimeInfo, 8.0, 0.0, 10.0) { auto smoothStep = [](double t) { @@ -134,6 +182,7 @@ OrbitalNavigator::OrbitalNavigator() return (6 * (t + t*t) / (1 - 3 * t*t + 2 * t*t*t)); }; _rotateToFocusNodeInterpolator.setTransferFunction(smoothStepDerivedTranferFunction); + _cameraToSurfaceDistanceInterpolator.setTransferFunction(smoothStepDerivedTranferFunction); // Define callback functions for changed properties _friction.roll.onChange([&]() { @@ -158,6 +207,13 @@ OrbitalNavigator::OrbitalNavigator() addProperty(_followFocusNodeRotationDistance); addProperty(_minimumAllowedDistance); addProperty(_sensitivity); + + addProperty(_useAdaptiveStereoscopicDepth); + addProperty(_staticViewScaleExponent); + addProperty(_stereoscopicDepthOfFocusSurface); + + addProperty(_rotateToFocusInterpolationTime); + addProperty(_stereoInterpolationTime); } OrbitalNavigator::~OrbitalNavigator() {} @@ -263,9 +319,43 @@ void OrbitalNavigator::updateCameraStateFromMouseStates(Camera& camera, double d // Update the camera state camera.setPositionVec3(camPos); camera.setRotation(camRot.globalRotation * camRot.localRotation); + + if (_useAdaptiveStereoscopicDepth) { + double targetCameraToSurfaceDistance = glm::length( + cameraToSurfaceVector(camPos, centerPos, posHandle) + ); + _currentCameraToSurfaceDistance = interpolateCameraToSurfaceDistance( + deltaTime, + _currentCameraToSurfaceDistance, + targetCameraToSurfaceDistance); + + camera.setScaling( + _stereoscopicDepthOfFocusSurface / + static_cast(_currentCameraToSurfaceDistance) + ); + } else { + camera.setScaling(glm::pow(10.f, _staticViewScaleExponent)); + } } } +glm::dvec3 OrbitalNavigator::cameraToSurfaceVector( + const glm::dvec3& camPos, + const glm::dvec3& centerPos, + const SurfacePositionHandle& posHandle) +{ + glm::dmat4 modelTransform = _focusNode->modelTransform(); + glm::dvec3 posDiff = camPos - centerPos; + glm::dvec3 centerToActualSurfaceModelSpace = + posHandle.centerToReferenceSurface + + posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface; + + glm::dvec3 centerToActualSurface = + glm::dmat3(modelTransform) * centerToActualSurfaceModelSpace; + + return centerToActualSurface - posDiff; +} + void OrbitalNavigator::setFocusNode(SceneGraphNode* focusNode) { _focusNode = focusNode; @@ -287,9 +377,12 @@ void OrbitalNavigator::startInterpolateCameraDirection(const Camera& camera) { // Minimum is two second. Otherwise proportional to angle _rotateToFocusNodeInterpolator.setInterpolationTime(static_cast( - glm::max(angle * 2.0, 2.0) + glm::max(angle, 1.0) * _rotateToFocusInterpolationTime )); _rotateToFocusNodeInterpolator.start(); + + _cameraToSurfaceDistanceInterpolator.setInterpolationTime(_stereoInterpolationTime); + _cameraToSurfaceDistanceInterpolator.start(); } bool OrbitalNavigator::followingNodeRotation() const { @@ -367,24 +460,48 @@ glm::dquat OrbitalNavigator::rotateLocally(double deltaTime, } glm::dquat OrbitalNavigator::interpolateLocalRotation(double deltaTime, - const glm::dquat& localCameraRotation) + const glm::dquat& localCameraRotation) { - if (_rotateToFocusNodeInterpolator.isInterpolating()) { - double t = _rotateToFocusNodeInterpolator.value(); - _rotateToFocusNodeInterpolator.setDeltaTime(static_cast(deltaTime)); - _rotateToFocusNodeInterpolator.step(); - glm::dquat result = glm::slerp( - localCameraRotation, - glm::dquat(glm::dvec3(0.0)), - glm::min(t * _rotateToFocusNodeInterpolator.deltaTimeScaled(), 1.0)); - if (angle(result) < 0.01) { - _rotateToFocusNodeInterpolator.end(); - } - return result; - } - else { + if (!_rotateToFocusNodeInterpolator.isInterpolating()) { return localCameraRotation; } + double t = _rotateToFocusNodeInterpolator.value(); + _rotateToFocusNodeInterpolator.setDeltaTime(static_cast(deltaTime)); + _rotateToFocusNodeInterpolator.step(); + glm::dquat result = glm::slerp( + localCameraRotation, + glm::dquat(glm::dvec3(0.0)), + glm::min(t * _rotateToFocusNodeInterpolator.deltaTimeScaled(), 1.0)); + if (angle(result) < 0.01) { + _rotateToFocusNodeInterpolator.end(); + } + return result; +} + +double OrbitalNavigator::interpolateCameraToSurfaceDistance(double deltaTime, + double currentDistance, + double targetDistance +) { + if (!_cameraToSurfaceDistanceInterpolator.isInterpolating()) { + return targetDistance; + } + + double t = _cameraToSurfaceDistanceInterpolator.value(); + _cameraToSurfaceDistanceInterpolator.setDeltaTime(static_cast(deltaTime)); + _cameraToSurfaceDistanceInterpolator.step(); + + // Interpolate distance logarithmically. + double result = glm::exp(glm::mix( + glm::log(currentDistance), + glm::log(targetDistance), + glm::min(t * _cameraToSurfaceDistanceInterpolator.deltaTimeScaled(), 1.0))); + + double ratio = currentDistance / targetDistance; + if (glm::abs(ratio - 1.0) < 0.000001) { + _cameraToSurfaceDistanceInterpolator.end(); + } + + return result; } glm::dvec3 OrbitalNavigator::translateHorizontally(double deltaTime, diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 65507ea931..3d953ae03e 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -1,26 +1,26 @@ /***************************************************************************************** - * * - * 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. * - ****************************************************************************************/ +* * +* 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. * +****************************************************************************************/ #include @@ -66,1309 +66,1324 @@ namespace { } // namespace namespace openspace { -void saveTextureToPPMFile(const GLenum color_buffer_attachment, - const std::string & fileName, - const int width, const int height); + void saveTextureToPPMFile(const GLenum color_buffer_attachment, + const std::string & fileName, + const int width, const int height); -void saveTextureToMemory(const GLenum color_buffer_attachment, - const int width, const int height, std::vector & memory); + void saveTextureToMemory(const GLenum color_buffer_attachment, + const int width, const int height, std::vector & memory); -FramebufferRenderer::FramebufferRenderer() - : _camera(nullptr) - , _scene(nullptr) - , _resolution(glm::vec2(0)) - , _hdrExposure(0.4f) - , _hdrBackground(2.8f) - , _gamma(2.2f) -{} + FramebufferRenderer::FramebufferRenderer() + : _camera(nullptr) + , _scene(nullptr) + , _resolution(glm::vec2(0)) + , _hdrExposure(0.4f) + , _hdrBackground(2.8f) + , _gamma(2.2f) + {} -FramebufferRenderer::~FramebufferRenderer() {} + FramebufferRenderer::~FramebufferRenderer() {} -void FramebufferRenderer::initialize() { - LDEBUG("Initializing FramebufferRenderer"); + void FramebufferRenderer::initialize() { + LDEBUG("Initializing FramebufferRenderer"); - const GLfloat size = 1.0f; - const GLfloat vertex_data[] = { - // x y s t - -size, -size, 0.0f, 1.0f, - size, size, 0.0f, 1.0f, - -size, size, 0.0f, 1.0f, - -size, -size, 0.0f, 1.0f, - size, -size, 0.0f, 1.0f, - size, size, 0.0f, 1.0f - }; + const GLfloat size = 1.0f; + const GLfloat vertex_data[] = { + // x y s t + -size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + -size, size, 0.0f, 1.0f, + -size, -size, 0.0f, 1.0f, + size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f + }; - glGenVertexArrays(1, &_screenQuad); - glBindVertexArray(_screenQuad); + glGenVertexArrays(1, &_screenQuad); + glBindVertexArray(_screenQuad); - glGenBuffers(1, &_vertexPositionBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glGenBuffers(1, &_vertexPositionBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - glVertexAttribPointer( - 0, - 4, - GL_FLOAT, - GL_FALSE, - sizeof(GLfloat) * 4, - nullptr - ); - glEnableVertexAttribArray(0); - - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - - // Main framebuffer - glGenTextures(1, &_mainColorTexture); - glGenTextures(1, &_mainDepthTexture); - glGenFramebuffers(1, &_mainFramebuffer); - - // 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); - - updateResolution(); - updateRendererData(); - updateRaycastData(); - - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D_MULTISAMPLE, - _mainColorTexture, - 0 - ); - // G-buffer - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT1, - GL_TEXTURE_2D_MULTISAMPLE, - _mainPositionTexture, - 0 - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT2, - GL_TEXTURE_2D_MULTISAMPLE, - _mainNormalTexture, - 0 - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D_MULTISAMPLE, - _mainDepthTexture, - 0 - ); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("Main framebuffer is not complete"); - } - - glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - _exitColorTexture, - 0 - ); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_TEXTURE_2D, - _exitDepthTexture, - 0 - ); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("Exit framebuffer is not complete"); - } - - glBindFramebuffer(GL_FRAMEBUFFER, _deferredFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - _deferredColorTexture, - 0 - ); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("Deferred framebuffer is not complete"); - } - - // JCC: Moved to here to avoid NVidia: "Program/shader state performance warning" - updateHDRData(); - updateDeferredcastData(); - updateMSAASamplingPattern(); - - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - - _resolveProgram = ghoul::opengl::ProgramObject::Build( - "Framebuffer Resolve", - absPath("${SHADERS}/framebuffer/resolveframebuffer.vert"), - absPath("${SHADERS}/framebuffer/resolveframebuffer.frag") - ); - - _uniformCache.mainColorTexture = _resolveProgram->uniformLocation("mainColorTexture"); - _uniformCache.blackoutFactor = _resolveProgram->uniformLocation("blackoutFactor"); - _uniformCache.nAaSamples = _resolveProgram->uniformLocation("nAaSamples"); - - OsEng.renderEngine().raycasterManager().addListener(*this); - OsEng.renderEngine().deferredcasterManager().addListener(*this); -} - -void FramebufferRenderer::deinitialize() { - LINFO("Deinitializing FramebufferRenderer"); - - glDeleteFramebuffers(1, &_mainFramebuffer); - glDeleteFramebuffers(1, &_exitFramebuffer); - glDeleteFramebuffers(1, &_deferredFramebuffer); - - glDeleteTextures(1, &_mainColorTexture); - glDeleteTextures(1, &_mainDepthTexture); - - // DEBUG: deferred g-buffer - glDeleteTextures(1, &_deferredColorTexture); - glDeleteTextures(1, &_mainPositionTexture); - glDeleteTextures(1, &_mainNormalTexture); - - glDeleteTextures(1, &_exitColorTexture); - glDeleteTextures(1, &_exitDepthTexture); - - glDeleteBuffers(1, &_vertexPositionBuffer); - glDeleteVertexArrays(1, &_screenQuad); - - OsEng.renderEngine().raycasterManager().removeListener(*this); - OsEng.renderEngine().deferredcasterManager().removeListener(*this); -} - -void FramebufferRenderer::raycastersChanged(VolumeRaycaster&, bool) { - _dirtyRaycastData = true; -} - -void FramebufferRenderer::deferredcastersChanged(Deferredcaster& deferredcaster, - ghoul::Boolean isAttached) -{ - (void) deferredcaster; - (void) isAttached; - _dirtyDeferredcastData = true; -} - -void FramebufferRenderer::update() { - if (_dirtyResolution) { - updateResolution(); - updateMSAASamplingPattern(); - } - - if (_dirtyRaycastData) { - updateRaycastData(); - } - - if (_dirtyDeferredcastData) { - 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(); - - _uniformCache.mainColorTexture = _resolveProgram->uniformLocation( - "mainColorTexture" + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer( + 0, + 4, + GL_FLOAT, + GL_FALSE, + sizeof(GLfloat) * 4, + nullptr ); + glEnableVertexAttribArray(0); + + GLint defaultFbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); + + // Main framebuffer + glGenTextures(1, &_mainColorTexture); + glGenTextures(1, &_mainDepthTexture); + glGenFramebuffers(1, &_mainFramebuffer); + + // 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); + + updateResolution(); + updateRendererData(); + updateRaycastData(); + + glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D_MULTISAMPLE, + _mainColorTexture, + 0 + ); + // G-buffer + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT1, + GL_TEXTURE_2D_MULTISAMPLE, + _mainPositionTexture, + 0 + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT2, + GL_TEXTURE_2D_MULTISAMPLE, + _mainNormalTexture, + 0 + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D_MULTISAMPLE, + _mainDepthTexture, + 0 + ); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Main framebuffer is not complete"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + _exitColorTexture, + 0 + ); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, + _exitDepthTexture, + 0 + ); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Exit framebuffer is not complete"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, _deferredFramebuffer); + glFramebufferTexture2D( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + _deferredColorTexture, + 0 + ); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Deferred framebuffer is not complete"); + } + + // JCC: Moved to here to avoid NVidia: "Program/shader state performance warning" + updateHDRData(); + updateDeferredcastData(); + updateMSAASamplingPattern(); + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + + _resolveProgram = ghoul::opengl::ProgramObject::Build( + "Framebuffer Resolve", + absPath("${SHADERS}/framebuffer/resolveframebuffer.vert"), + absPath("${SHADERS}/framebuffer/resolveframebuffer.frag") + ); + + _uniformCache.mainColorTexture = _resolveProgram->uniformLocation("mainColorTexture"); _uniformCache.blackoutFactor = _resolveProgram->uniformLocation("blackoutFactor"); _uniformCache.nAaSamples = _resolveProgram->uniformLocation("nAaSamples"); + + OsEng.renderEngine().raycasterManager().addListener(*this); + OsEng.renderEngine().deferredcasterManager().addListener(*this); } - for (auto& program : _exitPrograms) { - if (program.second->isDirty()) { - try { + void FramebufferRenderer::deinitialize() { + LINFO("Deinitializing FramebufferRenderer"); + + glDeleteFramebuffers(1, &_mainFramebuffer); + glDeleteFramebuffers(1, &_exitFramebuffer); + glDeleteFramebuffers(1, &_deferredFramebuffer); + + glDeleteTextures(1, &_mainColorTexture); + glDeleteTextures(1, &_mainDepthTexture); + + // DEBUG: deferred g-buffer + glDeleteTextures(1, &_deferredColorTexture); + glDeleteTextures(1, &_mainPositionTexture); + glDeleteTextures(1, &_mainNormalTexture); + + glDeleteTextures(1, &_exitColorTexture); + glDeleteTextures(1, &_exitDepthTexture); + + glDeleteBuffers(1, &_vertexPositionBuffer); + glDeleteVertexArrays(1, &_screenQuad); + + OsEng.renderEngine().raycasterManager().removeListener(*this); + OsEng.renderEngine().deferredcasterManager().removeListener(*this); + } + + void FramebufferRenderer::raycastersChanged(VolumeRaycaster&, bool) { + _dirtyRaycastData = true; + } + + void FramebufferRenderer::deferredcastersChanged(Deferredcaster& deferredcaster, + ghoul::Boolean isAttached) + { + (void)deferredcaster; + (void)isAttached; + _dirtyDeferredcastData = true; + } + + void FramebufferRenderer::update() { + if (_dirtyResolution) { + updateResolution(); + updateMSAASamplingPattern(); + } + + if (_dirtyRaycastData) { + updateRaycastData(); + } + + if (_dirtyDeferredcastData) { + 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(); + + _uniformCache.mainColorTexture = _resolveProgram->uniformLocation( + "mainColorTexture" + ); + _uniformCache.blackoutFactor = _resolveProgram->uniformLocation("blackoutFactor"); + _uniformCache.nAaSamples = _resolveProgram->uniformLocation("nAaSamples"); + } + + for (auto& program : _exitPrograms) { + if (program.second->isDirty()) { + try { + program.second->rebuildFromFile(); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + } + } + + for (auto& program : _raycastPrograms) { + if (program.second->isDirty()) { + try { + program.second->rebuildFromFile(); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + } + } + + for (auto& program : _insideRaycastPrograms) { + if (program.second->isDirty()) { + try { + program.second->rebuildFromFile(); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + } + } + + for (auto &program : _deferredcastPrograms) { + if (program.second && program.second->isDirty()) { program.second->rebuildFromFile(); - } catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); } } } - for (auto& program : _raycastPrograms) { - if (program.second->isDirty()) { - try { - program.second->rebuildFromFile(); - } catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } - } + void FramebufferRenderer::updateResolution() { + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + true + ); + + // G-buffer + glBindTexture(GL_TEXTURE_2D, _deferredColorTexture); + + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + 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); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainPositionTexture); + + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA32F, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + true); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainNormalTexture); + + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_RGBA32F, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + true); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); + glTexImage2DMultisample( + GL_TEXTURE_2D_MULTISAMPLE, + _nAaSamples, + GL_DEPTH_COMPONENT32F, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + true + ); + + glBindTexture(GL_TEXTURE_2D, _exitColorTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA16, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + 0, + GL_RGBA, + GL_UNSIGNED_SHORT, + nullptr + ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, _exitDepthTexture); + + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT32F, + GLsizei(_resolution.x), + GLsizei(_resolution.y), + 0, + GL_DEPTH_COMPONENT, + GL_FLOAT, + nullptr + ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + _dirtyResolution = false; } - for (auto& program : _insideRaycastPrograms) { - if (program.second->isDirty()) { + void FramebufferRenderer::updateRaycastData() { + _raycastData.clear(); + _exitPrograms.clear(); + _raycastPrograms.clear(); + _insideRaycastPrograms.clear(); + + const std::vector& raycasters = + OsEng.renderEngine().raycasterManager().raycasters(); + int nextId = 0; + for (auto& raycaster : raycasters) { + RaycastData data; + data.id = nextId++; + data.namespaceName = "HELPER"; + + std::string vsPath = raycaster->getBoundsVsPath(); + std::string fsPath = raycaster->getBoundsFsPath(); + + ghoul::Dictionary dict; + dict.setValue("rendererData", _rendererData); + dict.setValue("fragmentPath", fsPath); + dict.setValue("id", data.id); + std::string helperPath = raycaster->getHelperPath(); + ghoul::Dictionary helpersDict; + if (!helperPath.empty()) { + helpersDict.setValue("0", helperPath); + } + dict.setValue("helperPaths", helpersDict); + dict.setValue("raycastPath", raycaster->getRaycastPath()); + + _raycastData[raycaster] = data; + try { - program.second->rebuildFromFile(); + _exitPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( + "Volume " + std::to_string(data.id) + " exit", + vsPath, + ExitFragmentShaderPath, + dict + ); + } + catch (ghoul::RuntimeError e) { + LERROR(e.message); + } + try { + ghoul::Dictionary outsideDict = dict; + outsideDict.setValue("getEntryPath", GetEntryOutsidePath); + _raycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( + "Volume " + std::to_string(data.id) + " raycast", + absPath(vsPath), + absPath(RaycastFragmentShaderPath), + outsideDict + ); + } + catch (ghoul::RuntimeError e) { + LERROR(e.message); + } + try { + ghoul::Dictionary insideDict = dict; + insideDict.setValue("getEntryPath", GetEntryInsidePath); + _insideRaycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( + "Volume " + std::to_string(data.id) + " inside raycast", + absPath("${SHADERS}/framebuffer/resolveframebuffer.vert"), + absPath(RaycastFragmentShaderPath), + insideDict + ); } catch (const ghoul::RuntimeError& e) { LERRORC(e.component, e.message); } } + _dirtyRaycastData = false; } - for (auto &program : _deferredcastPrograms) { - if (program.second && program.second->isDirty()) { - program.second->rebuildFromFile(); + void FramebufferRenderer::updateDeferredcastData() { + _deferredcastData.clear(); + _deferredcastPrograms.clear(); + + const std::vector& deferredcasters = + OsEng.renderEngine().deferredcasterManager().deferredcasters(); + int nextId = 0; + for (auto& caster : deferredcasters) { + DeferredcastData data; + data.id = nextId++; + data.namespaceName = "HELPER"; + + std::string vsPath = caster->deferredcastVSPath(); + std::string fsPath = caster->deferredcastFSPath(); + std::string deferredShaderPath = caster->deferredcastPath(); + + ghoul::Dictionary dict; + dict.setValue("rendererData", _rendererData); + //dict.setValue("fragmentPath", fsPath); + dict.setValue("id", data.id); + std::string helperPath = caster->helperPath(); + ghoul::Dictionary helpersDict; + if (helperPath != "") { + helpersDict.setValue("0", helperPath); + } + dict.setValue("helperPaths", helpersDict); + //dict.setValue("deferredcastPath", caster->getDeferredcastPath()); + + _deferredcastData[caster] = data; + + try { + ghoul::Dictionary deferredDict = dict; + //deferredDict.setValue("getEntryPath", GetEntryOutsidePath); + _deferredcastPrograms[caster] = ghoul::opengl::ProgramObject::Build( + "Deferred " + std::to_string(data.id) + " raycast", + absPath(vsPath), + absPath(deferredShaderPath), + deferredDict); + using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; + _deferredcastPrograms[caster]->setIgnoreSubroutineUniformLocationError( + IgnoreError::Yes + ); + _deferredcastPrograms[caster]->setIgnoreUniformLocationError( + IgnoreError::Yes + ); + } + catch (ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + } + _dirtyDeferredcastData = false; } -} - -void FramebufferRenderer::updateResolution() { - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - true - ); - - // G-buffer - glBindTexture(GL_TEXTURE_2D, _deferredColorTexture); - - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA32F, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - 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); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainPositionTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - true); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainNormalTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - true); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_DEPTH_COMPONENT32F, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - true - ); - - glBindTexture(GL_TEXTURE_2D, _exitColorTexture); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA16, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - 0, - GL_RGBA, - GL_UNSIGNED_SHORT, - nullptr - ); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glBindTexture(GL_TEXTURE_2D, _exitDepthTexture); - - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_DEPTH_COMPONENT32F, - GLsizei(_resolution.x), - GLsizei(_resolution.y), - 0, - GL_DEPTH_COMPONENT, - GL_FLOAT, - nullptr - ); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - _dirtyResolution = false; -} - -void FramebufferRenderer::updateRaycastData() { - _raycastData.clear(); - _exitPrograms.clear(); - _raycastPrograms.clear(); - _insideRaycastPrograms.clear(); - - const std::vector& raycasters = - OsEng.renderEngine().raycasterManager().raycasters(); - int nextId = 0; - for (auto& raycaster : raycasters) { - RaycastData data; - data.id = nextId++; - data.namespaceName = "HELPER"; - - std::string vsPath = raycaster->getBoundsVsPath(); - std::string fsPath = raycaster->getBoundsFsPath(); - - ghoul::Dictionary dict; - dict.setValue("rendererData", _rendererData); - dict.setValue("fragmentPath", fsPath); - dict.setValue("id", data.id); - std::string helperPath = raycaster->getHelperPath(); - ghoul::Dictionary helpersDict; - if (!helperPath.empty()) { - helpersDict.setValue("0", helperPath); - } - dict.setValue("helperPaths", helpersDict); - dict.setValue("raycastPath", raycaster->getRaycastPath()); - - _raycastData[raycaster] = data; + void FramebufferRenderer::updateHDRData() { try { - _exitPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( - "Volume " + std::to_string(data.id) + " exit", - vsPath, - ExitFragmentShaderPath, - dict - ); - } catch (ghoul::RuntimeError e) { - LERROR(e.message); - } - try { - ghoul::Dictionary outsideDict = dict; - outsideDict.setValue("getEntryPath", GetEntryOutsidePath); - _raycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( - "Volume " + std::to_string(data.id) + " raycast", - absPath(vsPath), - absPath(RaycastFragmentShaderPath), - outsideDict - ); - } catch (ghoul::RuntimeError e) { - LERROR(e.message); - } - try { - ghoul::Dictionary insideDict = dict; - insideDict.setValue("getEntryPath", GetEntryInsidePath); - _insideRaycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( - "Volume " + std::to_string(data.id) + " inside raycast", - absPath("${SHADERS}/framebuffer/resolveframebuffer.vert"), - absPath(RaycastFragmentShaderPath), - insideDict + _hdrBackGroundProgram = ghoul::opengl::ProgramObject::Build( + "HDR Background Control", + absPath("${SHADERS}/framebuffer/hdrBackground.vert"), + absPath("${SHADERS}/framebuffer/hdrBackground.frag") ); + using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; + _hdrBackGroundProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); + _hdrBackGroundProgram->setIgnoreUniformLocationError(IgnoreError::Yes); } catch (const ghoul::RuntimeError& e) { LERRORC(e.component, e.message); } } - _dirtyRaycastData = false; -} -void FramebufferRenderer::updateDeferredcastData() { - _deferredcastData.clear(); - _deferredcastPrograms.clear(); + void FramebufferRenderer::updateMSAASamplingPattern() { + LDEBUG("Updating MSAA Sampling Pattern"); - const std::vector& deferredcasters = - OsEng.renderEngine().deferredcasterManager().deferredcasters(); - int nextId = 0; - for (auto& caster : deferredcasters) { - DeferredcastData data; - data.id = nextId++; - data.namespaceName = "HELPER"; + const int GRIDSIZE = 32; + GLfloat step = 2.0f / static_cast(GRIDSIZE); + GLfloat sizeX = -1.0f, + sizeY = 1.0f; - std::string vsPath = caster->deferredcastVSPath(); - std::string fsPath = caster->deferredcastFSPath(); - std::string deferredShaderPath = caster->deferredcastPath(); + const int NVERTEX = 4 * 6; + // openPixelSizeVertexData + GLfloat vertexData[GRIDSIZE * GRIDSIZE * NVERTEX]; - ghoul::Dictionary dict; - dict.setValue("rendererData", _rendererData); - //dict.setValue("fragmentPath", fsPath); - dict.setValue("id", data.id); - std::string helperPath = caster->helperPath(); - ghoul::Dictionary helpersDict; - if (helperPath != "") { - helpersDict.setValue("0", helperPath); + 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.0f; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 3] = 1.0f; + + 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.0f; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 7] = 1.0f; + + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 8] = sizeX; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 9] = sizeY; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 10] = 0.0f; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 11] = 1.0f; + + 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.0f; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 15] = 1.0f; + + 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.0f; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 19] = 1.0f; + + 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.0f; + vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 23] = 1.0f; + + sizeX += step; + } + sizeX = -1.0f; + sizeY -= step; } - dict.setValue("helperPaths", helpersDict); - //dict.setValue("deferredcastPath", caster->getDeferredcastPath()); - _deferredcastData[caster] = data; + GLuint pixelSizeQuadVAO = 0; + GLuint pixelSizeQuadVBO = 0; + glGenVertexArrays(1, &pixelSizeQuadVAO); + glBindVertexArray(pixelSizeQuadVAO); + + 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); + + 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.0f, 0.0f, 0.0f, 1.0f); + 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 = nullptr; try { - ghoul::Dictionary deferredDict = dict; - //deferredDict.setValue("getEntryPath", GetEntryOutsidePath); - _deferredcastPrograms[caster] = ghoul::opengl::ProgramObject::Build( - "Deferred " + std::to_string(data.id) + " raycast", - absPath(vsPath), - absPath(deferredShaderPath), - deferredDict); - - using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; - _deferredcastPrograms[caster]->setIgnoreSubroutineUniformLocationError( - IgnoreError::Yes + pixelSizeProgram = ghoul::opengl::ProgramObject::Build( + "OnePixel MSAA", + absPath("${SHADERS}/framebuffer/pixelSizeMSAA.vert"), + absPath("${SHADERS}/framebuffer/pixelSizeMSAA.frag") ); - _deferredcastPrograms[caster]->setIgnoreUniformLocationError( - IgnoreError::Yes - ); - - caster->initializeCachedVariables(*_deferredcastPrograms[caster]); } - catch (ghoul::RuntimeError& e) { + catch (const ghoul::RuntimeError& e) { LERRORC(e.component, e.message); } - } - _dirtyDeferredcastData = false; -} + pixelSizeProgram->activate(); -void FramebufferRenderer::updateHDRData() { - try { - _hdrBackGroundProgram = ghoul::opengl::ProgramObject::Build( - "HDR Background Control", - absPath("${SHADERS}/framebuffer/hdrBackground.vert"), - absPath("${SHADERS}/framebuffer/hdrBackground.frag") - ); - using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; - _hdrBackGroundProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); - _hdrBackGroundProgram->setIgnoreUniformLocationError(IgnoreError::Yes); - } - catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } -} + // 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); -void FramebufferRenderer::updateMSAASamplingPattern() { - LDEBUG("Updating MSAA Sampling Pattern"); + pixelSizeProgram->deactivate(); - const int GRIDSIZE = 32; - GLfloat step = 2.0f / static_cast(GRIDSIZE); - GLfloat sizeX = -1.0f, - sizeY = 1.0f; + // Now we render the Nx1 quad strip + GLuint nOneStripFramebuffer = 0; + GLuint nOneStripVAO = 0; + GLuint nOneStripVBO = 0; + GLuint nOneStripTexture = 0; - const int NVERTEX = 4 * 6; - // openPixelSizeVertexData - GLfloat vertexData[GRIDSIZE * GRIDSIZE * NVERTEX]; + sizeX = -1.0f; + step = 2.0f / static_cast(_nAaSamples); - 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.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 3] = 1.0f; + GLfloat * nOneStripVertexData = new GLfloat[_nAaSamples * (NVERTEX + 12)]; - 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.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 7] = 1.0f; + for (int x = 0; x < _nAaSamples; ++x) { + nOneStripVertexData[x * (NVERTEX + 12)] = sizeX; + nOneStripVertexData[x * (NVERTEX + 12) + 1] = -1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 2] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 3] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 4] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 5] = 0.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 8] = sizeX; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 9] = sizeY; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 10] = 0.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 11] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 6] = sizeX + step; + nOneStripVertexData[x * (NVERTEX + 12) + 7] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 8] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 9] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 10] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 11] = 1.0f; - 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.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 15] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 12] = sizeX; + nOneStripVertexData[x * (NVERTEX + 12) + 13] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 14] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 15] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 16] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 17] = 0.0f; - 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.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 19] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 18] = sizeX; + nOneStripVertexData[x * (NVERTEX + 12) + 19] = -1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 20] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 21] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 22] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 23] = 0.0f; - 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.0f; - vertexData[y * GRIDSIZE * NVERTEX + x * NVERTEX + 23] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 24] = sizeX + step; + nOneStripVertexData[x * (NVERTEX + 12) + 25] = -1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 26] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 27] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 28] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 29] = 1.0f; + + nOneStripVertexData[x * (NVERTEX + 12) + 30] = sizeX + step; + nOneStripVertexData[x * (NVERTEX + 12) + 31] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 32] = 0.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 33] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 34] = 1.0f; + nOneStripVertexData[x * (NVERTEX + 12) + 35] = 1.0f; sizeX += step; } - sizeX = -1.0f; - sizeY -= step; - } - GLuint pixelSizeQuadVAO = 0; - GLuint pixelSizeQuadVBO = 0; - - glGenVertexArrays(1, &pixelSizeQuadVAO); - glBindVertexArray(pixelSizeQuadVAO); - - 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); - - 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.0f, 0.0f, 0.0f, 1.0f); - 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 = nullptr; - try { - pixelSizeProgram = ghoul::opengl::ProgramObject::Build( - "OnePixel MSAA", - absPath("${SHADERS}/framebuffer/pixelSizeMSAA.vert"), - absPath("${SHADERS}/framebuffer/pixelSizeMSAA.frag") + glGenVertexArrays(1, &nOneStripVAO); + glBindVertexArray(nOneStripVAO); + glGenBuffers(1, &nOneStripVBO); + glBindBuffer(GL_ARRAY_BUFFER, nOneStripVBO); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(GLfloat) * _nAaSamples * (NVERTEX + 12), + nOneStripVertexData, + GL_STATIC_DRAW ); - } - catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } - 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.0f; - step = 2.0f / static_cast(_nAaSamples); - - GLfloat * nOneStripVertexData = new GLfloat[_nAaSamples * (NVERTEX + 12)]; - - for (int x = 0; x < _nAaSamples; ++x) { - nOneStripVertexData[x * (NVERTEX + 12)] = sizeX; - nOneStripVertexData[x * (NVERTEX + 12) + 1] = -1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 2] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 3] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 4] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 5] = 0.0f; - - nOneStripVertexData[x * (NVERTEX + 12) + 6] = sizeX + step; - nOneStripVertexData[x * (NVERTEX + 12) + 7] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 8] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 9] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 10] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 11] = 1.0f; - - nOneStripVertexData[x * (NVERTEX + 12) + 12] = sizeX; - nOneStripVertexData[x * (NVERTEX + 12) + 13] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 14] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 15] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 16] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 17] = 0.0f; - - nOneStripVertexData[x * (NVERTEX + 12) + 18] = sizeX; - nOneStripVertexData[x * (NVERTEX + 12) + 19] = -1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 20] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 21] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 22] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 23] = 0.0f; - - nOneStripVertexData[x * (NVERTEX + 12) + 24] = sizeX + step; - nOneStripVertexData[x * (NVERTEX + 12) + 25] = -1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 26] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 27] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 28] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 29] = 1.0f; - - nOneStripVertexData[x * (NVERTEX + 12) + 30] = sizeX + step; - nOneStripVertexData[x * (NVERTEX + 12) + 31] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 32] = 0.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 33] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 34] = 1.0f; - nOneStripVertexData[x * (NVERTEX + 12) + 35] = 1.0f; - - 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, - 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); - delete[] nOneStripVertexData; - - // 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 = nullptr; - try { - nOneStripProgram = ghoul::opengl::ProgramObject::Build( - "OneStrip MSAA", - absPath("${SHADERS}/framebuffer/nOneStripMSAA.vert"), - absPath("${SHADERS}/framebuffer/nOneStripMSAA.frag") + // position + glVertexAttribPointer( + 0, + 4, + GL_FLOAT, + GL_FALSE, + sizeof(GLfloat) * 6, + nullptr ); - } - catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } + glEnableVertexAttribArray(0); - 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.0f, 1.0f, 0.0f, 1.0f); - 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[2]); - _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); -} - -void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) { - std::unique_ptr perf; - if (doPerformanceMeasurements) { - perf = std::make_unique( - "FramebufferRenderer::render", - OsEng.renderEngine().performanceManager() + // texture coords + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(GLfloat) * 6, + reinterpret_cast(sizeof(GLfloat) * 4) ); + glEnableVertexAttribArray(1); + delete[] nOneStripVertexData; + + // 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 = nullptr; + try { + nOneStripProgram = ghoul::opengl::ProgramObject::Build( + "OneStrip MSAA", + absPath("${SHADERS}/framebuffer/nOneStripMSAA.vert"), + absPath("${SHADERS}/framebuffer/nOneStripMSAA.frag") + ); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + + 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.0f, 1.0f, 0.0f, 1.0f); + 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[2]); + _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); } - if (!_scene || !_camera) { - return; - } - - glEnable(GL_DEPTH_TEST); - - - Time time = OsEng.timeManager().time(); - - RenderData data = { *_camera, psc(), time, doPerformanceMeasurements, 0, {} }; - RendererTasks tasks; - - // Capture standard fbo - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - // deferred g-buffer - GLenum textureBuffers[3] = { - GL_COLOR_ATTACHMENT0, - GL_COLOR_ATTACHMENT1, - GL_COLOR_ATTACHMENT2, - }; - glDrawBuffers(3, textureBuffers); - 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); - - { - std::unique_ptr perfInternal; + void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurements) { + std::unique_ptr perf; if (doPerformanceMeasurements) { - perfInternal = std::make_unique( - "FramebufferRenderer::render::background", + perf = std::make_unique( + "FramebufferRenderer::render", OsEng.renderEngine().performanceManager() ); } - data.renderBinMask = static_cast(Renderable::RenderBin::Background); - _scene->render(data, tasks); - } - { - std::unique_ptr perfInternal; - if (doPerformanceMeasurements) { - perfInternal = std::make_unique( - "FramebufferRenderer::render::opaque", - OsEng.renderEngine().performanceManager() - ); + if (!_scene || !_camera) { + return; } - data.renderBinMask = static_cast(Renderable::RenderBin::Opaque); - _scene->render(data, tasks); - } - { - std::unique_ptr perfInternal; - if (doPerformanceMeasurements) { - perfInternal = std::make_unique( - "FramebufferRenderer::render::transparent", - OsEng.renderEngine().performanceManager() - ); - } - - data.renderBinMask = static_cast(Renderable::RenderBin::Transparent); - _scene->render(data, tasks); - } - { - std::unique_ptr perfInternal; - if (doPerformanceMeasurements) { - perfInternal = std::make_unique( - "FramebufferRenderer::render::overlay", - OsEng.renderEngine().performanceManager() - ); - } - - data.renderBinMask = static_cast(Renderable::RenderBin::Overlay); - _scene->render(data, tasks); - } - - { - std::unique_ptr perfInternal; - if (doPerformanceMeasurements) { - perfInternal = std::make_unique( - "FramebufferRenderer::render::raycasterTasks", - OsEng.renderEngine().performanceManager() - ); - } + glEnable(GL_DEPTH_TEST); - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { - VolumeRaycaster* raycaster = raycasterTask.raycaster; + Time time = OsEng.timeManager().time(); - glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderData data = { *_camera, psc(), time, doPerformanceMeasurements, 0,{} }; + RendererTasks tasks; - ghoul::opengl::ProgramObject* exitProgram = _exitPrograms[raycaster].get(); - if (exitProgram) { - exitProgram->activate(); - raycaster->renderExitPoints(raycasterTask.renderData, *exitProgram); - exitProgram->deactivate(); + // Capture standard fbo + GLint defaultFbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); + + glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + // deferred g-buffer + GLenum textureBuffers[3] = { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + }; + glDrawBuffers(3, textureBuffers); + 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); + + { + std::unique_ptr perfInternal; + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::background", + OsEng.renderEngine().performanceManager() + ); } - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - glm::vec3 cameraPosition; - bool cameraIsInside = raycaster->cameraIsInside( - raycasterTask.renderData, - cameraPosition - ); - ghoul::opengl::ProgramObject* raycastProgram = nullptr; + data.renderBinMask = static_cast(Renderable::RenderBin::Background); + _scene->render(data, tasks); + } + { + std::unique_ptr perfInternal; + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::opaque", + OsEng.renderEngine().performanceManager() + ); + } - if (cameraIsInside) { - raycastProgram = _insideRaycastPrograms[raycaster].get(); - if (raycastProgram) { - raycastProgram->activate(); - raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); + data.renderBinMask = static_cast(Renderable::RenderBin::Opaque); + _scene->render(data, tasks); + } + { + std::unique_ptr perfInternal; + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::transparent", + OsEng.renderEngine().performanceManager() + ); + } + + data.renderBinMask = static_cast(Renderable::RenderBin::Transparent); + _scene->render(data, tasks); + } + { + std::unique_ptr perfInternal; + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::overlay", + OsEng.renderEngine().performanceManager() + ); + } + + data.renderBinMask = static_cast(Renderable::RenderBin::Overlay); + _scene->render(data, tasks); + } + + { + std::unique_ptr perfInternal; + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::raycasterTasks", + OsEng.renderEngine().performanceManager() + ); + } + + + for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { + VolumeRaycaster* raycaster = raycasterTask.raycaster; + + glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + ghoul::opengl::ProgramObject* exitProgram = _exitPrograms[raycaster].get(); + if (exitProgram) { + exitProgram->activate(); + raycaster->renderExitPoints(raycasterTask.renderData, *exitProgram); + exitProgram->deactivate(); } - else { + + glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); + glm::vec3 cameraPosition; + bool cameraIsInside = raycaster->cameraIsInside( + raycasterTask.renderData, + cameraPosition + ); + ghoul::opengl::ProgramObject* raycastProgram = nullptr; + + if (cameraIsInside) { raycastProgram = _insideRaycastPrograms[raycaster].get(); - raycastProgram->activate(); - raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); - } - } - else { - raycastProgram = _raycastPrograms[raycaster].get(); - if (raycastProgram) { - raycastProgram->activate(); + if (raycastProgram) { + raycastProgram->activate(); + raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); + } + else { + raycastProgram = _insideRaycastPrograms[raycaster].get(); + raycastProgram->activate(); + raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); + } } else { raycastProgram = _raycastPrograms[raycaster].get(); - raycastProgram->activate(); + if (raycastProgram) { + raycastProgram->activate(); + } + else { + raycastProgram = _raycastPrograms[raycaster].get(); + raycastProgram->activate(); + } + } + + if (raycastProgram) { + raycaster->preRaycast(_raycastData[raycaster], *raycastProgram); + + ghoul::opengl::TextureUnit exitColorTextureUnit; + exitColorTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D, _exitColorTexture); + raycastProgram->setUniform("exitColorTexture", exitColorTextureUnit); + + ghoul::opengl::TextureUnit exitDepthTextureUnit; + exitDepthTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D, _exitDepthTexture); + raycastProgram->setUniform("exitDepthTexture", exitDepthTextureUnit); + + ghoul::opengl::TextureUnit mainDepthTextureUnit; + mainDepthTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); + raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit); + + raycastProgram->setUniform("nAaSamples", _nAaSamples); + raycastProgram->setUniform("windowSize", _resolution); + + glDisable(GL_DEPTH_TEST); + glDepthMask(false); + if (cameraIsInside) { + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + } + else { + raycaster->renderEntryPoints( + raycasterTask.renderData, + *raycastProgram + ); + } + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + + raycaster->postRaycast(_raycastData[raycaster], *raycastProgram); + raycastProgram->deactivate(); + } + else { + LWARNING( + "Raycaster is not attached when trying to perform raycaster task" + ); } } + } - if (raycastProgram) { - raycaster->preRaycast(_raycastData[raycaster], *raycastProgram); + // g-buffer + if (!tasks.deferredcasterTasks.empty()) { + std::unique_ptr perfInternal; + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::deferredTasks", + OsEng.renderEngine().performanceManager() + ); + } - ghoul::opengl::TextureUnit exitColorTextureUnit; - exitColorTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _exitColorTexture); - raycastProgram->setUniform("exitColorTexture", exitColorTextureUnit); + //glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _deferredFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + GLenum dBuffer[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, dBuffer); + glClear(GL_COLOR_BUFFER_BIT); - ghoul::opengl::TextureUnit exitDepthTextureUnit; - exitDepthTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _exitDepthTexture); - raycastProgram->setUniform("exitDepthTexture", exitDepthTextureUnit); + bool firstPaint = true; - ghoul::opengl::TextureUnit mainDepthTextureUnit; - mainDepthTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); - raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit); + for (const DeferredcasterTask& deferredcasterTask : tasks.deferredcasterTasks) { - raycastProgram->setUniform("nAaSamples", _nAaSamples); - raycastProgram->setUniform("windowSize", _resolution); + Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster; + + ghoul::opengl::ProgramObject* deferredcastProgram = nullptr; + + if (deferredcastProgram != _deferredcastPrograms[deferredcaster].get() + || deferredcastProgram == nullptr) { + deferredcastProgram = _deferredcastPrograms[deferredcaster].get(); + } + + if (deferredcastProgram) { + + deferredcastProgram->activate(); + + // adding G-Buffer + ghoul::opengl::TextureUnit mainDColorTextureUnit; + mainDColorTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); + deferredcastProgram->setUniform( + "mainColorTexture", + mainDColorTextureUnit + ); + + ghoul::opengl::TextureUnit mainPositionTextureUnit; + mainPositionTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainPositionTexture); + deferredcastProgram->setUniform( + "mainPositionTexture", + mainPositionTextureUnit + ); + + ghoul::opengl::TextureUnit mainNormalTextureUnit; + mainNormalTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainNormalTexture); + 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); + + deferredcaster->preRaycast( + deferredcasterTask.renderData, + _deferredcastData[deferredcaster], + *deferredcastProgram + ); + + glDisable(GL_DEPTH_TEST); + glDepthMask(false); - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - if (cameraIsInside) { glBindVertexArray(_screenQuad); glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); + + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + + deferredcaster->postRaycast(deferredcasterTask.renderData, + _deferredcastData[deferredcaster], + *deferredcastProgram); + + deferredcastProgram->deactivate(); + + if (firstPaint) { + firstPaint = false; + } } else { - raycaster->renderEntryPoints( - raycasterTask.renderData, - *raycastProgram + LWARNING( + "Deferredcaster is not attached when trying to perform deferred task" ); } - glDepthMask(true); - glEnable(GL_DEPTH_TEST); + } + } - raycaster->postRaycast(_raycastData[raycaster], *raycastProgram); - raycastProgram->deactivate(); - } - else { - LWARNING( - "Raycaster is not attached when trying to perform raycaster task" - ); - } + if (!tasks.deferredcasterTasks.empty()) { + // JCC: Temporarily disabled. Need to test it on mac and linux before final + // merging. + /*glBindFramebuffer(GL_READ_FRAMEBUFFER, _deferredFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFbo); + GLenum dBuffer[] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, dBuffer); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, GLsizei(_resolution.x), GLsizei(_resolution.y), + 0, 0, GLsizei(_resolution.x), GLsizei(_resolution.y), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + */ + //glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + } + else { + glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); + _resolveProgram->activate(); + + ghoul::opengl::TextureUnit mainColorTextureUnit; + mainColorTextureUnit.activate(); + + 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(); } } - // g-buffer - if (!tasks.deferredcasterTasks.empty()) { - std::unique_ptr perfInternal; - if (doPerformanceMeasurements) { - perfInternal = std::make_unique( - "FramebufferRenderer::render::deferredTasks", - OsEng.renderEngine().performanceManager() - ); + void FramebufferRenderer::setScene(Scene* scene) { + _scene = scene; + } + + void FramebufferRenderer::setCamera(Camera* camera) { + _camera = camera; + } + + void FramebufferRenderer::setResolution(glm::ivec2 res) { + _resolution = res; + _dirtyResolution = true; + } + + void FramebufferRenderer::setNAaSamples(int nAaSamples) { + _nAaSamples = nAaSamples; + if (_nAaSamples == 0) { + _nAaSamples = 1; } + if (_nAaSamples > 8) { + LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); + _nAaSamples = 8; + } + _dirtyResolution = true; + } - //glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _deferredFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - GLenum dBuffer[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, dBuffer); - glClear(GL_COLOR_BUFFER_BIT); + void FramebufferRenderer::setHDRExposure(float hdrExposure) { + _hdrExposure = hdrExposure; + if (_hdrExposure < 0.0f) { + LERROR("HDR Exposure constant must be greater than zero."); + _hdrExposure = 1.0f; + } + } - bool firstPaint = true; + void FramebufferRenderer::setHDRBackground(float hdrBackground) { + _hdrBackground = hdrBackground; + if (_hdrBackground < 0.0f) { + LERROR("HDR Background constant must be greater than zero."); + _hdrBackground = 1.0f; + } + } - for (const DeferredcasterTask& deferredcasterTask : tasks.deferredcasterTasks) { + void FramebufferRenderer::setGamma(float gamma) { + _gamma = gamma; + if (_gamma < 0.0f) { + LERROR("Gamma value must be greater than zero."); + _gamma = 2.2f; + } + } - Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster; + float FramebufferRenderer::hdrBackground() const { + return _hdrBackground; + } - ghoul::opengl::ProgramObject* deferredcastProgram = nullptr; + int FramebufferRenderer::nAaSamples() const { + return _nAaSamples; + } - if (deferredcastProgram != _deferredcastPrograms[deferredcaster].get() - || deferredcastProgram == nullptr) { - deferredcastProgram = _deferredcastPrograms[deferredcaster].get(); + std::vector FramebufferRenderer::mSSAPattern() const { + return _mSAAPattern; + } + + void FramebufferRenderer::updateRendererData() { + ghoul::Dictionary dict; + dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); + + _rendererData = dict; + + OsEng.renderEngine().setRendererData(dict); + } + + void saveTextureToPPMFile(const GLenum color_buffer_attachment, + const std::string & fileName, const int width, const int height) + { + std::fstream ppmFile; + + ppmFile.open(fileName.c_str(), std::fstream::out); + if (ppmFile.is_open()) { + unsigned char* pixels = new unsigned char[width*height * 3]; + for (int t = 0; t < width*height * 3; ++t) { + pixels[t] = 255; } - if (deferredcastProgram) { + if (color_buffer_attachment != GL_DEPTH_ATTACHMENT) { + glReadBuffer(color_buffer_attachment); + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); - deferredcastProgram->activate(); - - // adding G-Buffer - ghoul::opengl::TextureUnit mainDColorTextureUnit; - mainDColorTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); - deferredcastProgram->setUniform( - "mainColorTexture", - mainDColorTextureUnit + } + else { + glReadPixels( + 0, + 0, + width, + height, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, + pixels ); + } - ghoul::opengl::TextureUnit mainPositionTextureUnit; - mainPositionTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainPositionTexture); - deferredcastProgram->setUniform( - "mainPositionTexture", - mainPositionTextureUnit - ); + ppmFile << "P3" << std::endl; + ppmFile << width << " " << height << std::endl; + ppmFile << "255" << std::endl; - ghoul::opengl::TextureUnit mainNormalTextureUnit; - mainNormalTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainNormalTexture); - 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); - - deferredcaster->preRaycast( - deferredcasterTask.renderData, - _deferredcastData[deferredcaster], - *deferredcastProgram - ); - - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - - deferredcaster->postRaycast(deferredcasterTask.renderData, - _deferredcastData[deferredcaster], - *deferredcastProgram); - - deferredcastProgram->deactivate(); - - if (firstPaint) { - firstPaint = false; + std::cout << "\n\nFILE\n\n"; + int k = 0; + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + ppmFile << static_cast(pixels[k]) << " " + << static_cast(pixels[k + 1]) << " " + << static_cast(pixels[k + 2]) << " "; + k += 3; } + ppmFile << std::endl; } - else { - LWARNING( - "Deferredcaster is not attached when trying to perform deferred task" - ); - } + delete[] pixels; + + ppmFile.close(); } } - if (tasks.deferredcasterTasks.empty()) { - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - _resolveProgram->activate(); + void saveTextureToMemory(const GLenum color_buffer_attachment, + const int width, const int height, std::vector & memory) { - ghoul::opengl::TextureUnit mainColorTextureUnit; - mainColorTextureUnit.activate(); - - 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(); - } -} - -void FramebufferRenderer::setScene(Scene* scene) { - _scene = scene; -} - -void FramebufferRenderer::setCamera(Camera* camera) { - _camera = camera; -} - -void FramebufferRenderer::setResolution(glm::ivec2 res) { - _resolution = res; - _dirtyResolution = true; -} - -void FramebufferRenderer::setNAaSamples(int nAaSamples) { - _nAaSamples = nAaSamples; - if (_nAaSamples == 0) { - _nAaSamples = 1; - } - if (_nAaSamples > 8) { - LERROR("Framebuffer renderer does not support more than 8 MSAA samples."); - _nAaSamples = 8; - } - _dirtyResolution = true; -} - -void FramebufferRenderer::setHDRExposure(float hdrExposure) { - _hdrExposure = hdrExposure; - if (_hdrExposure < 0.0f) { - LERROR("HDR Exposure constant must be greater than zero."); - _hdrExposure = 1.0f; - } -} - -void FramebufferRenderer::setHDRBackground(float hdrBackground) { - _hdrBackground = hdrBackground; - if (_hdrBackground < 0.0f) { - LERROR("HDR Background constant must be greater than zero."); - _hdrBackground = 1.0f; - } -} - -void FramebufferRenderer::setGamma(float gamma) { - _gamma = gamma; - if (_gamma < 0.0f) { - LERROR("Gamma value must be greater than zero."); - _gamma = 2.2f; - } -} - -float FramebufferRenderer::hdrBackground() const { - return _hdrBackground; -} - -int FramebufferRenderer::nAaSamples() const { - return _nAaSamples; -} - -std::vector FramebufferRenderer::mSSAPattern() const { - return _mSAAPattern; -} - -void FramebufferRenderer::updateRendererData() { - ghoul::Dictionary dict; - dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); - - _rendererData = dict; - - OsEng.renderEngine().setRendererData(dict); -} - -void saveTextureToPPMFile(const GLenum color_buffer_attachment, - const std::string & fileName, const int width, const int height) -{ - std::fstream ppmFile; - - ppmFile.open(fileName.c_str(), std::fstream::out); - if (ppmFile.is_open()) { - unsigned char* pixels = new unsigned char[width*height * 3]; - for (int t = 0; t < width*height * 3; ++t) { - pixels[t] = 255; + if (!memory.empty()) { + memory.clear(); } + memory.resize(width * height * 3); + + float *tempMemory = new float[width*height * 3]; if (color_buffer_attachment != GL_DEPTH_ATTACHMENT) { glReadBuffer(color_buffer_attachment); - glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); + glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, tempMemory); } else { - glReadPixels( - 0, - 0, - width, - height, - GL_DEPTH_COMPONENT, - GL_UNSIGNED_BYTE, - pixels - ); + glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, tempMemory); } - ppmFile << "P3" << std::endl; - ppmFile << width << " " << height << std::endl; - ppmFile << "255" << std::endl; - - std::cout << "\n\nFILE\n\n"; - int k = 0; - for (int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - ppmFile << static_cast(pixels[k]) << " " - << static_cast(pixels[k + 1]) << " " - << static_cast(pixels[k + 2]) << " "; - k += 3; - } - ppmFile << std::endl; + for (auto i = 0; i < width*height * 3; ++i) { + memory[i] = static_cast(tempMemory[i]); } - delete[] pixels; - ppmFile.close(); + delete[] tempMemory; } -} - -void saveTextureToMemory(const GLenum color_buffer_attachment, - const int width, const int height, std::vector & memory) { - - if (!memory.empty()) { - memory.clear(); - } - memory.resize(width * height * 3); - - float *tempMemory = new float[width*height * 3]; - - if (color_buffer_attachment != GL_DEPTH_ATTACHMENT) { - glReadBuffer(color_buffer_attachment); - glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, tempMemory); - - } - else { - glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, tempMemory); - } - - for (auto i = 0; i < width*height * 3; ++i) { - memory[i] = static_cast(tempMemory[i]); - } - - delete[] tempMemory; -} } // namespace openspace diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 2c00efaaa3..8adfe0d89b 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -198,7 +198,7 @@ void Renderable::setPscUniforms(ghoul::opengl::ProgramObject& program, program.setUniform("campos", camera.position().vec4()); program.setUniform("objpos", position.vec4()); program.setUniform("camrot", glm::mat4(camera.viewRotationMatrix())); - program.setUniform("scaling", camera.scaling()); + program.setUniform("scaling", glm::vec2(1, 0)); } Renderable::RenderBin Renderable::renderBin() const { diff --git a/src/util/camera.cpp b/src/util/camera.cpp index b6483cc7cd..bc59e4dc66 100644 --- a/src/util/camera.cpp +++ b/src/util/camera.cpp @@ -49,8 +49,6 @@ namespace openspace { : _focusPosition() , _maxFov(0.f) { - - _scaling = glm::vec2(1.f, 0.f); _position = Vec3(1.0, 1.0, 1.0); Vec3 eulerAngles(1.0, 1.0, 1.0); _rotation = Quat(eulerAngles); @@ -60,7 +58,6 @@ namespace openspace { : sgctInternal(o.sgctInternal) , _position(o._position) , _rotation(o._rotation) - , _scaling(o._scaling) , _focusPosition(o._focusPosition) , _maxFov(o._maxFov) , _cachedViewDirection(o._cachedViewDirection) @@ -91,9 +88,11 @@ namespace openspace { _cachedCombinedViewMatrix.isDirty = true; } - void Camera::setScaling(glm::vec2 scaling) { + void Camera::setScaling(float scaling) { std::lock_guard _lock(_mutex); - _scaling = std::move(scaling); + _scaling = scaling; + _cachedViewScaleMatrix.isDirty = true; + _cachedCombinedViewMatrix.isDirty = true; } void Camera::setMaxFov(float fov) { @@ -122,6 +121,26 @@ namespace openspace { return _position; } + const Camera::Vec3 Camera::eyePositionVec3() const { + glm::dvec4 eyeInEyeSpace(0.0, 0.0, 0.0, 1.0); + + glm::dmat4 invViewMatrix = glm::inverse(sgctInternal.viewMatrix()); + glm::dmat4 invRotationMatrix = glm::inverse(viewRotationMatrix()); + glm::dmat4 invTranslationMatrix = + glm::translate(Mat4(1.0), static_cast(_position)); + + glm::dmat4 invViewScale = glm::inverse(viewScaleMatrix()); + + glm::dvec4 eyeInWorldSpace = + invTranslationMatrix * + invRotationMatrix * + invViewScale * + invViewMatrix * + eyeInEyeSpace; + + return glm::dvec3(eyeInWorldSpace.x, eyeInWorldSpace.y, eyeInWorldSpace.z); + } + const Camera::Vec3& Camera::unsynchedPositionVec3() const { return _position; } @@ -154,10 +173,6 @@ namespace openspace { return _cachedLookupVector.datum; } - const glm::vec2& Camera::scaling() const { - return _scaling; - } - float Camera::maxFov() const { return _maxFov; } @@ -174,6 +189,10 @@ namespace openspace { return _parent; } + float Camera::scaling() const { + return _scaling; + } + const Camera::Mat4& Camera::viewRotationMatrix() const { if (_cachedViewRotationMatrix.isDirty) { _cachedViewRotationMatrix.datum = glm::mat4_cast( @@ -183,6 +202,14 @@ namespace openspace { return _cachedViewRotationMatrix.datum; } + const Camera::Mat4& Camera::viewScaleMatrix() const + { + if (_cachedViewScaleMatrix.isDirty) { + _cachedViewScaleMatrix.datum = glm::scale(glm::vec3(_scaling)); + } + return _cachedViewScaleMatrix.datum; + } + const Camera::Quat& Camera::rotationQuaternion() const { return _rotation; } @@ -193,6 +220,7 @@ namespace openspace { glm::inverse(glm::translate(Mat4(1.0), static_cast(_position))); _cachedCombinedViewMatrix.datum = Mat4(sgctInternal.viewMatrix()) * + Mat4(viewScaleMatrix()) * Mat4(viewRotationMatrix()) * cameraTranslation; _cachedCombinedViewMatrix.isDirty = true; @@ -298,6 +326,10 @@ namespace openspace { return psc(_focusPosition); } + const glm::mat4& Camera::sceneMatrix() const { + return sgctInternal.sceneMatrix(); + } + const glm::mat4& Camera::viewMatrix() const { return sgctInternal.viewMatrix(); }