From e994e900ee3c8e6f018da3f2f4ec4778b57593c2 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 22 Jul 2021 20:42:21 +0200 Subject: [PATCH 01/24] Feature/intel atmosphere (#1691) * Add object names to atmosphere textures * Fix for rendering atmospheres on Intel chips * General cleanup of the atmosphere rendering code to make a it more modular --- .../solarsystem/planets/mars/atmosphere.asset | 1 - .../planets/venus/atmosphere.asset | 1 - include/openspace/rendering/deferredcaster.h | 2 - .../rendering/atmospheredeferredcaster.cpp | 1808 +++++++---------- .../rendering/atmospheredeferredcaster.h | 124 +- .../rendering/renderableatmosphere.cpp | 84 +- .../rendering/renderableatmosphere.h | 6 +- .../atmosphere/shaders/atmosphere_common.glsl | 163 +- .../shaders/atmosphere_deferred_fs.glsl | 153 +- .../atmosphere/shaders/calculation_vs.glsl | 4 +- .../atmosphere/shaders/deltaE_calc_fs.glsl | 2 - .../atmosphere/shaders/deltaJ_calc_fs.glsl | 58 +- .../atmosphere/shaders/deltaS_calc_fs.glsl | 4 + .../shaders/deltaS_sup_calc_fs.glsl | 11 +- .../shaders/inScattering_calc_fs.glsl | 25 +- .../shaders/inScattering_sup_calc_fs.glsl | 18 +- .../shaders/irradiance_calc_fs.glsl | 24 +- .../shaders/irradiance_final_fs.glsl | 3 +- .../shaders/irradiance_sup_calc_fs.glsl | 44 +- .../shaders/transmittance_calc_fs.glsl | 21 +- src/rendering/framebufferrenderer.cpp | 10 +- 21 files changed, 1124 insertions(+), 1442 deletions(-) diff --git a/data/assets/scene/solarsystem/planets/mars/atmosphere.asset b/data/assets/scene/solarsystem/planets/mars/atmosphere.asset index a3f30d278d..e76b1afd57 100644 --- a/data/assets/scene/solarsystem/planets/mars/atmosphere.asset +++ b/data/assets/scene/solarsystem/planets/mars/atmosphere.asset @@ -42,7 +42,6 @@ local Atmosphere = { G = 0.85 }, Debug = { - -- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....) PreCalculatedTextureScale = 1.0, SaveCalculatedTextures = false } diff --git a/data/assets/scene/solarsystem/planets/venus/atmosphere.asset b/data/assets/scene/solarsystem/planets/venus/atmosphere.asset index a8d28ff7e4..7e39382692 100644 --- a/data/assets/scene/solarsystem/planets/venus/atmosphere.asset +++ b/data/assets/scene/solarsystem/planets/venus/atmosphere.asset @@ -42,7 +42,6 @@ local Atmosphere = { G = 0.85 }, Debug = { - -- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....) PreCalculatedTextureScale = 1.0, SaveCalculatedTextures = false } diff --git a/include/openspace/rendering/deferredcaster.h b/include/openspace/rendering/deferredcaster.h index 3d9f476848..c0b2f12d1e 100644 --- a/include/openspace/rendering/deferredcaster.h +++ b/include/openspace/rendering/deferredcaster.h @@ -51,8 +51,6 @@ public: const DeferredcastData& /*deferredData*/, ghoul::opengl::ProgramObject& /*program*/) {}; - virtual std::filesystem::path deferredcastPath() const = 0; - virtual std::filesystem::path deferredcastVSPath() const = 0; virtual std::filesystem::path deferredcastFSPath() const = 0; diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 1cf0fc71ce..90b8cb0f83 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -83,57 +83,39 @@ namespace { constexpr const float ATM_EPS = 2000.f; constexpr const float KM_TO_M = 1000.f; - void createRenderQuad(GLuint* vao, GLuint* vbo, GLfloat size) { + void createRenderQuad(GLuint* vao, GLuint* vbo) { glGenVertexArrays(1, vao); - glGenBuffers(1, vbo); glBindVertexArray(*vao); + glGenBuffers(1, vbo); glBindBuffer(GL_ARRAY_BUFFER, *vbo); const GLfloat VertexData[] = { - // x y z w - -size, -size, 0.f, 1.f, - size, size, 0.f, 1.f, - -size, size, 0.f, 1.f, - -size, -size, 0.f, 1.f, - size, -size, 0.f, 1.f, - size, size, 0.f, 1.f + // x y z + -1.f, -1.f, + 1.f, 1.f, + -1.f, 1.f, + -1.f, -1.f, + 1.f, -1.f, + 1.f, 1.f, }; glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr); glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); glBindVertexArray(0); } - void saveTextureFile(GLenum colorBufferAttachment, - const std::filesystem::path& fileName, const glm::ivec2& size) - { - std::fstream ppmFile; - ppmFile.open(fileName, std::fstream::out); + template + void saveTextureFile(const std::filesystem::path& fileName, const glm::ivec2& size) { + std::ofstream ppmFile(fileName); if (!ppmFile.is_open()) { return; } - std::vector px( - size.x * size.y * 3, - static_cast(255) - ); + std::vector px(size.x * size.y * 3, unsigned char(255)); - if (colorBufferAttachment != GL_DEPTH_ATTACHMENT) { - glReadBuffer(colorBufferAttachment); - glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, px.data()); - } - else { - glReadPixels( - 0, - 0, - size.x, - size.y, - GL_DEPTH_COMPONENT, - GL_UNSIGNED_BYTE, - px.data() - ); - } + glReadBuffer(colorBufferAttachment); + glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, px.data()); ppmFile << "P3" << '\n' << size.x << " " << size.y << '\n' << "255" << '\n'; @@ -208,63 +190,119 @@ namespace { return true; } - void renderQuadForCalc(GLuint vao, GLsizei numberOfVertices) { + void renderQuadForCalc(GLuint vao) { glBindVertexArray(vao); - glDrawArrays(GL_TRIANGLES, 0, numberOfVertices); + glDrawArrays(GL_TRIANGLES, 0, 6); glBindVertexArray(0); } + + GLuint createTexture(const glm::ivec2& size, std::string_view name) { + GLuint t; + glGenTextures(1, &t); + glBindTexture(GL_TEXTURE_2D, t); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // Stopped using a buffer object for GL_PIXEL_UNPACK_BUFFER + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGB32F, + size.x, + size.y, + 0, + GL_RGB, + GL_FLOAT, + nullptr + ); + if (glbinding::Binding::ObjectLabel.isResolved()) { + glObjectLabel(GL_TEXTURE, t, static_cast(name.size()), name.data()); + } + return t; + } + + GLuint createTexture(const glm::ivec3& size, std::string_view name, int components) { + ghoul_assert(components == 3 || components == 4, "Only 3-4 components supported"); + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_3D, texture); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + // Stopped using a buffer object for GL_PIXEL_UNPACK_BUFFER + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glTexImage3D( + GL_TEXTURE_3D, + 0, + (components == 3) ? GL_RGB32F : GL_RGBA32F, + size.x, + size.y, + size.z, + 0, + GL_RGB, + GL_FLOAT, + nullptr + ); + if (glbinding::Binding::ObjectLabel.isResolved()) { + glObjectLabel(GL_TEXTURE, texture, name.size(), name.data()); + } + return texture; + } } // namespace namespace openspace { +AtmosphereDeferredcaster::AtmosphereDeferredcaster(float textureScale, + std::vector shadowConfigArray, + bool saveCalculatedTextures) + : _transmittanceTableSize(glm::ivec2(256 * textureScale, 64 * textureScale) ) + , _irradianceTableSize(glm::ivec2(64 * textureScale, 16 * textureScale)) + , _deltaETableSize(glm::ivec2(64 * textureScale, 16 * textureScale)) + , _muSSamples(static_cast(32 * textureScale)) + , _nuSamples(static_cast(8 * textureScale)) + , _muSamples(static_cast(128 * textureScale)) + , _rSamples(static_cast(32 * textureScale)) + , _shadowConfArray(std::move(shadowConfigArray)) + , _saveCalculationTextures(saveCalculatedTextures) + , _textureSize(_muSSamples * _nuSamples, _muSamples, _rSamples) +{ + std::memset(_uniformNameBuffer, '\0', sizeof(_uniformNameBuffer)); + std::strcpy(_uniformNameBuffer, "shadowDataArray["); + _shadowDataArrayCache.reserve(_shadowConfArray.size()); +} + void AtmosphereDeferredcaster::initialize() { ZoneScoped - if (!_atmosphereCalculated) { - preCalculateAtmosphereParam(); - } - - std::memset(_uniformNameBuffer, 0, sizeof(_uniformNameBuffer)); - std::strcpy(_uniformNameBuffer, "shadowDataArray["); + _transmittanceTableTexture = createTexture(_transmittanceTableSize, "Transmittance"); + _irradianceTableTexture = createTexture(_irradianceTableSize, "Irradiance"); + _inScatteringTableTexture = createTexture(_textureSize, "InScattering", 4); + calculateAtmosphereParameters(); } void AtmosphereDeferredcaster::deinitialize() { ZoneScoped - _transmittanceProgramObject = nullptr; - _irradianceProgramObject = nullptr; - _irradianceSupTermsProgramObject = nullptr; - _inScatteringProgramObject = nullptr; - _inScatteringSupTermsProgramObject = nullptr; - _deltaEProgramObject = nullptr; - _deltaSProgramObject = nullptr; - _deltaSSupTermsProgramObject = nullptr; - _deltaJProgramObject = nullptr; - glDeleteTextures(1, &_transmittanceTableTexture); glDeleteTextures(1, &_irradianceTableTexture); glDeleteTextures(1, &_inScatteringTableTexture); - glDeleteTextures(1, &_deltaETableTexture); - glDeleteTextures(1, &_deltaSRayleighTableTexture); - glDeleteTextures(1, &_deltaSMieTableTexture); - glDeleteTextures(1, &_deltaJTableTexture); } -void AtmosphereDeferredcaster::preRaycast(const RenderData& renderData, - const DeferredcastData&, - ghoul::opengl::ProgramObject& program) +void AtmosphereDeferredcaster::update(const UpdateData&) {} + +void AtmosphereDeferredcaster::preRaycast(const RenderData& data, const DeferredcastData&, + ghoul::opengl::ProgramObject& prg) { ZoneScoped // Atmosphere Frustum Culling - glm::dvec3 tPlanetPosWorld = glm::dvec3( - _modelTransform * glm::dvec4(0.0, 0.0, 0.0, 1.0) - ); - - const double distance = glm::distance( - tPlanetPosWorld, - renderData.camera.eyePositionVec3() - ); + glm::dvec3 tPlanetPos = glm::dvec3(_modelTransform * glm::dvec4(0.0, 0.0, 0.0, 1.0)); + const double distance = glm::distance(tPlanetPos, data.camera.eyePositionVec3()); // Radius is in KM const double scaledRadius = glm::length( @@ -272,232 +310,180 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& renderData, ); // Number of planet radii to use as distance threshold for culling - const double DISTANCE_CULLING_RADII = 5000; - if (distance > scaledRadius * DISTANCE_CULLING_RADII) { - program.setUniform(_uniformCache.cullAtmosphere, 1); - } - else { - glm::dmat4 MV = glm::dmat4(renderData.camera.sgctInternal.projectionMatrix()) * - renderData.camera.combinedViewMatrix(); + prg.setUniform(_uniformCache.cullAtmosphere, 1); - const double totalAtmosphere = (scaledRadius + ATM_EPS); - if (!isAtmosphereInFrustum(MV, tPlanetPosWorld, totalAtmosphere)) { - program.setUniform(_uniformCache.cullAtmosphere, 1); + constexpr const double DistanceCullingRadii = 5000; + glm::dmat4 MV = glm::dmat4(data.camera.sgctInternal.projectionMatrix()) * + data.camera.combinedViewMatrix(); + if (distance <= scaledRadius * DistanceCullingRadii && + isAtmosphereInFrustum(MV, tPlanetPos, scaledRadius + ATM_EPS)) + { + prg.setUniform(_uniformCache.cullAtmosphere, 0); + prg.setUniform(_uniformCache.Rg, _atmospherePlanetRadius); + prg.setUniform(_uniformCache.Rt, _atmosphereRadius); + prg.setUniform(_uniformCache.groundRadianceEmission, _groundRadianceEmission); + prg.setUniform(_uniformCache.HR, _rayleighHeightScale); + prg.setUniform(_uniformCache.betaRayleigh, _rayleighScatteringCoeff); + prg.setUniform(_uniformCache.HM, _mieHeightScale); + prg.setUniform(_uniformCache.betaMieExtinction, _mieExtinctionCoeff); + prg.setUniform(_uniformCache.mieG, _miePhaseConstant); + prg.setUniform(_uniformCache.sunRadiance, _sunRadianceIntensity); + prg.setUniform(_uniformCache.ozoneLayerEnabled, _ozoneEnabled); + prg.setUniform(_uniformCache.HO, _ozoneHeightScale); + prg.setUniform(_uniformCache.betaOzoneExtinction, _ozoneExtinctionCoeff); + prg.setUniform(_uniformCache.SAMPLES_R, _rSamples); + prg.setUniform(_uniformCache.SAMPLES_MU, _muSamples); + prg.setUniform(_uniformCache.SAMPLES_MU_S, _muSSamples); + prg.setUniform(_uniformCache.SAMPLES_NU, _nuSamples); + + // Object Space + glm::dmat4 invModelMatrix = glm::inverse(_modelTransform); + prg.setUniform(_uniformCache.inverseModelTransformMatrix, invModelMatrix); + prg.setUniform(_uniformCache.modelTransformMatrix, _modelTransform); + + glm::dmat4 viewToWorldMatrix = glm::inverse(data.camera.combinedViewMatrix()); + + // Eye Space to World Space + prg.setUniform(_uniformCache.viewToWorldMatrix, viewToWorldMatrix); + + // Projection to Eye Space + glm::dmat4 dInvProj = glm::inverse(glm::dmat4(data.camera.projectionMatrix())); + + glm::dmat4 invWholePipeline = invModelMatrix * viewToWorldMatrix * dInvProj; + + prg.setUniform(_uniformCache.projectionToModelTransform, invWholePipeline); + + glm::dvec4 camPosObjCoords = + invModelMatrix * glm::dvec4(data.camera.eyePositionVec3(), 1.0); + prg.setUniform(_uniformCache.camPosObj, glm::dvec3(camPosObjCoords)); + + SceneGraphNode* node = sceneGraph()->sceneGraphNode("Sun"); + glm::dvec3 sunPosWorld = node ? node->worldPosition() : glm::dvec3(0.0); + + glm::dvec3 sunPosObj; + // Sun following camera position + if (_sunFollowingCameraEnabled) { + sunPosObj = invModelMatrix * glm::dvec4(data.camera.eyePositionVec3(), 1.0); } else { - program.setUniform(_uniformCache.cullAtmosphere, 0); - program.setUniform(_uniformCache.Rg, _atmospherePlanetRadius); - program.setUniform(_uniformCache.Rt, _atmosphereRadius); - program.setUniform( - _uniformCache.groundRadianceEmission, - _planetGroundRadianceEmission - ); - program.setUniform(_uniformCache.HR, _rayleighHeightScale); - program.setUniform(_uniformCache.betaRayleigh, _rayleighScatteringCoeff); - program.setUniform(_uniformCache.HM, _mieHeightScale); - program.setUniform(_uniformCache.betaMieExtinction, _mieExtinctionCoeff); - program.setUniform(_uniformCache.mieG, _miePhaseConstant); - program.setUniform(_uniformCache.sunRadiance, _sunRadianceIntensity); - program.setUniform(_uniformCache.ozoneLayerEnabled, _ozoneEnabled); - program.setUniform(_uniformCache.HO, _ozoneHeightScale); - program.setUniform(_uniformCache.betaOzoneExtinction, _ozoneExtinctionCoeff); - program.setUniform(_uniformCache.SAMPLES_R, _r_samples); - program.setUniform(_uniformCache.SAMPLES_MU, _mu_samples); - program.setUniform(_uniformCache.SAMPLES_MU_S, _mu_s_samples); - program.setUniform(_uniformCache.SAMPLES_NU, _nu_samples); - - // Object Space - glm::dmat4 inverseModelMatrix = glm::inverse(_modelTransform); - program.setUniform( - _uniformCache.inverseModelTransformMatrix, inverseModelMatrix - ); - program.setUniform(_uniformCache.modelTransformMatrix, _modelTransform); - - glm::dmat4 viewToWorldMatrix = glm::inverse( - renderData.camera.combinedViewMatrix() - ); - - // Eye Space to World Space - program.setUniform(_uniformCache.viewToWorldMatrix, viewToWorldMatrix); - - // Projection to Eye Space - glm::dmat4 dInverseProjection = glm::inverse( - glm::dmat4(renderData.camera.projectionMatrix()) - ); - - glm::dmat4 inverseWholeMatrixPipeline = - inverseModelMatrix * viewToWorldMatrix * dInverseProjection; - - program.setUniform( - _uniformCache.projectionToModelTransformMatrix, - inverseWholeMatrixPipeline - ); - - glm::dvec4 camPosObjCoords = - inverseModelMatrix * glm::dvec4(renderData.camera.eyePositionVec3(), 1.0); - program.setUniform(_uniformCache.camPosObj, glm::dvec3(camPosObjCoords)); - - SceneGraphNode* node = sceneGraph()->sceneGraphNode("Sun"); - glm::dvec3 sunPosWorld = node ? node->worldPosition() : glm::dvec3(0.0); - - glm::dvec4 sunPosObj; - // Sun following camera position - if (_sunFollowingCameraEnabled) { - sunPosObj = inverseModelMatrix * glm::dvec4( - renderData.camera.eyePositionVec3(), - 1.0 - ); - } - else { - sunPosObj = inverseModelMatrix * - glm::dvec4( - (sunPosWorld - renderData.modelTransform.translation) * 1000.0, - 1.0 - ); - } - - // Sun Position in Object Space - program.setUniform( - _uniformCache.sunDirectionObj, - glm::normalize(glm::dvec3(sunPosObj)) - ); - - ghoul::opengl::updateUniformLocations(program, _uniformCache, UniformNames); - - // Shadow calculations.. - if (!_shadowConfArray.empty()) { - ZoneScopedN("Shadow Configuration") - - _shadowDataArrayCache.clear(); - - for (const ShadowConfiguration& shadowConf : _shadowConfArray) { - // TO REMEMBER: all distances and lengths in world coordinates are in - // meters!!! We need to move this to view space... - // Getting source and caster: - double lt; - glm::dvec3 sourcePos = SpiceManager::ref().targetPosition( - shadowConf.source.first, - "SSB", - "GALACTIC", - {}, - _time, - lt - ); - sourcePos *= KM_TO_M; // converting to meters - glm::dvec3 casterPos = SpiceManager::ref().targetPosition( - shadowConf.caster.first, - "SSB", - "GALACTIC", - {}, - _time, - lt - ); - casterPos *= KM_TO_M; // converting to meters - - SceneGraphNode* sourceNode = sceneGraphNode(shadowConf.source.first); - SceneGraphNode* casterNode = sceneGraphNode(shadowConf.caster.first); - - if ((sourceNode == nullptr) || (casterNode == nullptr)) { - LERRORC( - "AtmosphereDeferredcaster", - "Invalid scenegraph node for the shadow's caster or shadow's " - "receiver" - ); - return; - } - - const double sourceRadiusScale = std::max( - glm::compMax(sourceNode->scale()), - 1.0 - ); - - const double casterRadiusScale = std::max( - glm::compMax(casterNode->scale()), - 1.0 - ); - - // First we determine if the caster is shadowing the current planet - // (all calculations in World Coordinates): - glm::dvec3 planetCasterVec = - casterPos - renderData.modelTransform.translation; - glm::dvec3 sourceCasterVec = casterPos - sourcePos; - double sc_length = glm::length(sourceCasterVec); - glm::dvec3 planetCaster_proj = ( - glm::dot(planetCasterVec, sourceCasterVec) / - (sc_length*sc_length)) * sourceCasterVec; - double d_test = glm::length(planetCasterVec - planetCaster_proj); - double xp_test = shadowConf.caster.second * casterRadiusScale * - sc_length / - (shadowConf.source.second * sourceRadiusScale + - shadowConf.caster.second * casterRadiusScale); - double rp_test = shadowConf.caster.second * casterRadiusScale * - (glm::length(planetCaster_proj) + xp_test) / xp_test; - - double casterDistSun = glm::length(casterPos - sunPosWorld); - double planetDistSun = glm::length( - renderData.modelTransform.translation - sunPosWorld - ); - - ShadowRenderingStruct shadowData; - shadowData.isShadowing = false; - - if (((d_test - rp_test) < (_atmospherePlanetRadius * KM_TO_M)) && - (casterDistSun < planetDistSun)) - { - // The current caster is shadowing the current planet - shadowData.isShadowing = true; - shadowData.rs = shadowConf.source.second * sourceRadiusScale; - shadowData.rc = shadowConf.caster.second * casterRadiusScale; - shadowData.sourceCasterVec = glm::normalize(sourceCasterVec); - shadowData.xp = xp_test; - shadowData.xu = - shadowData.rc * sc_length / (shadowData.rs - shadowData.rc); - shadowData.casterPositionVec = casterPos; - } - _shadowDataArrayCache.push_back(shadowData); - } - - // _uniformNameBuffer[0..15] = "shadowDataArray[" - unsigned int counter = 0; - for (const ShadowRenderingStruct& sd : _shadowDataArrayCache) { - // Add the counter - char* bf = fmt::format_to(_uniformNameBuffer + 16, "{}", counter); - - std::strcpy(bf, "].isShadowing\0"); - program.setUniform(_uniformNameBuffer, sd.isShadowing); - - if (sd.isShadowing) { - std::strcpy(bf, "].xp\0"); - program.setUniform(_uniformNameBuffer, sd.xp); - std::strcpy(bf, "].xu\0"); - program.setUniform(_uniformNameBuffer, sd.xu); - std::strcpy(bf, "].rc\0"); - program.setUniform(_uniformNameBuffer, sd.rc); - std::strcpy(bf, "].sourceCasterVec\0"); - program.setUniform(_uniformNameBuffer, sd.sourceCasterVec); - std::strcpy(bf, "].casterPositionVec\0"); - program.setUniform(_uniformNameBuffer, sd.casterPositionVec); - } - counter++; - } - program.setUniform(_uniformCache.hardShadows, _hardShadowsEnabled); - } + sunPosObj = invModelMatrix * + glm::dvec4((sunPosWorld - data.modelTransform.translation) * 1000.0, 1.0); } + + // Sun Position in Object Space + prg.setUniform(_uniformCache.sunDirectionObj, glm::normalize(sunPosObj)); + + // Shadow calculations.. + _shadowDataArrayCache.clear(); + for (const ShadowConfiguration& shadowConf : _shadowConfArray) { + // TO REMEMBER: all distances and lengths in world coordinates are in + // meters!!! We need to move this to view space... + double lt; + glm::dvec3 sourcePos = SpiceManager::ref().targetPosition( + shadowConf.source.first, + "SSB", + "GALACTIC", + {}, + data.time.j2000Seconds(), + lt + ); + sourcePos *= KM_TO_M; // converting to meters + glm::dvec3 casterPos = SpiceManager::ref().targetPosition( + shadowConf.caster.first, + "SSB", + "GALACTIC", + {}, + data.time.j2000Seconds(), + lt + ); + casterPos *= KM_TO_M; // converting to meters + + SceneGraphNode* sourceNode = sceneGraphNode(shadowConf.source.first); + SceneGraphNode* casterNode = sceneGraphNode(shadowConf.caster.first); + + if (!sourceNode || !casterNode) { + LERROR("Invalid scenegraph node for the shadow's caster or receiver"); + return; + } + + const double sourceScale = std::max(glm::compMax(sourceNode->scale()), 1.0); + const double casterScale = std::max(glm::compMax(casterNode->scale()), 1.0); + + // First we determine if the caster is shadowing the current planet + // (all calculations in World Coordinates): + glm::dvec3 planetCasterVec = casterPos - data.modelTransform.translation; + glm::dvec3 sourceCasterVec = casterPos - sourcePos; + double scLength = glm::length(sourceCasterVec); + glm::dvec3 planetCasterProj = + (glm::dot(planetCasterVec, sourceCasterVec) / (scLength * scLength)) * + sourceCasterVec; + double dTest = glm::length(planetCasterVec - planetCasterProj); + double xpTest = shadowConf.caster.second * casterScale * + scLength / + (shadowConf.source.second * sourceScale + + shadowConf.caster.second * casterScale); + double rpTest = shadowConf.caster.second * casterScale * + (glm::length(planetCasterProj) + xpTest) / xpTest; + + double casterDistSun = glm::length(casterPos - sunPosWorld); + double planetDistSun = glm::length( + data.modelTransform.translation - sunPosWorld + ); + + ShadowRenderingStruct shadow; + shadow.isShadowing = false; + + if (((dTest - rpTest) < (_atmospherePlanetRadius * KM_TO_M)) && + (casterDistSun < planetDistSun)) + { + // The current caster is shadowing the current planet + shadow.isShadowing = true; + shadow.rs = shadowConf.source.second * sourceScale; + shadow.rc = shadowConf.caster.second * casterScale; + shadow.sourceCasterVec = glm::normalize(sourceCasterVec); + shadow.xp = xpTest; + shadow.xu = shadow.rc * scLength / (shadow.rs - shadow.rc); + shadow.casterPositionVec = casterPos; + } + _shadowDataArrayCache.push_back(shadow); + } + + // _uniformNameBuffer[0..15] = "shadowDataArray[" + unsigned int counter = 0; + for (const ShadowRenderingStruct& sd : _shadowDataArrayCache) { + // Add the counter + char* bf = fmt::format_to(_uniformNameBuffer + 16, "{}", counter); + + std::strcpy(bf, "].isShadowing\0"); + prg.setUniform(_uniformNameBuffer, sd.isShadowing); + + if (sd.isShadowing) { + std::strcpy(bf, "].xp\0"); + prg.setUniform(_uniformNameBuffer, sd.xp); + std::strcpy(bf, "].xu\0"); + prg.setUniform(_uniformNameBuffer, sd.xu); + std::strcpy(bf, "].rc\0"); + prg.setUniform(_uniformNameBuffer, sd.rc); + std::strcpy(bf, "].sourceCasterVec\0"); + prg.setUniform(_uniformNameBuffer, sd.sourceCasterVec); + std::strcpy(bf, "].casterPositionVec\0"); + prg.setUniform(_uniformNameBuffer, sd.casterPositionVec); + } + counter++; + } + prg.setUniform(_uniformCache.hardShadows, _hardShadowsEnabled); } _transmittanceTableTextureUnit.activate(); glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - program.setUniform( - _uniformCache.transmittanceTexture, - _transmittanceTableTextureUnit - ); + prg.setUniform(_uniformCache.transmittanceTexture, _transmittanceTableTextureUnit); _irradianceTableTextureUnit.activate(); glBindTexture(GL_TEXTURE_2D, _irradianceTableTexture); - program.setUniform(_uniformCache.irradianceTexture, _irradianceTableTextureUnit); + prg.setUniform(_uniformCache.irradianceTexture, _irradianceTableTextureUnit); _inScatteringTableTextureUnit.activate(); glBindTexture(GL_TEXTURE_3D, _inScatteringTableTexture); - program.setUniform(_uniformCache.inscatterTexture, _inScatteringTableTextureUnit); + prg.setUniform(_uniformCache.inscatterTexture, _inScatteringTableTextureUnit); } void AtmosphereDeferredcaster::postRaycast(const RenderData&, const DeferredcastData&, @@ -511,10 +497,6 @@ void AtmosphereDeferredcaster::postRaycast(const RenderData&, const Deferredcast _inScatteringTableTextureUnit.deactivate(); } -std::filesystem::path AtmosphereDeferredcaster::deferredcastPath() const { - return absPath("${MODULE_ATMOSPHERE}/shaders/atmosphere_deferred_fs.glsl"); -} - std::filesystem::path AtmosphereDeferredcaster::deferredcastFSPath() const { return absPath("${MODULE_ATMOSPHERE}/shaders/atmosphere_deferred_fs.glsl"); } @@ -533,453 +515,44 @@ void AtmosphereDeferredcaster::initializeCachedVariables( ghoul::opengl::updateUniformLocations(program, _uniformCache, UniformNames); } -void AtmosphereDeferredcaster::update(const UpdateData&) {} - void AtmosphereDeferredcaster::setModelTransform(glm::dmat4 transform) { _modelTransform = std::move(transform); } -void AtmosphereDeferredcaster::setTime(double time) { - _time = time; -} - -void AtmosphereDeferredcaster::setAtmosphereRadius(float atmRadius) { - _atmosphereRadius = atmRadius; -} - -void AtmosphereDeferredcaster::setPlanetRadius(float planetRadius) { +void AtmosphereDeferredcaster::setParameters(float atmosphereRadius, float planetRadius, + float averageGroundReflectance, + float groundRadianceEmission, + float rayleighHeightScale, bool enableOzone, + float ozoneHeightScale, float mieHeightScale, + float miePhaseConstant, float sunRadiance, + glm::vec3 rayScatteringCoefficients, + glm::vec3 ozoneExtinctionCoefficients, + glm::vec3 mieScatteringCoefficients, + glm::vec3 mieExtinctionCoefficients, + bool sunFollowing) +{ + _atmosphereRadius = atmosphereRadius; _atmospherePlanetRadius = planetRadius; -} - -void AtmosphereDeferredcaster::setPlanetAverageGroundReflectance( - float averageGReflectance) -{ - _planetAverageGroundReflectance = averageGReflectance; -} - -void AtmosphereDeferredcaster::setPlanetGroundRadianceEmission( - float groundRadianceEmission) -{ - _planetGroundRadianceEmission = groundRadianceEmission; -} - -void AtmosphereDeferredcaster::setRayleighHeightScale(float rayleighHeightScale) { + _averageGroundReflectance = averageGroundReflectance; + _groundRadianceEmission = groundRadianceEmission; _rayleighHeightScale = rayleighHeightScale; -} - -void AtmosphereDeferredcaster::enableOzone(bool enable) { - _ozoneEnabled = enable; -} - -void AtmosphereDeferredcaster::setOzoneHeightScale(float ozoneHeightScale) { + _ozoneEnabled = enableOzone; _ozoneHeightScale = ozoneHeightScale; -} - -void AtmosphereDeferredcaster::setMieHeightScale(float mieHeightScale) { _mieHeightScale = mieHeightScale; -} - -void AtmosphereDeferredcaster::setMiePhaseConstant(float miePhaseConstant) { _miePhaseConstant = miePhaseConstant; -} - -void AtmosphereDeferredcaster::setSunRadianceIntensity(float sunRadiance) { _sunRadianceIntensity = sunRadiance; -} - -void AtmosphereDeferredcaster::setRayleighScatteringCoefficients(glm::vec3 rayScattCoeff) -{ - _rayleighScatteringCoeff = std::move(rayScattCoeff); -} - -void AtmosphereDeferredcaster::setOzoneExtinctionCoefficients(glm::vec3 ozoneExtCoeff) { - _ozoneExtinctionCoeff = std::move(ozoneExtCoeff); -} - -void AtmosphereDeferredcaster::setMieScatteringCoefficients(glm::vec3 mieScattCoeff) { - _mieScatteringCoeff = std::move(mieScattCoeff); -} - -void AtmosphereDeferredcaster::setMieExtinctionCoefficients(glm::vec3 mieExtCoeff) { - _mieExtinctionCoeff = std::move(mieExtCoeff); -} - -void AtmosphereDeferredcaster::setEllipsoidRadii(glm::dvec3 radii) { - _ellipsoidRadii = std::move(radii); + _rayleighScatteringCoeff = std::move(rayScatteringCoefficients); + _ozoneExtinctionCoeff = std::move(ozoneExtinctionCoefficients); + _mieScatteringCoeff = std::move(mieScatteringCoefficients); + _mieExtinctionCoeff = std::move(mieExtinctionCoefficients); + _sunFollowingCameraEnabled = sunFollowing; } void AtmosphereDeferredcaster::setHardShadows(bool enabled) { _hardShadowsEnabled = enabled; } -void AtmosphereDeferredcaster::setShadowConfigArray( - std::vector shadowConfigArray) -{ - _shadowConfArray = std::move(shadowConfigArray); - - _shadowDataArrayCache.clear(); - _shadowDataArrayCache.reserve(_shadowConfArray.size()); -} - -void AtmosphereDeferredcaster::enableSunFollowing(bool enable) { - _sunFollowingCameraEnabled = enable; -} - -void AtmosphereDeferredcaster::setPrecalculationTextureScale( - float preCalculatedTexturesScale) -{ - _transmittanceTableSize *= static_cast(preCalculatedTexturesScale); - _irradianceTableSize *= static_cast(preCalculatedTexturesScale); - _deltaETableSize *= static_cast(preCalculatedTexturesScale); - _r_samples *= static_cast(preCalculatedTexturesScale); - _mu_samples *= static_cast(preCalculatedTexturesScale); - _mu_s_samples *= static_cast(preCalculatedTexturesScale); - _nu_samples *= static_cast(preCalculatedTexturesScale); -} - -void AtmosphereDeferredcaster::enablePrecalculationTexturesSaving() { - _saveCalculationTextures = true; -} - -void AtmosphereDeferredcaster::loadComputationPrograms() { - // - // Transmittance T - if (!_transmittanceProgramObject) { - _transmittanceProgramObject = ghoul::opengl::ProgramObject::Build( - "transmittanceCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/transmittance_calc_fs.glsl") - ); - } - using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; - _transmittanceProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - // - // Irradiance E - if (!_irradianceProgramObject) { - _irradianceProgramObject = ghoul::opengl::ProgramObject::Build( - "irradianceCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/irradiance_calc_fs.glsl") - ); - } - _irradianceProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - if (!_irradianceSupTermsProgramObject) { - _irradianceSupTermsProgramObject = ghoul::opengl::ProgramObject::Build( - "irradianceSupTermsCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/irradiance_sup_calc_fs.glsl") - ); - } - _irradianceSupTermsProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - // - // InScattering S - if (!_inScatteringProgramObject) { - _inScatteringProgramObject = ghoul::opengl::ProgramObject::Build( - "inScatteringCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/inScattering_calc_fs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") - ); - } - _inScatteringProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - if (!_inScatteringSupTermsProgramObject) { - _inScatteringSupTermsProgramObject = ghoul::opengl::ProgramObject::Build( - "inScatteringSupTermsCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/inScattering_sup_calc_fs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") - ); - } - _inScatteringSupTermsProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - // - // Delta E - if (!_deltaEProgramObject) { - _deltaEProgramObject = ghoul::opengl::ProgramObject::Build( - "deltaECalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/deltaE_calc_fs.glsl") - ); - } - _deltaEProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - // - // Irradiance finel E - if (!_irradianceFinalProgramObject) { - _irradianceFinalProgramObject = ghoul::opengl::ProgramObject::Build( - "irradianceEFinalProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/irradiance_final_fs.glsl") - ); - } - _irradianceFinalProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - // - // Delta S - if (!_deltaSProgramObject) { - _deltaSProgramObject = ghoul::opengl::ProgramObject::Build( - "deltaSCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/deltaS_calc_fs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") - ); - } - _deltaSProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - if (!_deltaSSupTermsProgramObject) { - _deltaSSupTermsProgramObject = ghoul::opengl::ProgramObject::Build( - "deltaSSUPTermsCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/deltaS_sup_calc_fs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") - ); - } - _deltaSSupTermsProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); - - // - // Delta J (Radiance Scattered) - if (!_deltaJProgramObject) { - _deltaJProgramObject = ghoul::opengl::ProgramObject::Build( - "deltaJCalcProgram", - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/deltaJ_calc_fs.glsl"), - absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") - ); - } - _deltaJProgramObject->setIgnoreUniformLocationError(IgnoreError::Yes); -} - -void AtmosphereDeferredcaster::unloadComputationPrograms() { - _transmittanceProgramObject = nullptr; - _irradianceProgramObject = nullptr; - _irradianceSupTermsProgramObject = nullptr; - _inScatteringProgramObject = nullptr; - _inScatteringSupTermsProgramObject = nullptr; - _deltaEProgramObject = nullptr; - _irradianceFinalProgramObject = nullptr; - _deltaSProgramObject = nullptr; - _deltaSSupTermsProgramObject = nullptr; - _deltaJProgramObject = nullptr; -} - -void AtmosphereDeferredcaster::createComputationTextures() { - if (!_atmosphereCalculated) { - // - // Transmittance - ghoul::opengl::TextureUnit transmittanceTableTextureUnit; - transmittanceTableTextureUnit.activate(); - glGenTextures(1, &_transmittanceTableTexture); - glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // Stopped using a buffer object for GL_PIXEL_UNPACK_BUFFER - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB32F, - _transmittanceTableSize.x, - _transmittanceTableSize.y, - 0, - GL_RGB, - GL_FLOAT, - nullptr - ); - - // - // Irradiance - ghoul::opengl::TextureUnit irradianceTableTextureUnit; - irradianceTableTextureUnit.activate(); - glGenTextures(1, &_irradianceTableTexture); - glBindTexture(GL_TEXTURE_2D, _irradianceTableTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB32F, - _irradianceTableSize.x, - _irradianceTableSize.y, - 0, - GL_RGB, - GL_FLOAT, - nullptr - ); - - // - // InScattering - ghoul::opengl::TextureUnit inScatteringTableTextureUnit; - inScatteringTableTextureUnit.activate(); - glGenTextures(1, &_inScatteringTableTexture); - glBindTexture(GL_TEXTURE_3D, _inScatteringTableTexture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage3D( - GL_TEXTURE_3D, - 0, - GL_RGBA32F, - _mu_s_samples * _nu_samples, - _mu_samples, - _r_samples, - 0, - GL_RGB, - GL_FLOAT, - nullptr - ); - } - - // - // Delta E - ghoul::opengl::TextureUnit deltaETableTextureUnit; - deltaETableTextureUnit.activate(); - glGenTextures(1, &_deltaETableTexture); - glBindTexture(GL_TEXTURE_2D, _deltaETableTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGB32F, - _deltaETableSize.x, - _deltaETableSize.y, - 0, - GL_RGB, - GL_FLOAT, - nullptr - ); - - // - // Delta S - ghoul::opengl::TextureUnit deltaSRayleighTableTextureUnit; - deltaSRayleighTableTextureUnit.activate(); - glGenTextures(1, &_deltaSRayleighTableTexture); - glBindTexture(GL_TEXTURE_3D, _deltaSRayleighTableTexture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage3D( - GL_TEXTURE_3D, - 0, - GL_RGB32F, - _mu_s_samples * _nu_samples, - _mu_samples, - _r_samples, - 0, GL_RGB, - GL_FLOAT, - nullptr - ); - - ghoul::opengl::TextureUnit deltaSMieTableTextureUnit; - deltaSMieTableTextureUnit.activate(); - glGenTextures(1, &_deltaSMieTableTexture); - glBindTexture(GL_TEXTURE_3D, _deltaSMieTableTexture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage3D( - GL_TEXTURE_3D, - 0, - GL_RGB32F, - _mu_s_samples * _nu_samples, - _mu_samples, - _r_samples, - 0, - GL_RGB, - GL_FLOAT, - nullptr - ); - - // - // Delta J (Radiance Scattered) - ghoul::opengl::TextureUnit deltaJTableTextureUnit; - deltaJTableTextureUnit.activate(); - glGenTextures(1, &_deltaJTableTexture); - glBindTexture(GL_TEXTURE_3D, _deltaJTableTexture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glTexImage3D( - GL_TEXTURE_3D, - 0, - GL_RGB32F, - _mu_s_samples * _nu_samples, - _mu_samples, - _r_samples, - 0, - GL_RGB, - GL_FLOAT, - nullptr - ); -} - -void AtmosphereDeferredcaster::deleteComputationTextures() { - glDeleteTextures(1, &_transmittanceTableTexture); - _transmittanceTableTexture = 0; - glDeleteTextures(1, &_irradianceTableTexture); - _irradianceTableTexture = 0; - glDeleteTextures(1, &_inScatteringTableTexture); - _inScatteringTableTexture = 0; - glDeleteTextures(1, &_deltaETableTexture); - _deltaETableTexture = 0; - glDeleteTextures(1, &_deltaSRayleighTableTexture); - _deltaSRayleighTableTexture = 0; - glDeleteTextures(1, &_deltaSMieTableTexture); - _deltaSMieTableTexture = 0; - glDeleteTextures(1, &_deltaJTableTexture); - _deltaJTableTexture = 0; -} - -void AtmosphereDeferredcaster::deleteUnusedComputationTextures() { - glDeleteTextures(1, &_deltaETableTexture); - _deltaETableTexture = 0; - glDeleteTextures(1, &_deltaSRayleighTableTexture); - _deltaSRayleighTableTexture = 0; - glDeleteTextures(1, &_deltaSMieTableTexture); - _deltaSMieTableTexture = 0; - glDeleteTextures(1, &_deltaJTableTexture); - _deltaJTableTexture = 0; -} - -void AtmosphereDeferredcaster::executeCalculations(GLuint quadCalcVAO, - GLenum drawBuffers[1], - GLsizei vertexSize) -{ - ghoul::opengl::TextureUnit transmittanceTableTextureUnit; - ghoul::opengl::TextureUnit irradianceTableTextureUnit; - ghoul::opengl::TextureUnit inScatteringTableTextureUnit; - ghoul::opengl::TextureUnit deltaETableTextureUnit; - ghoul::opengl::TextureUnit deltaSRayleighTableTextureUnit; - ghoul::opengl::TextureUnit deltaSMieTableTextureUnit; - ghoul::opengl::TextureUnit deltaJTableTextureUnit; - - glDisable(GL_BLEND); - - // See Precomputed Atmosphere Scattering from Bruneton et al. paper, algorithm 4.1: +void AtmosphereDeferredcaster::calculateTransmittance(GLuint vao) { glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -987,90 +560,113 @@ void AtmosphereDeferredcaster::executeCalculations(GLuint quadCalcVAO, 0 ); glViewport(0, 0, _transmittanceTableSize.x, _transmittanceTableSize.y); - _transmittanceProgramObject->activate(); - loadAtmosphereDataIntoShaderProgram(*_transmittanceProgramObject); + using ProgramObject = ghoul::opengl::ProgramObject; + std::unique_ptr program = ProgramObject::Build( + "Transmittance Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/transmittance_calc_fs.glsl") + ); + program->activate(); + program->setUniform("Rg", _atmospherePlanetRadius); + program->setUniform("Rt", _atmosphereRadius); + program->setUniform("HR", _rayleighHeightScale); + program->setUniform("betaRayleigh", _rayleighScatteringCoeff); + program->setUniform("HM", _mieHeightScale); + program->setUniform("betaMieExtinction", _mieExtinctionCoeff); + program->setUniform("TRANSMITTANCE", _transmittanceTableSize); + program->setUniform("ozoneLayerEnabled", _ozoneEnabled); + program->setUniform("HO", _ozoneHeightScale); + program->setUniform("betaOzoneExtinction", _ozoneExtinctionCoeff); - static const float Black[] = { 0.f, 0.f, 0.f, 0.f }; + constexpr const float Black[] = { 0.f, 0.f, 0.f, 0.f }; glClearBufferfv(GL_COLOR, 0, Black); - renderQuadForCalc(quadCalcVAO, vertexSize); + renderQuadForCalc(vao); if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - "transmittance_texture.ppm", - _transmittanceTableSize - ); + saveTextureFile("transmittance_texture.ppm", _transmittanceTableSize); } - _transmittanceProgramObject->deactivate(); + program->deactivate(); +} - // line 2 in algorithm 4.1 - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _deltaETableTexture, 0); +GLuint AtmosphereDeferredcaster::calculateDeltaE(GLuint vao) { + GLuint deltaE = createTexture(_deltaETableSize, "DeltaE"); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); - _irradianceProgramObject->activate(); - transmittanceTableTextureUnit.activate(); + using ProgramObject = ghoul::opengl::ProgramObject; + std::unique_ptr program = ProgramObject::Build( + "Irradiance Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/irradiance_calc_fs.glsl") + ); + program->activate(); + ghoul::opengl::TextureUnit unit; + unit.activate(); glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - _irradianceProgramObject->setUniform( - "transmittanceTexture", - transmittanceTableTextureUnit - ); - loadAtmosphereDataIntoShaderProgram(*_irradianceProgramObject); + program->setUniform("transmittanceTexture", unit); + program->setUniform("Rg", _atmospherePlanetRadius); + program->setUniform("Rt", _atmosphereRadius); + program->setUniform("OTHER_TEXTURES", _deltaETableSize); glClear(GL_COLOR_BUFFER_BIT); - renderQuadForCalc(quadCalcVAO, vertexSize); + renderQuadForCalc(vao); if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - "deltaE_table_texture.ppm", - _deltaETableSize - ); + saveTextureFile("deltaE_table_texture.ppm", _deltaETableSize); } - _irradianceProgramObject->deactivate(); + program->deactivate(); + return deltaE; +} - // line 3 in algorithm 4.1 - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - _deltaSRayleighTableTexture, - 0 - ); - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT1, - _deltaSMieTableTexture, - 0 - ); +std::pair AtmosphereDeferredcaster::calculateDeltaS(GLuint vao) { + GLuint deltaSRayleigh = createTexture(_textureSize, "DeltaS Rayleigh", 3); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); + GLuint deltaSMie = createTexture(_textureSize, "DeltaS Mie", 3); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, deltaSMie, 0); GLenum colorBuffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; glDrawBuffers(2, colorBuffers); - glViewport(0, 0, _mu_s_samples * _nu_samples, _mu_samples); - _inScatteringProgramObject->activate(); - transmittanceTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - _inScatteringProgramObject->setUniform( - "transmittanceTexture", - transmittanceTableTextureUnit + glViewport(0, 0, _textureSize.x, _textureSize.y); + using ProgramObject = ghoul::opengl::ProgramObject; + std::unique_ptr program = ProgramObject::Build( + "InScattering Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/inScattering_calc_fs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") ); - loadAtmosphereDataIntoShaderProgram(*_inScatteringProgramObject); + program->activate(); + ghoul::opengl::TextureUnit unit; + unit.activate(); + glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); + program->setUniform("transmittanceTexture", unit); + program->setUniform("Rg", _atmospherePlanetRadius); + program->setUniform("Rt", _atmosphereRadius); + program->setUniform("HR", _rayleighHeightScale); + program->setUniform("betaRayleigh", _rayleighScatteringCoeff); + program->setUniform("HM", _mieHeightScale); + program->setUniform("betaMieScattering", _mieScatteringCoeff); + program->setUniform("SAMPLES_MU_S", _muSSamples); + program->setUniform("SAMPLES_NU", _nuSamples); + program->setUniform("SAMPLES_MU", _muSamples); + program->setUniform("ozoneLayerEnabled", _ozoneEnabled); + program->setUniform("HO", _ozoneHeightScale); glClear(GL_COLOR_BUFFER_BIT); - for (int layer = 0; layer < _r_samples; ++layer) { - step3DTexture(*_inScatteringProgramObject, layer, true); - renderQuadForCalc(quadCalcVAO, vertexSize); + for (int layer = 0; layer < _rSamples; ++layer) { + program->setUniform("layer", layer); + step3DTexture(*program, layer); + renderQuadForCalc(vao); } if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - "deltaS_rayleigh_texture.ppm", - glm::ivec2(_mu_s_samples * _nu_samples, _mu_samples) - ); - saveTextureFile( - GL_COLOR_ATTACHMENT1, + saveTextureFile("deltaS_rayleigh_texture.ppm", glm::ivec2(_textureSize)); + saveTextureFile( "deltaS_mie_texture.ppm", - glm::ivec2(_mu_s_samples * _nu_samples, _mu_samples) + glm::ivec2(_textureSize) ); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0); + GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, drawBuffers); - _inScatteringProgramObject->deactivate(); + program->deactivate(); + return { deltaSRayleigh, deltaSMie }; +} - // line 4 in algorithm 4.1 +void AtmosphereDeferredcaster::calculateIrradiance(GLuint quadCalcVao) { glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -1080,251 +676,292 @@ void AtmosphereDeferredcaster::executeCalculations(GLuint quadCalcVAO, glDrawBuffer(GL_COLOR_ATTACHMENT0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); - _deltaEProgramObject->activate(); - deltaETableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _deltaETableTexture); - _deltaEProgramObject->setUniform("deltaETexture", deltaETableTextureUnit); - loadAtmosphereDataIntoShaderProgram(*_deltaEProgramObject); + using ProgramObject = ghoul::opengl::ProgramObject; + std::unique_ptr program = ProgramObject::Build( + "DeltaE Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/deltaE_calc_fs.glsl") + ); + program->activate(); glClear(GL_COLOR_BUFFER_BIT); - renderQuadForCalc(quadCalcVAO, vertexSize); + renderQuadForCalc(quadCalcVao); if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - "irradiance_texture.ppm", - _deltaETableSize - ); + saveTextureFile("irradiance_texture.ppm", _deltaETableSize); } - _deltaEProgramObject->deactivate(); + program->deactivate(); +} - // line 5 in algorithm 4.1 +void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, GLuint deltaSRayleigh, + GLuint deltaSMie) +{ glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _inScatteringTableTexture, 0 ); - glViewport(0, 0, _mu_s_samples * _nu_samples, _mu_samples); - _deltaSProgramObject->activate(); - deltaSRayleighTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSRayleighTableTexture); - deltaSMieTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSMieTableTexture); - _deltaSProgramObject->setUniform("deltaSRTexture", deltaSRayleighTableTextureUnit); - _deltaSProgramObject->setUniform("deltaSMTexture", deltaSMieTableTextureUnit); - loadAtmosphereDataIntoShaderProgram(*_deltaSProgramObject); + glViewport(0, 0, _textureSize.x, _textureSize.y); + using ProgramObject = ghoul::opengl::ProgramObject; + std::unique_ptr program = ProgramObject::Build( + "deltaSCalcProgram", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/deltaS_calc_fs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") + ); + program->activate(); + + ghoul::opengl::TextureUnit deltaSRayleighUnit; + deltaSRayleighUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSRayleigh); + program->setUniform("deltaSRTexture", deltaSRayleighUnit); + + ghoul::opengl::TextureUnit deltaSMieUnit; + deltaSMieUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSMie); + program->setUniform("deltaSMTexture", deltaSMieUnit); + + program->setUniform("SAMPLES_MU_S", _muSSamples); + program->setUniform("SAMPLES_NU", _nuSamples); + program->setUniform("SAMPLES_MU", _muSamples); + program->setUniform("SAMPLES_R", _rSamples); glClear(GL_COLOR_BUFFER_BIT); - for (int layer = 0; layer < _r_samples; ++layer) { - step3DTexture(*_deltaSProgramObject, layer, false); - renderQuadForCalc(quadCalcVAO, vertexSize); + for (int layer = 0; layer < _rSamples; ++layer) { + program->setUniform("layer", layer); + renderQuadForCalc(vao); + } + if (_saveCalculationTextures) { + saveTextureFile("S_texture.ppm", glm::ivec2(_textureSize)); + } + program->deactivate(); +} + +void AtmosphereDeferredcaster::calculateDeltaJ(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, + GLuint deltaJ, GLuint deltaE, + GLuint deltaSRayleigh, GLuint deltaSMie) +{ + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaJ, 0); + glViewport(0, 0, _textureSize.x, _textureSize.y); + program.activate(); + + ghoul::opengl::TextureUnit transmittanceUnit; + transmittanceUnit.activate(); + glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); + program.setUniform("transmittanceTexture", transmittanceUnit); + + ghoul::opengl::TextureUnit deltaEUnit; + deltaEUnit.activate(); + glBindTexture(GL_TEXTURE_2D, deltaE); + program.setUniform("deltaETexture", deltaEUnit); + + ghoul::opengl::TextureUnit deltaSRayleighUnit; + deltaSRayleighUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSRayleigh); + program.setUniform("deltaSRTexture", deltaSRayleighUnit); + + ghoul::opengl::TextureUnit deltaSMieUnit; + deltaSMieUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSMie); + program.setUniform("deltaSMTexture", deltaSMieUnit); + + program.setUniform("firstIteration", (scatteringOrder == 2) ? 1 : 0); + program.setUniform("Rg", _atmospherePlanetRadius); + program.setUniform("Rt", _atmosphereRadius); + program.setUniform("AverageGroundReflectance", _averageGroundReflectance); + program.setUniform("HR", _rayleighHeightScale); + program.setUniform("betaRayleigh", _rayleighScatteringCoeff); + program.setUniform("HM", _mieHeightScale); + program.setUniform("betaMieScattering", _mieScatteringCoeff); + program.setUniform("mieG", _miePhaseConstant); + program.setUniform("SAMPLES_MU_S", _muSSamples); + program.setUniform("SAMPLES_NU", _nuSamples); + program.setUniform("SAMPLES_MU", _muSamples); + program.setUniform("SAMPLES_R", _rSamples); + for (int layer = 0; layer < _rSamples; ++layer) { + program.setUniform("layer", layer); + step3DTexture(program, layer); + renderQuadForCalc(vao); } if (_saveCalculationTextures) { saveTextureFile( - GL_COLOR_ATTACHMENT0, - "S_texture.ppm", - glm::ivec2(_mu_s_samples * _nu_samples, _mu_samples) + fmt::format("deltaJ_texture-scattering_order-{}.ppm", scatteringOrder), + glm::ivec2(_textureSize) ); } - _deltaSProgramObject->deactivate(); - - // loop in line 6 in algorithm 4.1 - for (int scatteringOrder = 2; scatteringOrder <= 4; ++scatteringOrder) { - // line 7 in algorithm 4.1 - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - _deltaJTableTexture, - 0 - ); - glViewport(0, 0, _mu_s_samples * _nu_samples, _mu_samples); - _deltaJProgramObject->activate(); - if (scatteringOrder == 2) { - _deltaJProgramObject->setUniform("firstIteraction", 1); - } - else { - _deltaJProgramObject->setUniform("firstIteraction", 0); - } - transmittanceTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - _deltaJProgramObject->setUniform( - "transmittanceTexture", - transmittanceTableTextureUnit - ); - deltaETableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _deltaETableTexture); - _deltaJProgramObject->setUniform("deltaETexture", deltaETableTextureUnit); - deltaSRayleighTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSRayleighTableTexture); - _deltaJProgramObject->setUniform( - "deltaSRTexture", - deltaSRayleighTableTextureUnit - ); - deltaSMieTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSMieTableTexture); - _deltaJProgramObject->setUniform("deltaSMTexture", deltaSMieTableTextureUnit); - loadAtmosphereDataIntoShaderProgram(*_deltaJProgramObject); - for (int layer = 0; layer < _r_samples; ++layer) { - step3DTexture(*_deltaJProgramObject, layer, true); - renderQuadForCalc(quadCalcVAO, vertexSize); - } - if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - fmt::format("deltaJ_texture-scattering_order-{}.ppm", scatteringOrder), - glm::ivec2(_mu_s_samples * _nu_samples, _mu_samples) - ); - } - _deltaJProgramObject->deactivate(); - - // line 8 in algorithm 4.1 - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - _deltaETableTexture, - 0 - ); - glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); - _irradianceSupTermsProgramObject->activate(); - if (scatteringOrder == 2) { - _irradianceSupTermsProgramObject->setUniform("firstIteraction", 1); - } - else { - _irradianceSupTermsProgramObject->setUniform("firstIteraction", 0); - } - transmittanceTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - _irradianceSupTermsProgramObject->setUniform( - "transmittanceTexture", - transmittanceTableTextureUnit - ); - deltaSRayleighTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSRayleighTableTexture); - _irradianceSupTermsProgramObject->setUniform( - "deltaSRTexture", - deltaSRayleighTableTextureUnit - ); - deltaSMieTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSMieTableTexture); - _irradianceSupTermsProgramObject->setUniform( - "deltaSMTexture", - deltaSMieTableTextureUnit - ); - loadAtmosphereDataIntoShaderProgram(*_irradianceSupTermsProgramObject); - renderQuadForCalc(quadCalcVAO, vertexSize); - if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - fmt::format("deltaE_texture-scattering_order-{}.ppm", scatteringOrder), - _deltaETableSize - ); - } - _irradianceSupTermsProgramObject->deactivate(); - - // line 9 in algorithm 4.1 - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - _deltaSRayleighTableTexture, - 0 - ); - glViewport(0, 0, _mu_s_samples * _nu_samples, _mu_samples); - _inScatteringSupTermsProgramObject->activate(); - transmittanceTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); - _inScatteringSupTermsProgramObject->setUniform( - "transmittanceTexture", - transmittanceTableTextureUnit - ); - deltaJTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaJTableTexture); - _inScatteringSupTermsProgramObject->setUniform( - "deltaJTexture", - deltaJTableTextureUnit - ); - loadAtmosphereDataIntoShaderProgram(*_inScatteringSupTermsProgramObject); - for (int layer = 0; layer < _r_samples; ++layer) { - step3DTexture(*_inScatteringSupTermsProgramObject, layer, true); - renderQuadForCalc(quadCalcVAO, vertexSize); - } - if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - fmt::format("deltaS_texture-scattering_order-{}.ppm", scatteringOrder), - glm::ivec2(_mu_s_samples * _nu_samples, _mu_samples) - ); - } - _inScatteringSupTermsProgramObject->deactivate(); - - glEnable(GL_BLEND); - glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); - glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE); - - // line 10 in algorithm 4.1 - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - _irradianceTableTexture, - 0 - ); - glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); - _irradianceFinalProgramObject->activate(); - deltaETableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D, _deltaETableTexture); - _irradianceFinalProgramObject->setUniform( - "deltaETexture", - deltaETableTextureUnit - ); - loadAtmosphereDataIntoShaderProgram(*_irradianceFinalProgramObject); - renderQuadForCalc(quadCalcVAO, vertexSize); - if (_saveCalculationTextures) { - saveTextureFile( - GL_COLOR_ATTACHMENT0, - fmt::format("irradianceTable_order-{}.ppm", scatteringOrder), - _deltaETableSize - ); - } - _irradianceFinalProgramObject->deactivate(); - - // line 11 in algorithm 4.1 - glFramebufferTexture( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - _inScatteringTableTexture, - 0 - ); - glViewport(0, 0, _mu_s_samples * _nu_samples, _mu_samples); - _deltaSSupTermsProgramObject->activate(); - deltaSRayleighTableTextureUnit.activate(); - glBindTexture(GL_TEXTURE_3D, _deltaSRayleighTableTexture); - _deltaSSupTermsProgramObject->setUniform( - "deltaSTexture", - deltaSRayleighTableTextureUnit - ); - loadAtmosphereDataIntoShaderProgram(*_deltaSSupTermsProgramObject); - for (int layer = 0; layer < _r_samples; ++layer) { - step3DTexture(*_deltaSSupTermsProgramObject, layer, false); - renderQuadForCalc(quadCalcVAO, vertexSize); - } - if (_saveCalculationTextures) { - saveTextureFile(GL_COLOR_ATTACHMENT0, - fmt::format("inscatteringTable_order-{}.ppm", scatteringOrder), - glm::ivec2(_mu_s_samples * _nu_samples, _mu_samples) - ); - } - _deltaSSupTermsProgramObject->deactivate(); - - glDisable(GL_BLEND); - } - - // Restores OpenGL blending state - global::renderEngine->openglStateCache().resetBlendState(); + program.deactivate(); } -void AtmosphereDeferredcaster::preCalculateAtmosphereParam() { - // Load Shader Programs for Calculations - loadComputationPrograms(); +void AtmosphereDeferredcaster::calculateDeltaE(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, + GLuint deltaE, GLuint deltaSRayleigh, + GLuint deltaSMie) +{ + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); + glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); + program.activate(); + + ghoul::opengl::TextureUnit deltaSRayleighUnit; + deltaSRayleighUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSRayleigh); + program.setUniform("deltaSRTexture", deltaSRayleighUnit); + + ghoul::opengl::TextureUnit deltaSMieUnit; + deltaSMieUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSMie); + program.setUniform("deltaSMTexture", deltaSMieUnit); + + program.setUniform("firstIteration", (scatteringOrder == 2) ? 1 : 0); + program.setUniform("Rg", _atmospherePlanetRadius); + program.setUniform("Rt", _atmosphereRadius); + program.setUniform("mieG", _miePhaseConstant); + program.setUniform("SKY", _irradianceTableSize); + program.setUniform("SAMPLES_MU_S", _muSSamples); + program.setUniform("SAMPLES_NU", _nuSamples); + program.setUniform("SAMPLES_MU", _muSamples); + program.setUniform("SAMPLES_R", _rSamples); + renderQuadForCalc(vao); + if (_saveCalculationTextures) { + saveTextureFile( + fmt::format("deltaE_texture-scattering_order-{}.ppm", scatteringOrder), + _deltaETableSize + ); + } + program.deactivate(); +} + +void AtmosphereDeferredcaster::calculateDeltaS(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, + GLuint deltaSRayleigh, GLuint deltaJ) +{ + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); + glViewport(0, 0, _textureSize.x, _textureSize.y); + program.activate(); + + ghoul::opengl::TextureUnit transmittanceUnit; + transmittanceUnit.activate(); + glBindTexture(GL_TEXTURE_2D, _transmittanceTableTexture); + program.setUniform("transmittanceTexture", transmittanceUnit); + + ghoul::opengl::TextureUnit deltaJUnit; + deltaJUnit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaJ); + program.setUniform("deltaJTexture", deltaJUnit); + + program.setUniform("Rg", _atmospherePlanetRadius); + program.setUniform("Rt", _atmosphereRadius); + program.setUniform("SAMPLES_MU_S", _muSSamples); + program.setUniform("SAMPLES_NU", _nuSamples); + program.setUniform("SAMPLES_MU", _muSamples); + program.setUniform("SAMPLES_R", _rSamples); + for (int layer = 0; layer < _rSamples; ++layer) { + program.setUniform("layer", layer); + step3DTexture(program, layer); + renderQuadForCalc(vao); + } + if (_saveCalculationTextures) { + saveTextureFile( + fmt::format("deltaS_texture-scattering_order-{}.ppm", scatteringOrder), + glm::ivec2(_textureSize) + ); + } + program.deactivate(); +} + +void AtmosphereDeferredcaster::calculateIrradiance(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, + GLuint deltaE) +{ + glFramebufferTexture( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + _irradianceTableTexture, + 0 + ); + glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); + program.activate(); + + ghoul::opengl::TextureUnit unit; + unit.activate(); + glBindTexture(GL_TEXTURE_2D, deltaE); + program.setUniform("deltaETexture", unit); + program.setUniform("OTHER_TEXTURES", _deltaETableSize); + + renderQuadForCalc(vao); + if (_saveCalculationTextures) { + saveTextureFile( + fmt::format("irradianceTable_order-{}.ppm", scatteringOrder), + _deltaETableSize + ); + } + program.deactivate(); +} + +void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& prg, + GLuint deltaSRayleigh) + +{ + glFramebufferTexture( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + _inScatteringTableTexture, + 0 + ); + glViewport(0, 0, _textureSize.x, _textureSize.y); + prg.activate(); + + ghoul::opengl::TextureUnit unit; + unit.activate(); + glBindTexture(GL_TEXTURE_3D, deltaSRayleigh); + prg.setUniform("deltaSTexture", unit); + prg.setUniform("SAMPLES_MU_S", _muSSamples); + prg.setUniform("SAMPLES_NU", _nuSamples); + prg.setUniform("SAMPLES_MU", _muSamples); + prg.setUniform("SAMPLES_R", _rSamples); + for (int layer = 0; layer < _rSamples; ++layer) { + prg.setUniform("layer", layer); + renderQuadForCalc(vao); + } + if (_saveCalculationTextures) { + saveTextureFile( + fmt::format("inscatteringTable_order-{}.ppm", scatteringOrder), + glm::ivec2(_textureSize) + ); + } + prg.deactivate(); +} + +void AtmosphereDeferredcaster::calculateAtmosphereParameters() { + using ProgramObject = ghoul::opengl::ProgramObject; + std::unique_ptr deltaJProgram = ProgramObject::Build( + "DeltaJ Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/deltaJ_calc_fs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") + ); + std::unique_ptr irradianceSupTermsProgram = ProgramObject::Build( + "IrradianceSupTerms Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/irradiance_sup_calc_fs.glsl") + ); + std::unique_ptr inScatteringSupTermsProgram = ProgramObject::Build( + "InScatteringSupTerms Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/inScattering_sup_calc_fs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") + ); + std::unique_ptr irradianceFinalProgram = ProgramObject::Build( + "IrradianceEFinal Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/irradiance_final_fs.glsl") + ); + std::unique_ptr deltaSSupTermsProgram = ProgramObject::Build( + "DeltaSSUPTerms Program", + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_vs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/deltaS_sup_calc_fs.glsl"), + absPath("${MODULE_ATMOSPHERE}/shaders/calculation_gs.glsl") + ); - // Create Textures for Calculations - createComputationTextures(); // Saves current FBO first GLint defaultFBO; @@ -1341,86 +978,127 @@ void AtmosphereDeferredcaster::preCalculateAtmosphereParam() { glDrawBuffers(1, drawBuffers); // Prepare for rendering/calculations - GLuint quadCalcVAO; - GLuint quadCalcVBO; - createRenderQuad(&quadCalcVAO, &quadCalcVBO, 1.0f); - - // Starting Calculations... - LDEBUG("Starting precalculations for scattering effects"); + GLuint quadVao; + GLuint quadVbo; + createRenderQuad(&quadVao, &quadVbo); // Execute Calculations - executeCalculations(quadCalcVAO, drawBuffers, 6); + LDEBUG("Starting precalculations for scattering effects"); + glDisable(GL_BLEND); - deleteUnusedComputationTextures(); + // See Precomputed Atmosphere Scattering from Bruneton et al. paper, algorithm 4.1: + calculateTransmittance(quadVao); + + // line 2 in algorithm 4.1 + GLuint deltaETable = calculateDeltaE(quadVao); + + // line 3 in algorithm 4.1 + auto [deltaSRayleighTable, deltaSMieTable] = calculateDeltaS(quadVao); + + // line 4 in algorithm 4.1 + calculateIrradiance(quadVao); + + // line 5 in algorithm 4.1 + calculateInscattering(quadVao, deltaSRayleighTable, deltaSMieTable); + + GLuint deltaJTable = createTexture(_textureSize, "DeltaJ", 3); + + // loop in line 6 in algorithm 4.1 + for (int scatteringOrder = 2; scatteringOrder <= 4; ++scatteringOrder) { + // line 7 in algorithm 4.1 + calculateDeltaJ( + quadVao, + scatteringOrder, + *deltaJProgram, + deltaJTable, + deltaETable, + deltaSRayleighTable, + deltaSMieTable + ); + + // line 8 in algorithm 4.1 + calculateDeltaE( + quadVao, + scatteringOrder, + *irradianceSupTermsProgram, + deltaETable, + deltaSRayleighTable, + deltaSMieTable + ); + + // line 9 in algorithm 4.1 + calculateDeltaS( + quadVao, + scatteringOrder, + *inScatteringSupTermsProgram, + deltaSRayleighTable, + deltaJTable + ); + + glEnable(GL_BLEND); + glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); + glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE); + + // line 10 in algorithm 4.1 + calculateIrradiance( + quadVao, + scatteringOrder, + *irradianceFinalProgram, + deltaETable + ); + + // line 11 in algorithm 4.1 + calculateInscattering( + quadVao, + scatteringOrder, + *deltaSSupTermsProgram, + deltaSRayleighTable + ); + + glDisable(GL_BLEND); + } + + // Restores OpenGL blending state + global::renderEngine->openglStateCache().resetBlendState(); + + glDeleteTextures(1, &deltaETable); + glDeleteTextures(1, &deltaSRayleighTable); + glDeleteTextures(1, &deltaSMieTable); + glDeleteTextures(1, &deltaJTable); // Restores system state glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); global::renderEngine->openglStateCache().setViewportState(viewport); - glDeleteBuffers(1, &quadCalcVBO); - glDeleteVertexArrays(1, &quadCalcVAO); + glDeleteBuffers(1, &quadVao); + glDeleteVertexArrays(1, &quadVbo); glDeleteFramebuffers(1, &calcFBO); LDEBUG("Ended precalculations for Atmosphere effects"); } -void AtmosphereDeferredcaster::loadAtmosphereDataIntoShaderProgram( - ghoul::opengl::ProgramObject& shaderProg) -{ - shaderProg.setUniform("Rg", _atmospherePlanetRadius); - shaderProg.setUniform("Rt", _atmosphereRadius); - shaderProg.setUniform("AverageGroundReflectance", _planetAverageGroundReflectance); - shaderProg.setUniform("groundRadianceEmission", _planetGroundRadianceEmission); - shaderProg.setUniform("HR", _rayleighHeightScale); - shaderProg.setUniform("betaRayleigh", _rayleighScatteringCoeff); - shaderProg.setUniform("HM", _mieHeightScale); - shaderProg.setUniform("betaMieScattering", _mieScatteringCoeff); - shaderProg.setUniform("betaMieExtinction", _mieExtinctionCoeff); - shaderProg.setUniform("mieG", _miePhaseConstant); - shaderProg.setUniform("sunRadiance", _sunRadianceIntensity); - shaderProg.setUniform("TRANSMITTANCE", _transmittanceTableSize); - shaderProg.setUniform("SKY", _irradianceTableSize); - shaderProg.setUniform("OTHER_TEXTURES", _deltaETableSize); - shaderProg.setUniform("SAMPLES_R", _r_samples); - shaderProg.setUniform("SAMPLES_MU", _mu_samples); - shaderProg.setUniform("SAMPLES_MU_S", _mu_s_samples); - shaderProg.setUniform("SAMPLES_NU", _nu_samples); - shaderProg.setUniform("ozoneLayerEnabled", _ozoneEnabled); - shaderProg.setUniform("HO", _ozoneHeightScale); - shaderProg.setUniform("betaOzoneExtinction", _ozoneExtinctionCoeff); -} - -void AtmosphereDeferredcaster::step3DTexture(ghoul::opengl::ProgramObject& shaderProg, - int layer, bool doCalculation) +void AtmosphereDeferredcaster::step3DTexture(ghoul::opengl::ProgramObject& prg, int layer) { // See OpenGL redbook 8th Edition page 556 for Layered Rendering - if (doCalculation) { - const float earth2 = _atmospherePlanetRadius * _atmospherePlanetRadius; - const float diff = _atmosphereRadius * _atmosphereRadius - earth2; - const float ri = static_cast(layer) / static_cast(_r_samples - 1); - const float eps = [&]() { - if (layer == 0) { - return 0.01f; - } - else { - if (layer == (_r_samples - 1)) { - return -0.001f; - } - else { - return 0.f; - } - } - }(); - const float r = std::sqrt(earth2 + ri * ri * diff) + eps; - const float dminG = r - _atmospherePlanetRadius; - const float dminT = _atmosphereRadius - r; - const float dh = std::sqrt(r * r - earth2); - const float dH = dh + std::sqrt(diff); - - shaderProg.setUniform("r", r); - shaderProg.setUniform("dhdH", dminT, dH, dminG, dh); + const float planet2 = _atmospherePlanetRadius * _atmospherePlanetRadius; + const float diff = _atmosphereRadius * _atmosphereRadius - planet2; + const float ri = static_cast(layer) / static_cast(_rSamples - 1); + float eps = 0.01f; + if (layer > 0) { + if (layer == (_rSamples - 1)) { + eps = -0.001f; + } + else { + eps = 0.f; + } } + const float r = std::sqrt(planet2 + ri * ri * diff) + eps; + const float dminG = r - _atmospherePlanetRadius; + const float dminT = _atmosphereRadius - r; + const float dh = std::sqrt(r * r - planet2); + const float dH = dh + std::sqrt(diff); - shaderProg.setUniform("layer", layer); + prg.setUniform("r", r); + prg.setUniform("dhdH", dminT, dH, dminG, dh); } } // namespace openspace diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.h b/modules/atmosphere/rendering/atmospheredeferredcaster.h index 589d2479c7..a117882f8e 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.h +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.h @@ -57,16 +57,17 @@ struct ShadowRenderingStruct { class AtmosphereDeferredcaster : public Deferredcaster { public: + AtmosphereDeferredcaster(float textureScale, + std::vector shadowConfigArray, bool saveCalculatedTextures); virtual ~AtmosphereDeferredcaster() = default; void initialize(); void deinitialize(); - void preRaycast(const RenderData& renderData, const DeferredcastData& deferredData, + void preRaycast(const RenderData& data, const DeferredcastData& deferredData, ghoul::opengl::ProgramObject& program) override; - void postRaycast(const RenderData& renderData, const DeferredcastData& deferredData, + void postRaycast(const RenderData& data, const DeferredcastData& deferredData, ghoul::opengl::ProgramObject& program) override; - std::filesystem::path deferredcastPath() const override; std::filesystem::path deferredcastVSPath() const override; std::filesystem::path deferredcastFSPath() const override; std::filesystem::path helperPath() const override; @@ -75,82 +76,64 @@ public: void update(const UpdateData&) override; - void preCalculateAtmosphereParam(); + void calculateAtmosphereParameters(); void setModelTransform(glm::dmat4 transform); - void setTime(double time); - void setAtmosphereRadius(float atmRadius); - void setPlanetRadius(float planetRadius); - void setPlanetAverageGroundReflectance(float averageGReflectance); - void setPlanetGroundRadianceEmission(float groundRadianceEmission); - void setRayleighHeightScale(float rayleighHeightScale); - void enableOzone(bool enable); - void setOzoneHeightScale(float ozoneHeightScale); - void setMieHeightScale(float mieHeightScale); - void setMiePhaseConstant(float miePhaseConstant); - void setSunRadianceIntensity(float sunRadiance); - void setRayleighScatteringCoefficients(glm::vec3 rayScattCoeff); - void setOzoneExtinctionCoefficients(glm::vec3 ozoneExtCoeff); - void setMieScatteringCoefficients(glm::vec3 mieScattCoeff); - void setMieExtinctionCoefficients(glm::vec3 mieExtCoeff); - void setEllipsoidRadii(glm::dvec3 radii); - void setShadowConfigArray(std::vector shadowConfigArray); - void setHardShadows(bool enabled); - void enableSunFollowing(bool enable); - void setPrecalculationTextureScale(float preCalculatedTexturesScale); - void enablePrecalculationTexturesSaving(); + void setParameters(float atmosphereRadius, float planetRadius, + float averageGroundReflectance, float groundRadianceEmission, + float rayleighHeightScale, bool enableOzone, float ozoneHeightScale, + float mieHeightScale, float miePhaseConstant, float sunRadiance, + glm::vec3 rayScatteringCoefficients, glm::vec3 ozoneExtinctionCoefficients, + glm::vec3 mieScatteringCoefficients, glm::vec3 mieExtinctionCoefficients, + bool sunFollowing); + + void setHardShadows(bool enabled); private: - void loadComputationPrograms(); - void unloadComputationPrograms(); - void createComputationTextures(); - void deleteComputationTextures(); - void deleteUnusedComputationTextures(); - void executeCalculations(GLuint quadCalcVAO, GLenum drawBuffers[1], - GLsizei vertexSize); - void step3DTexture(ghoul::opengl::ProgramObject& shaderProg, int layer, - bool doCalculation); - void loadAtmosphereDataIntoShaderProgram(ghoul::opengl::ProgramObject& shaderProg); + void step3DTexture(ghoul::opengl::ProgramObject& prg, int layer); + + void calculateTransmittance(GLuint vao); + GLuint calculateDeltaE(GLuint vao); + std::pair calculateDeltaS(GLuint vao); + void calculateIrradiance(GLuint vao); + void calculateInscattering(GLuint vao, GLuint deltaSRayleigh, GLuint deltaSMie); + void calculateDeltaJ(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, GLuint deltaJ, GLuint deltaE, + GLuint deltaSRayleigh, GLuint deltaSMie); + void calculateDeltaE(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, GLuint deltaE, GLuint deltaSRayleigh, + GLuint deltaSMie); + void calculateDeltaS(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh, GLuint deltaJ); + void calculateIrradiance(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, GLuint deltaE); + void calculateInscattering(GLuint vao, int scatteringOrder, + ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh); - std::unique_ptr _transmittanceProgramObject; - std::unique_ptr _irradianceProgramObject; - std::unique_ptr _irradianceSupTermsProgramObject; - std::unique_ptr _irradianceFinalProgramObject; - std::unique_ptr _inScatteringProgramObject; - std::unique_ptr _inScatteringSupTermsProgramObject; - std::unique_ptr _deltaEProgramObject; - std::unique_ptr _deltaSProgramObject; - std::unique_ptr _deltaSSupTermsProgramObject; - std::unique_ptr _deltaJProgramObject; UniformCache(cullAtmosphere, Rg, Rt, groundRadianceEmission, HR, betaRayleigh, HM, betaMieExtinction, mieG, sunRadiance, ozoneLayerEnabled, HO, betaOzoneExtinction, SAMPLES_R, SAMPLES_MU, SAMPLES_MU_S, SAMPLES_NU, inverseModelTransformMatrix, - modelTransformMatrix, projectionToModelTransformMatrix, - viewToWorldMatrix, camPosObj, sunDirectionObj, hardShadows, - transmittanceTexture, irradianceTexture, inscatterTexture) _uniformCache; - - GLuint _transmittanceTableTexture = 0; - GLuint _irradianceTableTexture = 0; - GLuint _inScatteringTableTexture = 0; - GLuint _deltaETableTexture = 0; - GLuint _deltaSRayleighTableTexture = 0; - GLuint _deltaSMieTableTexture = 0; - GLuint _deltaJTableTexture = 0; + modelTransformMatrix, projectionToModelTransform, viewToWorldMatrix, + camPosObj, sunDirectionObj, hardShadows, transmittanceTexture, irradianceTexture, + inscatterTexture) _uniformCache; ghoul::opengl::TextureUnit _transmittanceTableTextureUnit; ghoul::opengl::TextureUnit _irradianceTableTextureUnit; ghoul::opengl::TextureUnit _inScatteringTableTextureUnit; + GLuint _transmittanceTableTexture = 0; + GLuint _irradianceTableTexture = 0; + GLuint _inScatteringTableTexture = 0; + // Atmosphere Data - bool _atmosphereCalculated = false; bool _ozoneEnabled = false; bool _sunFollowingCameraEnabled = false; float _atmosphereRadius = 0.f; float _atmospherePlanetRadius = 0.f; - float _planetAverageGroundReflectance = 0.f; - float _planetGroundRadianceEmission = 0.f; + float _averageGroundReflectance = 0.f; + float _groundRadianceEmission = 0.f; float _rayleighHeightScale = 0.f; float _ozoneHeightScale = 0.f; float _mieHeightScale = 0.f; @@ -161,34 +144,33 @@ private: glm::vec3 _ozoneExtinctionCoeff = glm::vec3(0.f); glm::vec3 _mieScatteringCoeff = glm::vec3(0.f); glm::vec3 _mieExtinctionCoeff = glm::vec3(0.f); - glm::dvec3 _ellipsoidRadii = glm::dvec3(0.0); // Atmosphere Textures Dimmensions - glm::ivec2 _transmittanceTableSize = glm::ivec2(256, 64); - glm::ivec2 _irradianceTableSize = glm::ivec2(64, 16); - glm::ivec2 _deltaETableSize = glm::ivec2(64, 16); - int _r_samples = 32; - int _mu_samples = 128; - int _mu_s_samples = 32; - int _nu_samples = 8; + const glm::ivec2 _transmittanceTableSize; + const glm::ivec2 _irradianceTableSize; + const glm::ivec2 _deltaETableSize; + const int _muSSamples; + const int _nuSamples; + const int _muSamples; + const int _rSamples; + const glm::ivec3 _textureSize; glm::dmat4 _modelTransform; - double _time = 0.0; // Eclipse Shadows std::vector _shadowConfArray; + std::vector _shadowDataArrayCache; bool _hardShadowsEnabled = false; // Atmosphere Debugging - bool _saveCalculationTextures = false; + const bool _saveCalculationTextures = false; - std::vector _shadowDataArrayCache; // Assuming < 1000 shadow casters, the longest uniform name that we are getting is // shadowDataArray[999].casterPositionVec // which needs to fit into the uniform buffer char _uniformNameBuffer[40]; }; -} // openspace +} // namespace openspace #endif // __OPENSPACE_MODULE_ATMOSPHERE___ATMOSPHEREDEFERREDCASTER___H__ diff --git a/modules/atmosphere/rendering/renderableatmosphere.cpp b/modules/atmosphere/rendering/renderableatmosphere.cpp index e14ff893a7..6f0fa990ac 100644 --- a/modules/atmosphere/rendering/renderableatmosphere.cpp +++ b/modules/atmosphere/rendering/renderableatmosphere.cpp @@ -244,7 +244,7 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) MieScatteringCoeffInfo, glm::vec3(0.004f), glm::vec3(0.00001f), glm::vec3(1.f) ) - , _mieScatteringExtinctionPropCoefficient( + , _mieScatteringExtinctionPropCoeff( MieScatteringExtinctionPropCoeffInfo, 0.9f, 0.01f, 1.f ) @@ -328,16 +328,15 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) _miePhaseConstant.onChange(updateWithCalculation); addProperty(_miePhaseConstant); - _mieScatteringExtinctionPropCoefficient = + _mieScatteringExtinctionPropCoeff = _mieScattExtPropCoefProp != 1.f ? _mieScattExtPropCoefProp : _mieScatteringCoeff.value().x / _mieExtinctionCoeff.x; - _mieScatteringExtinctionPropCoefficient.onChange(updateWithCalculation); - addProperty(_mieScatteringExtinctionPropCoefficient); + _mieScatteringExtinctionPropCoeff.onChange(updateWithCalculation); + addProperty(_mieScatteringExtinctionPropCoeff); if (p.debug.has_value()) { - _preCalculatedTexturesScale = - p.debug->preCalculatedTextureScale.value_or(_preCalculatedTexturesScale); + _textureScale = p.debug->preCalculatedTextureScale.value_or(_textureScale); _saveCalculationsToTexture = p.debug->saveCalculatedTextures.value_or(_saveCalculationsToTexture); @@ -364,15 +363,13 @@ void RenderableAtmosphere::deinitializeGL() { } void RenderableAtmosphere::initializeGL() { - _deferredcaster = std::make_unique(); + _deferredcaster = std::make_unique( + _textureScale, + _shadowEnabled ? std::move(_shadowConfArray) : std::vector(), + _saveCalculationsToTexture + ); + _shadowConfArray.clear(); updateAtmosphereParameters(); - - if (_shadowEnabled) { - _deferredcaster->setShadowConfigArray(_shadowConfArray); - // We no longer need it - _shadowConfArray.clear(); - } - _deferredcaster->initialize(); global::deferredcasterManager->attachDeferredcaster(*_deferredcaster); @@ -382,13 +379,11 @@ bool RenderableAtmosphere::isReady() const { return true; } -glm::dmat4 RenderableAtmosphere::computeModelTransformMatrix( - const TransformData& transformData) -{ +glm::dmat4 RenderableAtmosphere::computeModelTransformMatrix(const TransformData& data) { // scale the planet to appropriate size since the planet is a unit sphere - return glm::translate(glm::dmat4(1.0), transformData.translation) * - glm::dmat4(transformData.rotation) * - glm::scale(glm::dmat4(1.0), glm::dvec3(transformData.scale)); + return glm::translate(glm::dmat4(1.0), data.translation) * + glm::dmat4(data.rotation) * + glm::scale(glm::dmat4(1.0), glm::dvec3(data.scale)); } void RenderableAtmosphere::render(const RenderData& data, RendererTasks& renderTask) { @@ -404,11 +399,10 @@ void RenderableAtmosphere::update(const UpdateData& data) { _deferredCasterNeedsUpdate = false; } if (_deferredCasterNeedsCalculation) { - _deferredcaster->preCalculateAtmosphereParam(); + _deferredcaster->calculateAtmosphereParameters(); _deferredCasterNeedsCalculation = false; } - _deferredcaster->setTime(data.time.j2000Seconds()); glm::dmat4 modelTransform = computeModelTransformMatrix(data.modelTransform); _deferredcaster->setModelTransform(modelTransform); _deferredcaster->update(data); @@ -416,34 +410,26 @@ void RenderableAtmosphere::update(const UpdateData& data) { void RenderableAtmosphere::updateAtmosphereParameters() { _mieExtinctionCoeff = - _mieScatteringCoeff.value() / _mieScatteringExtinctionPropCoefficient.value(); + _mieScatteringCoeff.value() / _mieScatteringExtinctionPropCoeff.value(); - _deferredcaster->setAtmosphereRadius(_planetRadius + _atmosphereHeight); - _deferredcaster->setPlanetRadius(_planetRadius); - _deferredcaster->setPlanetAverageGroundReflectance(_groundAverageReflectance); - _deferredcaster->setPlanetGroundRadianceEmission(_groundRadianceEmission); - _deferredcaster->setRayleighHeightScale(_rayleighHeightScale); - _deferredcaster->enableOzone(_ozoneEnabled); - _deferredcaster->setOzoneHeightScale(_ozoneHeightScale); - _deferredcaster->setMieHeightScale(_mieHeightScale); - _deferredcaster->setMiePhaseConstant(_miePhaseConstant); - _deferredcaster->setSunRadianceIntensity(_sunIntensity); - _deferredcaster->setRayleighScatteringCoefficients(_rayleighScatteringCoeff); - _deferredcaster->setOzoneExtinctionCoefficients(_ozoneCoeff); - _deferredcaster->setMieScatteringCoefficients(_mieScatteringCoeff); - _deferredcaster->setMieExtinctionCoefficients(_mieExtinctionCoeff); - _deferredcaster->enableSunFollowing(_sunFollowingCameraEnabled); - // TODO: Fix the ellipsoid nature of the renderable globe (JCC) - //_deferredcaster->setEllipsoidRadii(_ellipsoid.radii()); - - _deferredcaster->setPrecalculationTextureScale(_preCalculatedTexturesScale); - if (_saveCalculationsToTexture) { - _deferredcaster->enablePrecalculationTexturesSaving(); - } - - if (_shadowEnabled) { - _deferredcaster->setHardShadows(_hardShadowsEnabled); - } + _deferredcaster->setParameters( + _planetRadius + _atmosphereHeight, + _planetRadius, + _groundAverageReflectance, + _groundRadianceEmission, + _rayleighHeightScale, + _ozoneEnabled, + _ozoneHeightScale, + _mieHeightScale, + _miePhaseConstant, + _sunIntensity, + _rayleighScatteringCoeff, + _ozoneCoeff, + _mieScatteringCoeff, + _mieExtinctionCoeff, + _sunFollowingCameraEnabled + ); + _deferredcaster->setHardShadows(_hardShadowsEnabled); } } // namespace openspace diff --git a/modules/atmosphere/rendering/renderableatmosphere.h b/modules/atmosphere/rendering/renderableatmosphere.h index 63ec3afeab..c0f871ff2c 100644 --- a/modules/atmosphere/rendering/renderableatmosphere.h +++ b/modules/atmosphere/rendering/renderableatmosphere.h @@ -72,7 +72,7 @@ public: static documentation::Documentation Documentation(); private: - glm::dmat4 computeModelTransformMatrix(const openspace::TransformData& transformData); + glm::dmat4 computeModelTransformMatrix(const openspace::TransformData& data); void updateAtmosphereParameters(); properties::FloatProperty _atmosphereHeight; @@ -85,7 +85,7 @@ private: properties::Vec3Property _ozoneCoeff; properties::FloatProperty _mieHeightScale; properties::Vec3Property _mieScatteringCoeff; - properties::FloatProperty _mieScatteringExtinctionPropCoefficient; + properties::FloatProperty _mieScatteringExtinctionPropCoeff; properties::FloatProperty _miePhaseConstant; properties::FloatProperty _sunIntensity; properties::BoolProperty _sunFollowingCameraEnabled; @@ -98,7 +98,7 @@ private: // Atmosphere Debug bool _saveCalculationsToTexture = false; - float _preCalculatedTexturesScale = 1.f; + float _textureScale = 1.f; std::unique_ptr _deferredcaster; diff --git a/modules/atmosphere/shaders/atmosphere_common.glsl b/modules/atmosphere/shaders/atmosphere_common.glsl index 6a0884f861..c935dc0c50 100644 --- a/modules/atmosphere/shaders/atmosphere_common.glsl +++ b/modules/atmosphere/shaders/atmosphere_common.glsl @@ -54,85 +54,11 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Atmosphere Rendering Parameters -uniform float Rg; -uniform float Rt; -uniform float AverageGroundReflectance; -uniform float groundRadianceEmission; -uniform float HR; -uniform vec3 betaRayleigh; -uniform float HO; -uniform vec3 betaOzoneExtinction; -uniform float HM; -uniform vec3 betaMieScattering; -uniform vec3 betaMieExtinction; -uniform float mieG; -uniform float sunRadiance; - -uniform bool ozoneLayerEnabled; - -uniform ivec2 TRANSMITTANCE; -uniform ivec2 SKY; -uniform ivec2 OTHER_TEXTURES; -uniform int SAMPLES_R; -uniform int SAMPLES_MU; -uniform int SAMPLES_MU_S; -uniform int SAMPLES_NU; +const int INSCATTER_INTEGRAL_SAMPLES = 50; +const float M_PI = 3.141592657; const float ATM_EPSILON = 1.0; -// Integration steps -const int TRANSMITTANCE_STEPS = 500; -const int INSCATTER_INTEGRAL_SAMPLES = 50; -const int IRRADIANCE_INTEGRAL_SAMPLES = 32; -const int INSCATTER_SPHERICAL_INTEGRAL_SAMPLES = 16; - -const float M_PI = 3.141592657; -const float M_2PI = 2.0 * M_PI; - -uniform sampler2D transmittanceTexture; - -float Rg2 = Rg * Rg; -float Rt2 = Rt * Rt; -float H = sqrt(Rt2 - Rg2); -float H2 = Rt2 - Rg2; -float invSamplesMu = 1.0 / float(SAMPLES_MU); -float invSamplesR = 1.0 / float(SAMPLES_R); -float invSamplesMuS = 1.0 / float(SAMPLES_MU_S); -float invSamplesNu = 1.0 / float(SAMPLES_NU); -float RtMinusRg = float(Rt - Rg); -float invRtMinusRg = 1.0 / RtMinusRg; - -float opticalDepth(float localH, float r, float mu, float d) { - float invH = 1.0 / localH; - float a = sqrt(0.5 * invH * r); - vec2 a01 = a * vec2(mu, mu + d / r); - vec2 a01s = sign(a01); - vec2 a01sq = a01 * a01; - float x = a01s.y > a01s.x ? exp(a01sq.x) : 0.0; - vec2 y = a01s / (2.3193 * abs(a01) + sqrt(1.52 * a01sq + 4.0)) * vec2(1.0, exp(-d * invH * (d / (2.0 * r) + mu))); - return sqrt(M_2PI * H * r) * exp((Rg-r)*invH) * (x + dot(y, vec2(1.0, -1.0))); -} - -vec3 analyticTransmittance(float r, float mu, float d) { - vec3 ozone = vec3(0.0); - if (ozoneLayerEnabled) { - ozone = betaOzoneExtinction * (0.0000006) * opticalDepth(HO, r, mu, d); - } - return exp(-betaRayleigh * opticalDepth(HR, r, mu, d) - ozone - - betaMieExtinction * opticalDepth(HM, r, mu, d)); -} - -vec3 irradiance(sampler2D sampler, float r, float muSun) { - float u_r = (r - Rg) * invRtMinusRg; - float u_muSun = (muSun + 0.2) / 1.2; - return texture(sampler, vec2(u_muSun, u_r)).rgb; -} - - -//================================================// -//=============== General Functions ==============// -//================================================// // In the following shaders r (altitude) is the length of vector/position x in the // atmosphere (or on the top of it when considering an observer in space), where the light // is coming from the opposite direction of the view direction, here the vector v or @@ -142,7 +68,7 @@ vec3 irradiance(sampler2D sampler, float r, float muSun) { // or top of atmosphere // r := || vec(x) || e [0, Rt] // mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r -float rayDistance(float r, float mu) { +float rayDistance(float r, float mu, float Rt, float Rg) { // The light ray starting at the observer in/on the atmosphere can have to possible end // points: the top of the atmosphere or the planet ground. So the shortest path is the // one we are looking for, otherwise we may be passing through the ground @@ -151,9 +77,8 @@ float rayDistance(float r, float mu) { float atmRadiusEps2 = (Rt + ATM_EPSILON) * (Rt + ATM_EPSILON); float mu2 = mu * mu; float r2 = r * r; - float rg2 = Rg * Rg; float rayDistanceAtmosphere = -r * mu + sqrt(r2 * (mu2 - 1.0) + atmRadiusEps2); - float delta = r2 * (mu2 - 1.0) + rg2; + float delta = r2 * (mu2 - 1.0) + Rg*Rg; // Ray may be hitting ground if (delta >= 0.0) { @@ -173,19 +98,23 @@ float rayDistance(float r, float mu) { // nu := cosone of the angle between vec(s) and vec(v) // dhdH := it is a vec4. dhdH.x stores the dminT := Rt - r, dhdH.y stores the dH value // (see paper), dhdH.z stores dminG := r - Rg and dhdH.w stores dh (see paper) -void unmappingMuMuSunNu(float r, vec4 dhdH, out float mu, out float muSun, out float nu) { +void unmappingMuMuSunNu(float r, vec4 dhdH, int SAMPLES_MU, float Rg, float Rt, + int SAMPLES_MU_S, int SAMPLES_NU, + out float mu, out float muSun, out float nu) +{ // Window coordinates of pixel (uncentering also) vec2 fragment = gl_FragCoord.xy - vec2(0.5); // Pre-calculations float r2 = r * r; + float Rg2 = Rg * Rg; float halfSAMPLE_MU = float(SAMPLES_MU) / 2.0; // If the (vec(x) dot vec(v))/r is negative, i.e., the light ray has great probability // to touch the ground, we obtain mu considering the geometry of the ground if (fragment.y < halfSAMPLE_MU) { float ud = 1.0 - (fragment.y / (halfSAMPLE_MU - 1.0)); - float d = min(max(dhdH.z, ud * dhdH.w), dhdH.w * 0.999); + float d = min(max(dhdH.z, ud * dhdH.w), dhdH.w * 0.999); // cosine law: Rg^2 = r^2 + d^2 - 2rdcos(pi-theta) where cosine(theta) = mu mu = (Rg2 - r2 - d * d) / (2.0 * r * d); // We can't handle a ray inside the planet, i.e., when r ~ Rg, so we check against it. @@ -199,12 +128,12 @@ void unmappingMuMuSunNu(float r, vec4 dhdH, out float mu, out float muSun, out f float d = (fragment.y - halfSAMPLE_MU) / (halfSAMPLE_MU - 1.0); d = min(max(dhdH.x, d * dhdH.y), dhdH.y * 0.999); // cosine law: Rt^2 = r^2 + d^2 - 2rdcos(pi-theta) where cosine(theta) = mu - mu = (Rt2 - r2 - d * d) / (2.0 * r * d); + mu = (Rt*Rt - r2 - d * d) / (2.0 * r * d); } float modValueMuSun = mod(fragment.x, float(SAMPLES_MU_S)) / (float(SAMPLES_MU_S) - 1.0); - // The following mapping is different from the paper. See Colliene for an details. - muSun = tan((2.0 * modValueMuSun - 1.0 + 0.26) * 1.1f) / tan(1.26 * 1.1); + // The following mapping is different from the paper. See Collienne for an details. + muSun = tan((2.0 * modValueMuSun - 1.0 + 0.26) * 1.1) / tan(1.26 * 1.1); nu = -1.0 + floor(fragment.x / float(SAMPLES_MU_S)) / (float(SAMPLES_NU) - 1.0) * 2.0; } @@ -213,14 +142,14 @@ void unmappingMuMuSunNu(float r, vec4 dhdH, out float mu, out float muSun, out f // hits the ground or the top of atmosphere. // r := height of starting point vect(x) // mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r -vec3 transmittance(float r, float mu) { +vec3 transmittance(sampler2D tex, float r, float mu, float Rg, float Rt) { // Given the position x (here the altitude r) and the view angle v // (here the cosine(v)= mu), we map this - float u_r = sqrt((r - Rg) * invRtMinusRg); - // See Colliene to understand the mapping + float u_r = sqrt((r - Rg) / (Rt - Rg)); + // See Collienne to understand the mapping float u_mu = atan((mu + 0.15) / 1.15 * tan(1.5)) / 1.5; - return texture(transmittanceTexture, vec2(u_mu, u_r)).rgb; + return texture(tex, vec2(u_mu, u_r)).rgb; } // Given a position r and direction mu, calculates de transmittance along the ray with @@ -228,13 +157,13 @@ vec3 transmittance(float r, float mu) { // T(a,b) = TableT(a,v)/TableT(b, v) // r := height of starting point vect(x) // mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r -vec3 transmittance(float r, float mu, float d) { +vec3 transmittance(sampler2D tex, float r, float mu, float d, float Rg, float Rt) { // Here we use the transmittance property: T(x,v) = T(x,d)*T(d,v) to, given a distance // d, calculates that transmittance along that distance starting in x (height r): // T(x,d) = T(x,v)/T(d,v). // // From cosine law: c^2 = a^2 + b^2 - 2*a*b*cos(ab) - float ri = sqrt(d * d + r * r + 2.0 * r * d * mu); + float ri = sqrt(d * d + r * r + 2.0 * r * d * mu); // mu_i = (vec(d) dot vec(v)) / r_i // = ((vec(x) + vec(d-x)) dot vec(v))/ r_i // = (r*mu + d) / r_i @@ -246,19 +175,21 @@ vec3 transmittance(float r, float mu, float d) { // x --> x0, then x0-->x. // Also, let's use the property: T(a,c) = T(a,b)*T(b,c) // Because T(a,c) and T(b,c) are already in the table T, T(a,b) = T(a,c)/T(b,c). + vec3 res; if (mu > 0.0) { - return min(transmittance(r, mu) / transmittance(ri, mui), 1.0); + res = transmittance(tex, r, mu, Rg, Rt) / transmittance(tex, ri, mui, Rg, Rt); } else { - return min(transmittance(ri, -mui) / transmittance(r, -mu), 1.0); + res = transmittance(tex, ri, -mui, Rg, Rt) / transmittance(tex, r, -mu, Rg, Rt); } + return min(res, 1.0); } // Calculates Rayleigh phase function given the scattering cosine angle mu // mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r float rayleighPhaseFunction(float mu) { - //return (3.0f / (16.0f * M_PI)) * (1.0f + mu * mu); - return 0.0596831036 * (1.0 + mu * mu); + // return (3.0 / (16.0 * M_PI)) * (1.0 + mu * mu); + return 0.0596831036 * (1.0 + mu * mu); } // Calculates Mie phase function given the scattering cosine angle mu @@ -277,38 +208,30 @@ float miePhaseFunction(float mu, float mieG) { // mu := cosine of the zeith angle of vec(v). Or mu = (vec(x) * vec(v))/r // muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v)) // nu := cosine of the angle between vec(s) and vec(v) -vec4 texture4D(sampler3D table, float r, float mu, float muSun, float nu) { +vec4 texture4D(sampler3D table, float r, float mu, float muSun, float nu, float Rg, + int samplesMu, float Rt, int samplesR, int samplesMuS, + int samplesNu) +{ float r2 = r * r; + float Rg2 = Rg * Rg; + float Rt2 = Rt * Rt; float rho = sqrt(r2 - Rg2); float rmu = r * mu; float delta = rmu * rmu - r2 + Rg2; vec4 cst = rmu < 0.0 && delta > 0.0 ? - vec4(1.0, 0.0, 0.0, 0.5 - 0.5 * invSamplesMu) : - vec4(-1.0, H2, H, 0.5 + 0.5 * invSamplesMu); + vec4(1.0, 0.0, 0.0, 0.5 - 0.5 / float(samplesMu)) : + vec4(-1.0, Rt2 - Rg2, sqrt(Rt2 - Rg2), 0.5 + 0.5 / float(samplesMu)); - float u_r = 0.5 * invSamplesR + rho / H * (1.0 - invSamplesR); - float u_mu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5 - invSamplesMu); - float u_mu_s = 0.5 * invSamplesMuS + - (atan(max(muSun, -0.1975) * tan(1.386)) * 0.9090909090909090 + 0.74) * 0.5 * (1.0 - invSamplesMuS); - float lerp = (nu + 1.0) / 2.0 * (float(SAMPLES_NU) - 1.0); - float u_nu = floor(lerp); - lerp = lerp - u_nu; + float u_r = 0.5 / float(samplesR) + rho / sqrt(Rt2 - Rg2) * (1.0 - 1.0 / float(samplesR)); + float u_mu = cst.w + (rmu * cst.x + sqrt(delta + cst.y)) / (rho + cst.z) * (0.5 - 1.0 / samplesMu); + float u_mu_s = 0.5 / float(samplesMuS) + + (atan(max(muSun, -0.1975) * tan(1.386)) * 0.9090909090909090 + 0.74) * 0.5 * (1.0 - 1.0 / float(samplesMuS)); + float t = (nu + 1.0) / 2.0 * (float(samplesNu) - 1.0); + float u_nu = floor(t); + t = t - u_nu; - return texture( - table, vec3((u_nu + u_mu_s) * invSamplesNu, u_mu, u_r)) * (1.0 - lerp) + - texture(table, vec3((u_nu + u_mu_s + 1.0) * invSamplesNu, u_mu, u_r)) * lerp; -} - -// Given the irradiance texture table, the cosine of zenith sun vector and the height of -// the observer (ray's stating point x), calculates the mapping for u_r and u_muSun and -// returns the value in the LUT -// lut := OpenGL texture2D sampler (the irradiance texture deltaE) -// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v)) -// r := height of starting point vect(x) -vec3 irradianceLUT(sampler2D lut, float muSun, float r) { - // See Bruneton paper and Coliene to understand the mapping - float u_muSun = (muSun + 0.2) / 1.2; - float u_r = (r - Rg) * invRtMinusRg; - return texture(lut, vec2(u_muSun, u_r)).rgb; + vec4 v1 = texture(table, vec3((u_nu + u_mu_s) / float(samplesNu), u_mu, u_r)); + vec4 v2 = texture(table, vec3((u_nu + u_mu_s + 1.0) / float(samplesNu), u_mu, u_r)); + return mix(v1, v2, t); } diff --git a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl index f0f97c8de1..6c524a5072 100644 --- a/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl +++ b/modules/atmosphere/shaders/atmosphere_deferred_fs.glsl @@ -64,27 +64,37 @@ out vec4 renderTarget; uniform int cullAtmosphere; +uniform float Rg; +uniform float Rt; +uniform float groundRadianceEmission; +uniform float HR; +uniform vec3 betaRayleigh; +uniform float HO; +uniform vec3 betaOzoneExtinction; +uniform float HM; +uniform vec3 betaMieExtinction; +uniform float mieG; +uniform float sunRadiance; +uniform bool ozoneLayerEnabled; +uniform int SAMPLES_R; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; +uniform sampler2D transmittanceTexture; uniform sampler2D irradianceTexture; uniform sampler3D inscatterTexture; uniform sampler2D mainPositionTexture; uniform sampler2D mainNormalTexture; uniform sampler2D mainColorTexture; - uniform dmat4 inverseModelTransformMatrix; uniform dmat4 modelTransformMatrix; uniform dmat4 viewToWorldMatrix; uniform dmat4 projectionToModelTransformMatrix; - uniform vec4 viewport; uniform vec2 resolution; - uniform dvec3 camPosObj; uniform dvec3 sunDirectionObj; -uniform dvec3 sunWorld; -uniform dvec3 viewDirWorld; -uniform dvec3 sunModel; - /******************************************************************************* ***** ALL CALCULATIONS FOR ECLIPSE ARE IN METERS AND IN WORLD SPACE SYSTEM **** *******************************************************************************/ @@ -92,8 +102,10 @@ uniform dvec3 sunModel; const uint numberOfShadows = 1; struct ShadowRenderingStruct { - double xu, xp; - double rs, rc; + double xu; + double xp; + double rs; + double rc; dvec3 sourceCasterVec; dvec3 casterPositionVec; bool isShadowing; @@ -113,15 +125,15 @@ float calcShadow(ShadowRenderingStruct shadowInfoArray[numberOfShadows], dvec3 p } dvec3 pc = shadowInfoArray[0].casterPositionVec - position; - dvec3 sc_norm = shadowInfoArray[0].sourceCasterVec; - dvec3 pc_proj = dot(pc, sc_norm) * sc_norm; - dvec3 d = pc - pc_proj; + dvec3 scNorm = shadowInfoArray[0].sourceCasterVec; + dvec3 pcProj = dot(pc, scNorm) * scNorm; + dvec3 d = pc - pcProj; float length_d = float(length(d)); - double length_pc_proj = length(pc_proj); + double lengthPcProj = length(pcProj); - float r_p_pi = float(shadowInfoArray[0].rc * (length_pc_proj + shadowInfoArray[0].xp) / shadowInfoArray[0].xp); - float r_u_pi = float(shadowInfoArray[0].rc * (shadowInfoArray[0].xu - length_pc_proj) / shadowInfoArray[0].xu); + float r_p_pi = float(shadowInfoArray[0].rc * (lengthPcProj + shadowInfoArray[0].xp) / shadowInfoArray[0].xp); + float r_u_pi = float(shadowInfoArray[0].rc * (shadowInfoArray[0].xu - lengthPcProj) / shadowInfoArray[0].xu); if (length_d < r_u_pi) { // umbra @@ -142,6 +154,33 @@ float calcShadow(ShadowRenderingStruct shadowInfoArray[numberOfShadows], dvec3 p } } +float opticalDepth(float localH, float r, float mu, float d, float Rg) { + float invH = 1.0 / localH; + float a = sqrt(0.5 * invH * r); + vec2 a01 = a * vec2(mu, mu + d / r); + vec2 a01s = sign(a01); + vec2 a01sq = a01 * a01; + float x = a01s.y > a01s.x ? exp(a01sq.x) : 0.0; + vec2 y = a01s / (2.3193 * abs(a01) + sqrt(1.52 * a01sq + 4.0)) * + vec2(1.0, exp(-d * invH * (d / (2.0 * r) + mu))); + return sqrt(2.0 * M_PI * sqrt(Rt*Rt - Rg*Rg) * r) * exp((Rg-r)*invH) * (x + dot(y, vec2(1.0, -1.0))); +} + +vec3 analyticTransmittance(float r, float mu, float d) { + vec3 ozone = vec3(0.0); + if (ozoneLayerEnabled) { + ozone = betaOzoneExtinction * 0.0000006 * opticalDepth(HO, r, mu, d, Rg); + } + return exp(-betaRayleigh * opticalDepth(HR, r, mu, d, Rg) - ozone - + betaMieExtinction * opticalDepth(HM, r, mu, d, Rg)); +} + +vec3 irradiance(sampler2D s, float r, float muSun) { + float u_r = (r - Rg) / (Rt - Rg); + float u_muSun = (muSun + 0.2) / 1.2; + return texture(s, vec2(u_muSun, u_r)).rgb; +} + ////////////////////////////////////////////////////////////////////////////////////////// // ALL CALCULATIONS FOR ATMOSPHERE ARE KM AND IN WORLD SPACE SYSTEM // ////////////////////////////////////////////////////////////////////////////////////////// @@ -173,10 +212,11 @@ bool atmosphereIntersection(Ray ray, double atmRadius, out double offset, double l2 = dot(l, l); double r2 = atmRadius * atmRadius; // avoiding surface acne + offset = 0.0; + maxLength = 0.0; + // Ray origin (eye position) is behind sphere if ((s < 0.0) && (l2 > r2)) { - offset = 0.0; - maxLength = 0.0; return false; } @@ -184,13 +224,9 @@ bool atmosphereIntersection(Ray ray, double atmRadius, out double offset, // Ray misses atmosphere if (m2 > r2) { - offset = 0.0; - maxLength = 0.0; return false; } - // We already now the ray hits the atmosphere - // If q = 0.0, there is only one intersection double q = sqrt(r2 - m2); @@ -248,9 +284,9 @@ Ray calculateRayRenderableGlobe(vec2 st) { * the reflectance R[L] */ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 v, vec3 s, - float r, out float mu, out vec3 attenuation, vec3 fragPosObj, - out bool groundHit, double maxLength, double pixelDepth, - vec3 spaceColor, float sunIntensity) + float r, vec3 fragPosObj, double maxLength, double pixelDepth, + vec3 spaceColor, float sunIntensity, + out float mu, out vec3 attenuation, out bool groundHit) { const float INTERPOLATION_EPS = 0.004; // precision const from Brunetton @@ -268,7 +304,11 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 // I.e. the next line has the scattering light for the "infinite" ray passing through // the atmosphere. If this ray hits something inside the atmosphere, we will subtract // the attenuated scattering light from that path in the current path - vec4 inscatterRadiance = max(texture4D(inscatterTexture, r, mu, muSun, nu), 0.0); + vec4 inscatterRadiance = max( + texture4D(inscatterTexture, r, mu, muSun, nu, Rg, SAMPLES_MU, Rt, SAMPLES_R, + SAMPLES_MU_S, SAMPLES_NU), + 0.0 + ); // After removing the initial path from camera pos to top of atmosphere (for an // observer in the space) we test if the light ray is hitting the atmosphere @@ -286,13 +326,14 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 // attenuation = analyticTransmittance(r, mu, t); // JCC: change from analytical to LUT transmittance to avoid // acme on planet surface when looking from far away. (11/02/2017) - attenuation = transmittance(r, mu, t); + attenuation = transmittance(transmittanceTexture, r, mu, t, Rg, Rt); // Here we use the idea of S[L](a->b) = S[L](b->a), and get the S[L](x0, v, s) // Then we calculate S[L] = S[L]|x - T(x, x0)*S[L]|x0 // The "infinite" ray hist something inside the atmosphere, so we need to remove // the unsused contribution to the final radiance. - vec4 inscatterFromSurface = texture4D(inscatterTexture, r0, mu0, muSun0, nu); + vec4 inscatterFromSurface = texture4D(inscatterTexture, r0, mu0, muSun0, nu, Rg, + SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU); inscatterRadiance = max(inscatterRadiance - attenuation.rgbr * inscatterFromSurface, 0.0); // We set the irradianceFactor to 1.0 so the reflected irradiance will be considered @@ -307,7 +348,7 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 // cos(PI-thetaH) = dist/r // cos(thetaH) = -dist/r // muHorizon = -sqrt(r^2-Rg^2)/r = -sqrt(1-(Rg/r)^2) - float muHorizon = -sqrt(1.0 - Rg2 / r2); + float muHorizon = -sqrt(1.0 - Rg*Rg / r2); // In order to avoid precision problems near horizon, we interpolate between two // points: above and below horizon @@ -318,10 +359,10 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 // Above Horizon mu = muHorizon - INTERPOLATION_EPS; - // r0 = sqrt(r * r + t * t + 2.0f * r * t * mu); + // r0 = sqrt(r * r + t * t + 2.0 * r * t * mu); // From cosine law where t = distance between x and x0 // r0^2 = r^2 + t^2 - 2 * r * t * cos(PI-theta) - // r0 = sqrt(r2 + t2 + 2.0f * r * t * mu); + // r0 = sqrt(r2 + t2 + 2.0 * r * t * mu); float halfCosineLaw1 = r2 + (t * t); float halfCosineLaw2 = 2.0 * r * t; r0 = sqrt(halfCosineLaw1 + halfCosineLaw2 * mu); @@ -332,20 +373,24 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 // mu0 = (r*mu + t) / r0 mu0 = (r * mu + t) * (1.0 / r0); - vec4 inScatterAboveX = texture4D(inscatterTexture, r, mu, muSun, nu); - vec4 inScatterAboveXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu); + vec4 inScatterAboveX = texture4D(inscatterTexture, r, mu, muSun, nu, Rg, + SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU); + vec4 inScatterAboveXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu, Rg, + SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU); // Attention for the attenuation.r value applied to the S_Mie vec4 inScatterAbove = max(inScatterAboveX - attenuation.rgbr * inScatterAboveXs, 0.0); // Below Horizon mu = muHorizon + INTERPOLATION_EPS; - //r0 = sqrt(r2 + t2 + 2.0f * r * t * mu); + //r0 = sqrt(r2 + t2 + 2.0 * r * t * mu); r0 = sqrt(halfCosineLaw1 + halfCosineLaw2 * mu); mu0 = (r * mu + t) * (1.0 / r0); - vec4 inScatterBelowX = texture4D(inscatterTexture, r, mu, muSun, nu); - vec4 inScatterBelowXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu); + vec4 inScatterBelowX = texture4D(inscatterTexture, r, mu, muSun, nu, Rg, + SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU); + vec4 inScatterBelowXs = texture4D(inscatterTexture, r0, mu0, muSun0, nu, Rg, + SAMPLES_MU, Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU); // Attention for the attenuation.r value applied to the S_Mie vec4 inScatterBelow = max(inScatterBelowX - attenuation.rgbr * inScatterBelowXs, 0.0); @@ -370,13 +415,7 @@ vec3 inscatterRadiance(vec3 x, inout float t, inout float irradianceFactor, vec3 // Finally we add the Lsun (all calculations are done with no Lsun so we can change it // on the fly with no precomputations) vec3 finalScatteringRadiance = radiance * sunIntensity; - - if (groundHit) { - return finalScatteringRadiance; - } - else { - return spaceColor + finalScatteringRadiance; - } + return groundHit ? finalScatteringRadiance : spaceColor + finalScatteringRadiance; } /* @@ -401,8 +440,6 @@ vec3 groundColor(vec3 x, float t, vec3 v, vec3 s, vec3 attenuationXtoX0, vec3 gr vec3 normal, float irradianceFactor, float waterReflectance, float sunIntensity) { - vec3 reflectedRadiance = vec3(0.0); - // First we obtain the ray's end point on the surface float r0 = length(x + t * v); @@ -415,7 +452,7 @@ vec3 groundColor(vec3 x, float t, vec3 v, vec3 s, vec3 attenuationXtoX0, vec3 gr // Is direct Sun light arriving at x0? If not, there is no direct light from Sun (shadowed) vec3 transmittanceL0 = - muSun < -sqrt(1.0 - (Rg2 / (r0 * r0))) ? vec3(0.0) : transmittance(r0, muSun); + muSun < -sqrt(1.0 - (Rg*Rg / (r0 * r0))) ? vec3(0.0) : transmittance(transmittanceTexture, r0, muSun, Rg, Rt); // E[L*] at x0 vec3 irradianceReflected = irradiance(irradianceTexture, r0, muSun) * irradianceFactor; @@ -433,16 +470,14 @@ vec3 groundColor(vec3 x, float t, vec3 v, vec3 s, vec3 attenuationXtoX0, vec3 gr // Fresnell Schlick's approximation float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0); // Walter BRDF approximation - float waterBrdf = fresnel * pow(max(dot(h, normal), 0.0), 150.0); + float waterBrdf = max(fresnel * pow(max(dot(h, normal), 0.0), 150.0), 0.0); // Adding Fresnell and Water BRDFs approximation to the final surface color // after adding the sunRadiance and the attenuation of the Sun through atmosphere - groundRadiance += waterReflectance * max(waterBrdf, 0.0) * transmittanceL0 * sunIntensity; + groundRadiance += waterReflectance * waterBrdf * transmittanceL0 * sunIntensity; } // Finally, we attenuate the surface Radiance from the point x0 to the camera location - reflectedRadiance = attenuationXtoX0 * groundRadiance; - - // Returns reflectedRadiance = 0.0 if the ray doesn't hit the ground. + vec3 reflectedRadiance = attenuationXtoX0 * groundRadiance; return reflectedRadiance; } @@ -464,7 +499,7 @@ vec3 sunColor(vec3 v, vec3 s, float r, float mu, float irradianceFactor) { // JCC: Change this function to a impostor texture with gaussian decay color weighted // by the sunRadiance, transmittance and irradianceColor (11/03/2017) - // @TODO (abock, 2021-07-01) This value is hard-coded to our sun right now + // @TODO (abock, 2021-07-01) This value is hard-coded to our sun+earth right now // Convert 0.3 degrees -> radians const float SunAngularSize = (0.3 * M_PI / 180.0); const float FuzzyFactor = 0.5; // How fuzzy should the edges be @@ -474,7 +509,7 @@ vec3 sunColor(vec3 v, vec3 s, float r, float mu, float irradianceFactor) { float t = (angle - p1) / (p2 - p1); float scale = clamp(t, 0.0, 1.0); - return scale * transmittance(r, mu) * sunRadiance * (1.0 - irradianceFactor); + return scale * transmittance(transmittanceTexture, r, mu, Rg, Rt) * sunRadiance * (1.0 - irradianceFactor); } void main() { @@ -588,24 +623,22 @@ void main() { bool groundHit = false; vec3 attenuation; - vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v, s, r, mu, - attenuation, vec3(positionObjectsCoords), groundHit, maxLength, pixelDepth, - color, sunIntensityInscatter); + vec3 inscatterColor = inscatterRadiance(x, tF, irradianceFactor, v, s, r, + vec3(positionObjectsCoords), maxLength, pixelDepth, color, sunIntensityInscatter, mu, + attenuation, groundHit); vec3 atmColor = vec3(0.0); if (groundHit) { float eclipseShadowPlanet = calcShadow(shadowDataArray, positionWorldCoords.xyz, true); float sunIntensityGround = sunRadiance * eclipseShadowPlanet; - atmColor = groundColor(x, tF, v, s, attenuation, color, normal.xyz, - irradianceFactor, normal.w, sunIntensityGround); + atmColor = groundColor(x, tF, v, s, attenuation, color, normal.xyz, irradianceFactor, + normal.w, sunIntensityGround); } else { // In order to get better performance, we are not tracing multiple rays per pixel // when the ray doesn't intersect the ground - atmColor = sunColor(v, s, r, mu, irradianceFactor); } // Final Color of ATM plus terrain: - vec4 finalRadiance = vec4(inscatterColor + atmColor, 1.0); - renderTarget = finalRadiance; + renderTarget = vec4(inscatterColor + atmColor, 1.0);; } diff --git a/modules/atmosphere/shaders/calculation_vs.glsl b/modules/atmosphere/shaders/calculation_vs.glsl index be225fa6a6..a7d480b829 100644 --- a/modules/atmosphere/shaders/calculation_vs.glsl +++ b/modules/atmosphere/shaders/calculation_vs.glsl @@ -24,8 +24,8 @@ #version __CONTEXT__ -layout(location = 0) in vec3 in_position; +layout(location = 0) in vec2 in_position; void main() { - gl_Position = vec4(in_position, 1.0); + gl_Position = vec4(in_position, 0.0, 1.0); } diff --git a/modules/atmosphere/shaders/deltaE_calc_fs.glsl b/modules/atmosphere/shaders/deltaE_calc_fs.glsl index fe0163b6b2..117bd0a631 100644 --- a/modules/atmosphere/shaders/deltaE_calc_fs.glsl +++ b/modules/atmosphere/shaders/deltaE_calc_fs.glsl @@ -24,8 +24,6 @@ #version __CONTEXT__ -#include "atmosphere_common.glsl" - out vec4 renderTableColor; void main() { diff --git a/modules/atmosphere/shaders/deltaJ_calc_fs.glsl b/modules/atmosphere/shaders/deltaJ_calc_fs.glsl index 37bacbe3b9..044ea1de30 100644 --- a/modules/atmosphere/shaders/deltaJ_calc_fs.glsl +++ b/modules/atmosphere/shaders/deltaJ_calc_fs.glsl @@ -28,19 +28,45 @@ out vec4 renderTarget; +uniform float Rg; +uniform float Rt; +uniform float AverageGroundReflectance; +uniform float HR; +uniform vec3 betaRayleigh; +uniform float HM; +uniform vec3 betaMieScattering; +uniform float mieG; +uniform int SAMPLES_R; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; +uniform sampler2D transmittanceTexture; uniform float r; uniform vec4 dhdH; - uniform sampler2D deltaETexture; uniform sampler3D deltaSRTexture; uniform sampler3D deltaSMTexture; +uniform int firstIteration; -uniform int firstIteraction; +const int INSCATTER_SPHERICAL_INTEGRAL_SAMPLES = 16; // -- Spherical Coordinates Steps. phi e [0,2PI] and theta e [0, PI] const float stepPhi = (2.0 * M_PI) / float(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES); const float stepTheta = M_PI / float(INSCATTER_SPHERICAL_INTEGRAL_SAMPLES); +// Given the irradiance texture table, the cosine of zenith sun vector and the height of +// the observer (ray's stating point x), calculates the mapping for u_r and u_muSun and +// returns the value in the LUT +// lut := OpenGL texture2D sampler (the irradiance texture deltaE) +// muSun := cosine of the zeith angle of vec(s). Or muSun = (vec(s) * vec(v)) +// r := height of starting point vect(x) +vec3 irradianceLUT(sampler2D lut, float muSun, float r) { + // See Bruneton paper and Coliene to understand the mapping + float u_muSun = (muSun + 0.2) / 1.2; + float u_r = (r - Rg) / (Rt - Rg); + return texture(lut, vec2(u_muSun, u_r)).rgb; +} + vec3 inscatter(float r, float mu, float muSun, float nu) { // Be sure to not get a cosine or height out of bounds r = clamp(r, Rg, Rt); @@ -59,7 +85,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) { float muSun2 = muSun * muSun; float sinThetaSinSigma = sqrt(1.0 - mu2) * sqrt(1.0 - muSun2); // cos(sigma + theta) = cos(theta)cos(sigma)-sin(theta)sin(sigma) - // cos(ni) = nu = mu * muSun - sqrt(1.0f - mu*mu)*sqrt(1.0 - muSun*muSun) // sin(theta) = sqrt(1.0 - mu*mu) + // cos(ni) = nu = mu * muSun - sqrt(1.0 - mu*mu)*sqrt(1.0 - muSun*muSun) // sin(theta) = sqrt(1.0 - mu*mu) // Now we make sure the angle between vec(s) and vec(v) is in the right range: nu = clamp(nu, muSun * mu - sinThetaSinSigma, muSun * mu + sinThetaSinSigma); @@ -69,7 +95,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) { // -cos(theta) = sqrt(r*r-Rg*Rg)/r float Rg2 = Rg * Rg; float r2 = r * r; - float cosHorizon = -sqrt(r2 - Rg2)/r; + float cosHorizon = -sqrt(r2 - Rg2) / r; // Now we get vec(v) and vec(s) from mu, muSun and nu: // Assuming: @@ -97,6 +123,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) { // In order to integrate over 4PI, we scan the sphere using the spherical coordinates // previously defined + vec3 radianceJAcc = vec3(0.0); for (int theta_i = 0; theta_i < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; theta_i++) { float theta = (float(theta_i) + 0.5) * stepTheta; float cosineTheta = cos(theta); @@ -131,7 +158,7 @@ vec3 inscatter(float r, float mu, float muSun, float nu) { // float muGround = (r2 - distanceToGround*distanceToGround - Rg2)/(2*distanceToGround*Rg); // Access the Transmittance LUT in order to calculate the transmittance from the // ground point Rg, thorugh the atmosphere, at a distance: distanceToGround - groundTransmittance = transmittance(Rg, muGround, distanceToGround); + groundTransmittance = transmittance(transmittanceTexture, Rg, muGround, distanceToGround, Rg, Rt); } for (int phi_i = 0; phi_i < INSCATTER_SPHERICAL_INTEGRAL_SAMPLES; ++phi_i) { @@ -161,43 +188,48 @@ vec3 inscatter(float r, float mu, float muSun, float nu) { // We calculate the Rayleigh and Mie phase function for the new scattering angle: // cos(angle between vec(s) and vec(w)), ||s|| = ||w|| = 1 float nuSW = dot(s, w); - // The first iteraction is different from the others. In the first iteraction all + // The first iteration is different from the others. In the first iteration all // the light InScattered is coming from the initial pre-computed single InScattered // light. We stored these values in the deltaS textures (Ray and Mie), and in order // to avoid problems with the high angle dependency in the phase functions, we don't // include the phase functions on those tables (that's why we calculate them now). - if (firstIteraction == 1) { + if (firstIteration == 1) { float phaseRaySW = rayleighPhaseFunction(nuSW); float phaseMieSW = miePhaseFunction(nuSW, mieG); // We can now access the values for the single InScattering in the textures deltaS textures. - vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nuSW).rgb; - vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nuSW).rgb; + vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nuSW, Rg, SAMPLES_MU, + Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb; + vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nuSW, Rg, SAMPLES_MU, + Rt, SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb; // Initial InScattering including the phase functions radianceJ1 += singleRay * phaseRaySW + singleMie * phaseMieSW; } else { // On line 9 of the algorithm, the texture table deltaSR is updated, so when we - // are not in the first iteraction, we are getting the updated result of deltaSR + // are not in the first iteration, we are getting the updated result of deltaSR // (not the single inscattered light but the accumulated (higher order) // inscattered light. // w.z is the cosine(theta) = mu for vec(w) - radianceJ1 += texture4D(deltaSRTexture, r, w.z, muSun, nuSW).rgb; + radianceJ1 += texture4D(deltaSRTexture, r, w.z, muSun, nuSW, Rg, SAMPLES_MU, Rt, + SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb; } // Finally, we add the atmospheric scale height (See: Radiation Transfer on the // Atmosphere and Ocean from Thomas and Stamnes, pg 9-10. - return radianceJ1 * (betaRayleigh * exp(-(r - Rg) / HR) * phaseRayleighWV + + radianceJAcc += radianceJ1 * (betaRayleigh * exp(-(r - Rg) / HR) * phaseRayleighWV + betaMieScattering * exp(-(r - Rg) / HM) * phaseMieWV) * dw; } } + + return radianceJAcc; } void main() { // InScattering Radiance to be calculated at different points in the ray path // Unmapping the variables from texture texels coordinates to mapped coordinates float mu, muSun, nu; - unmappingMuMuSunNu(r, dhdH, mu, muSun, nu); + unmappingMuMuSunNu(r, dhdH, SAMPLES_MU, Rg, Rt, SAMPLES_MU_S, SAMPLES_NU, mu, muSun, nu); // Calculate the the light inScattered in direction // -vec(v) for the point at height r (vec(y) following Bruneton and Neyret's paper diff --git a/modules/atmosphere/shaders/deltaS_calc_fs.glsl b/modules/atmosphere/shaders/deltaS_calc_fs.glsl index b5d7de5e79..ca97f15ff9 100644 --- a/modules/atmosphere/shaders/deltaS_calc_fs.glsl +++ b/modules/atmosphere/shaders/deltaS_calc_fs.glsl @@ -28,6 +28,10 @@ out vec4 renderTarget; +uniform int SAMPLES_R; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; uniform int layer; uniform sampler3D deltaSRTexture; uniform sampler3D deltaSMTexture; diff --git a/modules/atmosphere/shaders/deltaS_sup_calc_fs.glsl b/modules/atmosphere/shaders/deltaS_sup_calc_fs.glsl index ebe63b5071..7580c790be 100644 --- a/modules/atmosphere/shaders/deltaS_sup_calc_fs.glsl +++ b/modules/atmosphere/shaders/deltaS_sup_calc_fs.glsl @@ -28,6 +28,10 @@ out vec4 renderTarget; +uniform int SAMPLES_R; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; uniform int layer; uniform sampler3D deltaSTexture; @@ -35,10 +39,9 @@ void main() { vec2 p = gl_FragCoord.xy - vec2(0.5); float nu = -1.0 + floor(p.x / float(SAMPLES_MU_S)) / (float(SAMPLES_NU) - 1.0) * 2.0; - vec3 uvw = vec3( - gl_FragCoord.xy, - float(layer) + 0.5) / vec3(ivec3(SAMPLES_MU_S * SAMPLES_NU, SAMPLES_MU, SAMPLES_R) - ); + vec3 uvw = + vec3(gl_FragCoord.xy, float(layer) + 0.5) / + vec3(ivec3(SAMPLES_MU_S * SAMPLES_NU, SAMPLES_MU, SAMPLES_R)); // See Bruneton and Neyret paper, "Angular Precision" paragraph to understanding why we // are dividing the S[L*] by the Rayleigh phase function. diff --git a/modules/atmosphere/shaders/inScattering_calc_fs.glsl b/modules/atmosphere/shaders/inScattering_calc_fs.glsl index 8443cb1109..94c7aabcac 100644 --- a/modules/atmosphere/shaders/inScattering_calc_fs.glsl +++ b/modules/atmosphere/shaders/inScattering_calc_fs.glsl @@ -29,6 +29,18 @@ layout(location = 0) out vec4 renderTarget1; layout(location = 1) out vec4 renderTarget2; +uniform float Rg; +uniform float Rt; +uniform float HR; +uniform vec3 betaRayleigh; +uniform float HO; +uniform float HM; +uniform vec3 betaMieScattering; +uniform bool ozoneLayerEnabled; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; +uniform sampler2D transmittanceTexture; uniform float r; uniform vec4 dhdH; @@ -60,7 +72,9 @@ void integrand(float r, float mu, float muSun, float nu, float y, out vec3 S_R, if (muSun_i >= -sqrt(1.0 - Rg * Rg / (ri * ri))) { // It's the transmittance from the point y (ri) to the top of atmosphere in direction // of the sun (muSun_i) and the transmittance from the observer at x (r) to y (ri). - vec3 transmittanceY = transmittance(r, mu, y) * transmittance(ri, muSun_i); + vec3 transmittanceY = + transmittance(transmittanceTexture, r, mu, y, Rg, Rt) * + transmittance(transmittanceTexture, ri, muSun_i, Rg, Rt); // exp(-h/H)*T(x,v) if (ozoneLayerEnabled) { S_R = (exp(-(ri - Rg) / HO) + exp(-(ri - Rg) / HR)) * transmittanceY; @@ -83,7 +97,7 @@ void inscatter(float r, float mu, float muSun, float nu, out vec3 S_R, out vec3 S_R = vec3(0.0); S_M = vec3(0.0); - float rayDist = rayDistance(r, mu); + float rayDist = rayDistance(r, mu, Rt, Rg); float dy = rayDist / float(INSCATTER_INTEGRAL_SAMPLES); vec3 S_Ri; vec3 S_Mi; @@ -103,13 +117,10 @@ void inscatter(float r, float mu, float muSun, float nu, out vec3 S_R, out vec3 } void main() { - vec3 S_R; // First Order Rayleigh InScattering - vec3 S_M; // First Order Mie InScattering - // From the layer interpolation (see C++ code for layer to r) and the textures // parameters (uv), we unmapping mu, muSun and nu. float mu, muSun, nu; - unmappingMuMuSunNu(r, dhdH, mu, muSun, nu); + unmappingMuMuSunNu(r, dhdH, SAMPLES_MU, Rg, Rt, SAMPLES_MU_S, SAMPLES_NU, mu, muSun, nu); // Here we calculate the single inScattered light. Because this is a single // inscattering, the light that arrives at a point y in the path from the eye to the @@ -122,6 +133,8 @@ void main() { // S[L0] = P_R*S_R[L0] + P_M*S_M[L0] // In order to save memory, we just store the red component of S_M[L0], and later we use // the proportionality rule to calcule the other components. + vec3 S_R; // First Order Rayleigh InScattering + vec3 S_M; // First Order Mie InScattering inscatter(r, mu, muSun, nu, S_R, S_M); renderTarget1 = vec4(S_R, 1.0); renderTarget2 = vec4(S_M, 1.0); diff --git a/modules/atmosphere/shaders/inScattering_sup_calc_fs.glsl b/modules/atmosphere/shaders/inScattering_sup_calc_fs.glsl index fd128b3b16..c84ffff774 100644 --- a/modules/atmosphere/shaders/inScattering_sup_calc_fs.glsl +++ b/modules/atmosphere/shaders/inScattering_sup_calc_fs.glsl @@ -28,6 +28,13 @@ out vec4 renderTarget; +uniform float Rg; +uniform float Rt; +uniform int SAMPLES_R; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; +uniform sampler2D transmittanceTexture; uniform float r; uniform vec4 dhdH; uniform sampler3D deltaJTexture; @@ -35,7 +42,7 @@ uniform sampler3D deltaJTexture; // The integrand here is the f(y) of the trapezoidal rule: vec3 integrand(float r, float mu, float muSun, float nu, float dist) { // We can calculate r_i by the cosine law: r_i^2=dist^2 + r^2 - 2*r*dist*cos(PI-theta) - float r_i = sqrt(r * r + dist * dist + 2.0f * r * dist * mu); + float r_i = sqrt(r * r + dist * dist + 2.0 * r * dist * mu); // r_i can be found using the dot product: // vec(y_i) dot vec(dist) = cos(theta_i) * ||vec(y_i)|| * ||vec(dist)|| // But vec(y_i) = vec(x) + vec(dist), also: vec(x) dot vec(dist) = cos(theta) = mu @@ -46,12 +53,15 @@ vec3 integrand(float r, float mu, float muSun, float nu, float dist) { // But vec(y_i) = vec(x) + vec(dist), and vec(x) dot vec(s) = muSun, cos(sigma_i + theta_i) = nu float muSun_i = (r * muSun + dist * nu) / r_i; // The irradiance attenuated from point r until y (y-x = dist) - return transmittance(r, mu, dist) * texture4D(deltaJTexture, r_i, mu_i, muSun_i, nu).rgb; + return + transmittance(transmittanceTexture, r, mu, dist, Rg, Rt) * + texture4D(deltaJTexture, r_i, mu_i, muSun_i, nu, Rg, SAMPLES_MU, Rt, SAMPLES_R, + SAMPLES_MU_S, SAMPLES_NU).rgb; } vec3 inscatter(float r, float mu, float muSun, float nu) { vec3 inScatteringRadiance = vec3(0.0); - float dy = rayDistance(r, mu) / float(INSCATTER_INTEGRAL_SAMPLES); + float dy = rayDistance(r, mu, Rt, Rg) / float(INSCATTER_INTEGRAL_SAMPLES); vec3 inScatteringRadiance_i = integrand(r, mu, muSun, nu, 0.0); // In order to solve the integral from equation (11) we use the trapezoidal rule: @@ -71,7 +81,7 @@ void main() { float muSun = 0.0; float nu = 0.0; // Unmapping the variables from texture texels coordinates to mapped coordinates - unmappingMuMuSunNu(r, dhdH, mu, muSun, nu); + unmappingMuMuSunNu(r, dhdH, SAMPLES_MU, Rg, Rt, SAMPLES_MU_S, SAMPLES_NU, mu, muSun, nu); // Write to texture deltaSR renderTarget = vec4(inscatter(r, mu, muSun, nu), 1.0); diff --git a/modules/atmosphere/shaders/irradiance_calc_fs.glsl b/modules/atmosphere/shaders/irradiance_calc_fs.glsl index 93fca5128e..4e31d608b1 100644 --- a/modules/atmosphere/shaders/irradiance_calc_fs.glsl +++ b/modules/atmosphere/shaders/irradiance_calc_fs.glsl @@ -28,16 +28,24 @@ out vec4 renderTableColor; -void main() { - // See Bruneton and Colliene to understand the mapping - float muSun = -0.2 + (gl_FragCoord.x - 0.5) / (float(OTHER_TEXTURES.x) - 1.0) * 1.2; - float r = Rg + (gl_FragCoord.y - 0.5) / (float(OTHER_TEXTURES.y) ) * RtMinusRg; +uniform float Rg; +uniform float Rt; +uniform ivec2 OTHER_TEXTURES; +uniform sampler2D transmittanceTexture; - // We are calculating the Irradiance for L0, i.e., only the radiance coming from Sun - // direction is accounted: +void main() { + // See Bruneton and Collienne to understand the mapping + float muSun = -0.2 + (gl_FragCoord.x - 0.5) / (float(OTHER_TEXTURES.x) - 1.0) * 1.2; + float r = Rg + (gl_FragCoord.y - 0.5) / (float(OTHER_TEXTURES.y)) * (Rt - Rg); + + // We are calculating the Irradiance for L0, i.e., only the radiance coming from the Sun + // direction is accounted for: // E[L0](x,s) = L0*dot(w,n) or 0 (if v!=s or the sun is occluded). - // Because we consider the Planet as a perfect sphere and we are considering only single + // Because we consider the planet as a perfect sphere and we are considering only single // scattering here, the dot product dot(w,n) is equal to dot(s,n) that is equal to // dot(s, r/||r||) = muSun. - renderTableColor = vec4(transmittance(r, muSun) * max(muSun, 0.0), 0.0); + renderTableColor = vec4( + transmittance(transmittanceTexture, r, muSun, Rg, Rt) * max(muSun, 0.0), + 0.0 + ); } diff --git a/modules/atmosphere/shaders/irradiance_final_fs.glsl b/modules/atmosphere/shaders/irradiance_final_fs.glsl index 5f9834ab2c..6640cc2f6a 100644 --- a/modules/atmosphere/shaders/irradiance_final_fs.glsl +++ b/modules/atmosphere/shaders/irradiance_final_fs.glsl @@ -24,10 +24,9 @@ #version __CONTEXT__ -#include "atmosphere_common.glsl" - out vec4 renderTableColor; +uniform ivec2 OTHER_TEXTURES; uniform sampler2D deltaETexture; void main() { diff --git a/modules/atmosphere/shaders/irradiance_sup_calc_fs.glsl b/modules/atmosphere/shaders/irradiance_sup_calc_fs.glsl index 06b31090b8..5c3f29452e 100644 --- a/modules/atmosphere/shaders/irradiance_sup_calc_fs.glsl +++ b/modules/atmosphere/shaders/irradiance_sup_calc_fs.glsl @@ -28,22 +28,32 @@ out vec4 renderTableColor; -uniform int firstIteraction; +uniform float Rg; +uniform float Rt; +uniform float mieG; +uniform ivec2 SKY; +uniform int SAMPLES_R; +uniform int SAMPLES_MU; +uniform int SAMPLES_MU_S; +uniform int SAMPLES_NU; +uniform int firstIteration; uniform sampler3D deltaSRTexture; uniform sampler3D deltaSMTexture; +const int IRRADIANCE_INTEGRAL_SAMPLES = 32; + // Spherical Coordinates Steps. phi e [0,2PI] and theta e [0, PI/2] const float stepPhi = (2.0 * M_PI) / float(IRRADIANCE_INTEGRAL_SAMPLES); const float stepTheta = M_PI / (2.0 * float(IRRADIANCE_INTEGRAL_SAMPLES)); void main() { - // See Bruneton and Colliene to understand the mapping. + // See Bruneton and Collienne to understand the mapping. float muSun = -0.2 + (gl_FragCoord.x - 0.5) / (float(SKY.x) - 1.0) * 1.2; - float r = Rg + (gl_FragCoord.y - 0.5) / (float(SKY.y) - 1.0) * RtMinusRg; + float r = Rg + (gl_FragCoord.y - 0.5) / (float(SKY.y) - 1.0) * (Rt - Rg); // We know that muSun = cos(sigma) = s.z/||s|| // But, ||s|| = 1, so s.z = muSun. Also, - // ||s|| = 1, so s.x = sin(sigma) = sqrt(1-muSun^2) and s.y = 0.0f + // ||s|| = 1, so s.x = sin(sigma) = sqrt(1-muSun^2) and s.y = 0.0 vec3 s = vec3(max(sqrt(1.0 - muSun * muSun), 0.0), 0.0, muSun); // In order to solve the integral from equation (15) we use the trapezoidal rule: @@ -60,30 +70,32 @@ void main() { vec3 w = vec3(cos(phi) * sin(theta), sin(phi) * sin(theta), cos(theta)); float nu = dot(s, w); - // The first iteraction is different from the others, that's because in the first - // iteraction all the light arriving are coming from the initial pre-computed - // single scattered light. We stored these values in the deltaS textures (Ray and - // Mie), and in order to avoid problems with the high angle dependency in the phase - // functions, we don't include the phase functions on those tables (that's why we - // calculate them now) - if (firstIteraction == 1) { + // The first iteration is different from the others as in the first iteration all + // the light arriving is coming from the initial pre-computed single scattered + // light. We stored these values in the deltaS textures (Ray and Mie), and in order + // to avoid problems with the high angle dependency in the phase functions, we don't + // include the phase functions on those tables (that's why we calculate them now) + if (firstIteration == 1) { float phaseRay = rayleighPhaseFunction(nu); float phaseMie = miePhaseFunction(nu, mieG); - vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nu).rgb; - vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nu).rgb; + vec3 singleRay = texture4D(deltaSRTexture, r, w.z, muSun, nu, Rg, SAMPLES_MU, Rt, + SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb; + vec3 singleMie = texture4D(deltaSMTexture, r, w.z, muSun, nu, Rg, SAMPLES_MU, Rt, + SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb; // w.z is the cosine(theta) = mu for vec(w) and also vec(w) dot vec(n(xo)) irradianceE += (singleRay * phaseRay + singleMie * phaseMie) * w.z * dw; } else { // On line 10 of the algorithm, the texture table deltaE is updated, so when we - // are not in the first iteraction, we are getting the updated result of deltaE + // are not in the first iteration, we are getting the updated result of deltaE // (not the single irradiance light but the accumulated (higher order) irradiance // light. w.z is the cosine(theta) = mu for vec(w) and also vec(w) dot vec(n(xo)) - irradianceE += texture4D(deltaSRTexture, r, w.z, muSun, nu).rgb * w.z * dw; + irradianceE += texture4D(deltaSRTexture, r, w.z, muSun, nu, Rg, SAMPLES_MU, Rt, + SAMPLES_R, SAMPLES_MU_S, SAMPLES_NU).rgb * w.z * dw; } } } - // Write the higher oder irradiance to texture deltaE + // Write the higher order irradiance to texture deltaE renderTableColor = vec4(irradianceE, 0.0); } diff --git a/modules/atmosphere/shaders/transmittance_calc_fs.glsl b/modules/atmosphere/shaders/transmittance_calc_fs.glsl index cf78347f29..a0dd54f6f2 100644 --- a/modules/atmosphere/shaders/transmittance_calc_fs.glsl +++ b/modules/atmosphere/shaders/transmittance_calc_fs.glsl @@ -28,6 +28,19 @@ out vec4 renderTableColor; +uniform float Rg; +uniform float Rt; +uniform float HR; +uniform vec3 betaRayleigh; +uniform float HO; +uniform vec3 betaOzoneExtinction; +uniform float HM; +uniform vec3 betaMieExtinction; +uniform bool ozoneLayerEnabled; +uniform ivec2 TRANSMITTANCE; + +const int TRANSMITTANCE_STEPS = 500; + // Optical depth by integration, from ray starting at point vec(x), i.e, height r and // angle mu (cosine of vec(v)) until top of atmosphere or planet's ground. // r := height of starting point vect(x) @@ -42,14 +55,14 @@ float opticalDepth(float r, float mu, float H) { // direction and starting and ending points. // cosine law for triangles: y_i^2 = a^2 + b^2 - 2abcos(alpha) - float cosZenithHorizon = -sqrt(1.0 - (Rg * Rg / r2)); + float cosZenithHorizon = -sqrt(1.0 - ((Rg * Rg) / r2)); if (mu < cosZenithHorizon) { return 1e9; } // Integrating using the Trapezoidal rule: // Integral(f(y)dy)(from a to b) = ((b-a)/2n_steps)*(Sum(f(y_i+1)+f(y_i))) - float b_a = rayDistance(r, mu); + float b_a = rayDistance(r, mu, Rt, Rg); float deltaStep = b_a / float(TRANSMITTANCE_STEPS); // cosine law float y_i = exp(-(r - Rg) / H); @@ -72,11 +85,11 @@ void main() { // In the paper u_r^2 = (r^2-Rg^2)/(Rt^2-Rg^2) // So, extracting r from u_r in the above equation: - float r = Rg + (u_r * u_r) * RtMinusRg; + float r = Rg + (u_r * u_r) * (Rt - Rg); // In the paper the Bruneton suggest mu = dot(v,x)/||x|| with ||v|| = 1.0 // Later he proposes u_mu = (1-exp(-3mu-0.6))/(1-exp(-3.6)) - // But the below one is better. See Colliene. + // But the below one is better. See Collienne. // One must remember that mu is defined from 0 to PI/2 + epsilon float muSun = -0.15 + tan(1.5 * u_mu) / tan(1.5) * 1.15; diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 7c93764d9f..1a92b2f781 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -1067,7 +1067,6 @@ void FramebufferRenderer::updateDeferredcastData() { std::filesystem::path vsPath = caster->deferredcastVSPath(); std::filesystem::path fsPath = caster->deferredcastFSPath(); - std::filesystem::path deferredShaderPath = caster->deferredcastPath(); ghoul::Dictionary dict; dict.setValue("rendererData", _rendererData); @@ -1086,17 +1085,10 @@ void FramebufferRenderer::updateDeferredcastData() { _deferredcastPrograms[caster] = ghoul::opengl::ProgramObject::Build( "Deferred " + std::to_string(data.id) + " raycast", vsPath, - deferredShaderPath, + fsPath, dict ); - _deferredcastPrograms[caster]->setIgnoreSubroutineUniformLocationError( - ghoul::opengl::ProgramObject::IgnoreError::Yes - ); - _deferredcastPrograms[caster]->setIgnoreUniformLocationError( - ghoul::opengl::ProgramObject::IgnoreError::Yes - ); - caster->initializeCachedVariables(*_deferredcastPrograms[caster]); } catch (ghoul::RuntimeError& e) { From fcc108312968c3f850ed72c548eafa500b5b2188 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 22 Jul 2021 20:51:01 +0200 Subject: [PATCH 02/24] Make the Speckloader ignore tabs as well as spaces (closes #1688) --- modules/space/speckloader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index 649e3f9aff..6ee778bf42 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -50,7 +50,7 @@ namespace { // 3. Remove all spaces from the new beginning // 4. Remove all spaces from the end - while (!line.empty() && line[0] == ' ') { + while (!line.empty() && (line[0] == ' ' || line[0] == '\t')) { line = line.substr(1); } @@ -58,11 +58,11 @@ namespace { line = line.substr(1); } - while (!line.empty() && line[0] == ' ') { + while (!line.empty() && (line[0] == ' ' || line[0] == '\t')) { line = line.substr(1); } - while (!line.empty() && line.back() == ' ') { + while (!line.empty() && (line.back() == ' ' || line.back() == '\t')) { line = line.substr(0, line.size() - 1); } } From 527bc4d108e060d3ccfadf961746caf3147c134a Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 22 Jul 2021 21:04:53 +0200 Subject: [PATCH 03/24] Add support for speck keywords that are mixed case (closes #1689) --- modules/space/speckloader.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index 6ee778bf42..4bf46d86cf 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -40,7 +40,10 @@ namespace { constexpr const int8_t LabelCacheFileVersion = 10; constexpr const int8_t ColorCacheFileVersion = 10; - constexpr bool startsWith(std::string_view lhs, std::string_view rhs) noexcept { + bool startsWith(std::string lhs, std::string_view rhs) noexcept { + for (size_t i = 0; i < lhs.size(); i++) { + lhs[i] = static_cast(tolower(lhs[i])); + } return (rhs.size() <= lhs.size()) && (lhs.substr(0, rhs.size()) == rhs); } From 05c577bd3d0b6c8f532ad90ec23ca9c85db43c9c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 22 Jul 2021 21:19:35 +0200 Subject: [PATCH 04/24] Filter out non-image files from the launcher collection (closes #1693) --- .../ext/launcher/src/launcherwindow.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp index a7ebe492c3..460313f531 100644 --- a/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp +++ b/apps/OpenSpace/ext/launcher/src/launcherwindow.cpp @@ -312,8 +312,24 @@ void LauncherWindow::setBackgroundImage(const std::string& syncPath) { std::mt19937 g(rd()); std::shuffle(files.begin(), files.end(), g); // We know there has to be at least one folder, so it's fine to just pick the first - std::string image = files.front(); - _backgroundImage->setPixmap(QPixmap(QString::fromStdString(image))); + while (!files.empty()) { + std::string p = files.front(); + if (std::filesystem::path(p).extension() == ".png") { + // If the top path starts with the png extension, we have found our candidate + break; + } + else { + // There shouldn't be any non-png images in here, but you never know. So we + // just remove non-image files here + files.erase(files.begin()); + } + } + + // There better be at least one file left, but just in in case + if (!files.empty()) { + std::string image = files.front(); + _backgroundImage->setPixmap(QPixmap(QString::fromStdString(image))); + } } void LauncherWindow::populateProfilesList(std::string preset) { From d38968a5ad1c820a45e84ce11d7b0939af1f9064 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 23 Jul 2021 11:50:50 +0200 Subject: [PATCH 05/24] Don't accidentally delete someone elses VBO and VAO (closes #1694) --- .../rendering/atmospheredeferredcaster.cpp | 107 ++++++++---------- .../rendering/atmospheredeferredcaster.h | 20 ++-- 2 files changed, 56 insertions(+), 71 deletions(-) diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 90b8cb0f83..cafe67ef2d 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -83,28 +83,6 @@ namespace { constexpr const float ATM_EPS = 2000.f; constexpr const float KM_TO_M = 1000.f; - void createRenderQuad(GLuint* vao, GLuint* vbo) { - glGenVertexArrays(1, vao); - glBindVertexArray(*vao); - glGenBuffers(1, vbo); - glBindBuffer(GL_ARRAY_BUFFER, *vbo); - - const GLfloat VertexData[] = { - // x y z - -1.f, -1.f, - 1.f, 1.f, - -1.f, 1.f, - -1.f, -1.f, - 1.f, -1.f, - 1.f, 1.f, - }; - - glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glBindVertexArray(0); - } - template void saveTextureFile(const std::filesystem::path& fileName, const glm::ivec2& size) { std::ofstream ppmFile(fileName); @@ -190,12 +168,6 @@ namespace { return true; } - void renderQuadForCalc(GLuint vao) { - glBindVertexArray(vao); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - } - GLuint createTexture(const glm::ivec2& size, std::string_view name) { GLuint t; glGenTextures(1, &t); @@ -552,7 +524,7 @@ void AtmosphereDeferredcaster::setHardShadows(bool enabled) { _hardShadowsEnabled = enabled; } -void AtmosphereDeferredcaster::calculateTransmittance(GLuint vao) { +void AtmosphereDeferredcaster::calculateTransmittance() { glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -580,14 +552,14 @@ void AtmosphereDeferredcaster::calculateTransmittance(GLuint vao) { constexpr const float Black[] = { 0.f, 0.f, 0.f, 0.f }; glClearBufferfv(GL_COLOR, 0, Black); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); if (_saveCalculationTextures) { saveTextureFile("transmittance_texture.ppm", _transmittanceTableSize); } program->deactivate(); } -GLuint AtmosphereDeferredcaster::calculateDeltaE(GLuint vao) { +GLuint AtmosphereDeferredcaster::calculateDeltaE() { GLuint deltaE = createTexture(_deltaETableSize, "DeltaE"); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); @@ -606,7 +578,7 @@ GLuint AtmosphereDeferredcaster::calculateDeltaE(GLuint vao) { program->setUniform("Rt", _atmosphereRadius); program->setUniform("OTHER_TEXTURES", _deltaETableSize); glClear(GL_COLOR_BUFFER_BIT); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); if (_saveCalculationTextures) { saveTextureFile("deltaE_table_texture.ppm", _deltaETableSize); } @@ -614,7 +586,7 @@ GLuint AtmosphereDeferredcaster::calculateDeltaE(GLuint vao) { return deltaE; } -std::pair AtmosphereDeferredcaster::calculateDeltaS(GLuint vao) { +std::pair AtmosphereDeferredcaster::calculateDeltaS() { GLuint deltaSRayleigh = createTexture(_textureSize, "DeltaS Rayleigh", 3); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); GLuint deltaSMie = createTexture(_textureSize, "DeltaS Mie", 3); @@ -649,7 +621,7 @@ std::pair AtmosphereDeferredcaster::calculateDeltaS(GLuint vao) for (int layer = 0; layer < _rSamples; ++layer) { program->setUniform("layer", layer); step3DTexture(*program, layer); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); } if (_saveCalculationTextures) { saveTextureFile("deltaS_rayleigh_texture.ppm", glm::ivec2(_textureSize)); @@ -666,7 +638,7 @@ std::pair AtmosphereDeferredcaster::calculateDeltaS(GLuint vao) return { deltaSRayleigh, deltaSMie }; } -void AtmosphereDeferredcaster::calculateIrradiance(GLuint quadCalcVao) { +void AtmosphereDeferredcaster::calculateIrradiance() { glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -684,14 +656,14 @@ void AtmosphereDeferredcaster::calculateIrradiance(GLuint quadCalcVao) { ); program->activate(); glClear(GL_COLOR_BUFFER_BIT); - renderQuadForCalc(quadCalcVao); + glDrawArrays(GL_TRIANGLES, 0, 6); if (_saveCalculationTextures) { saveTextureFile("irradiance_texture.ppm", _deltaETableSize); } program->deactivate(); } -void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, GLuint deltaSRayleigh, +void AtmosphereDeferredcaster::calculateInscattering(GLuint deltaSRayleigh, GLuint deltaSMie) { glFramebufferTexture( @@ -727,7 +699,7 @@ void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, GLuint deltaSRa glClear(GL_COLOR_BUFFER_BIT); for (int layer = 0; layer < _rSamples; ++layer) { program->setUniform("layer", layer); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); } if (_saveCalculationTextures) { saveTextureFile("S_texture.ppm", glm::ivec2(_textureSize)); @@ -735,7 +707,7 @@ void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, GLuint deltaSRa program->deactivate(); } -void AtmosphereDeferredcaster::calculateDeltaJ(GLuint vao, int scatteringOrder, +void AtmosphereDeferredcaster::calculateDeltaJ(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaJ, GLuint deltaE, GLuint deltaSRayleigh, GLuint deltaSMie) @@ -780,7 +752,7 @@ void AtmosphereDeferredcaster::calculateDeltaJ(GLuint vao, int scatteringOrder, for (int layer = 0; layer < _rSamples; ++layer) { program.setUniform("layer", layer); step3DTexture(program, layer); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); } if (_saveCalculationTextures) { saveTextureFile( @@ -791,7 +763,7 @@ void AtmosphereDeferredcaster::calculateDeltaJ(GLuint vao, int scatteringOrder, program.deactivate(); } -void AtmosphereDeferredcaster::calculateDeltaE(GLuint vao, int scatteringOrder, +void AtmosphereDeferredcaster::calculateDeltaE(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaE, GLuint deltaSRayleigh, GLuint deltaSMie) @@ -819,7 +791,7 @@ void AtmosphereDeferredcaster::calculateDeltaE(GLuint vao, int scatteringOrder, program.setUniform("SAMPLES_NU", _nuSamples); program.setUniform("SAMPLES_MU", _muSamples); program.setUniform("SAMPLES_R", _rSamples); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); if (_saveCalculationTextures) { saveTextureFile( fmt::format("deltaE_texture-scattering_order-{}.ppm", scatteringOrder), @@ -829,7 +801,7 @@ void AtmosphereDeferredcaster::calculateDeltaE(GLuint vao, int scatteringOrder, program.deactivate(); } -void AtmosphereDeferredcaster::calculateDeltaS(GLuint vao, int scatteringOrder, +void AtmosphereDeferredcaster::calculateDeltaS(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh, GLuint deltaJ) { @@ -856,7 +828,7 @@ void AtmosphereDeferredcaster::calculateDeltaS(GLuint vao, int scatteringOrder, for (int layer = 0; layer < _rSamples; ++layer) { program.setUniform("layer", layer); step3DTexture(program, layer); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); } if (_saveCalculationTextures) { saveTextureFile( @@ -867,7 +839,7 @@ void AtmosphereDeferredcaster::calculateDeltaS(GLuint vao, int scatteringOrder, program.deactivate(); } -void AtmosphereDeferredcaster::calculateIrradiance(GLuint vao, int scatteringOrder, +void AtmosphereDeferredcaster::calculateIrradiance(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaE) { @@ -886,7 +858,7 @@ void AtmosphereDeferredcaster::calculateIrradiance(GLuint vao, int scatteringOrd program.setUniform("deltaETexture", unit); program.setUniform("OTHER_TEXTURES", _deltaETableSize); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); if (_saveCalculationTextures) { saveTextureFile( fmt::format("irradianceTable_order-{}.ppm", scatteringOrder), @@ -896,7 +868,7 @@ void AtmosphereDeferredcaster::calculateIrradiance(GLuint vao, int scatteringOrd program.deactivate(); } -void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, int scatteringOrder, +void AtmosphereDeferredcaster::calculateInscattering(int scatteringOrder, ghoul::opengl::ProgramObject& prg, GLuint deltaSRayleigh) @@ -920,7 +892,7 @@ void AtmosphereDeferredcaster::calculateInscattering(GLuint vao, int scatteringO prg.setUniform("SAMPLES_R", _rSamples); for (int layer = 0; layer < _rSamples; ++layer) { prg.setUniform("layer", layer); - renderQuadForCalc(vao); + glDrawArrays(GL_TRIANGLES, 0, 6); } if (_saveCalculationTextures) { saveTextureFile( @@ -979,27 +951,44 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { // Prepare for rendering/calculations GLuint quadVao; + glGenVertexArrays(1, &quadVao); + glBindVertexArray(quadVao); GLuint quadVbo; - createRenderQuad(&quadVao, &quadVbo); + glGenBuffers(1, &quadVbo); + glBindBuffer(GL_ARRAY_BUFFER, quadVbo); + + const GLfloat VertexData[] = { + // x y z + -1.f, -1.f, + 1.f, 1.f, + -1.f, 1.f, + -1.f, -1.f, + 1.f, -1.f, + 1.f, 1.f, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); // Execute Calculations LDEBUG("Starting precalculations for scattering effects"); glDisable(GL_BLEND); // See Precomputed Atmosphere Scattering from Bruneton et al. paper, algorithm 4.1: - calculateTransmittance(quadVao); + calculateTransmittance(); // line 2 in algorithm 4.1 - GLuint deltaETable = calculateDeltaE(quadVao); + GLuint deltaETable = calculateDeltaE(); // line 3 in algorithm 4.1 - auto [deltaSRayleighTable, deltaSMieTable] = calculateDeltaS(quadVao); + auto [deltaSRayleighTable, deltaSMieTable] = calculateDeltaS(); // line 4 in algorithm 4.1 - calculateIrradiance(quadVao); + calculateIrradiance(); // line 5 in algorithm 4.1 - calculateInscattering(quadVao, deltaSRayleighTable, deltaSMieTable); + calculateInscattering(deltaSRayleighTable, deltaSMieTable); GLuint deltaJTable = createTexture(_textureSize, "DeltaJ", 3); @@ -1007,7 +996,6 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { for (int scatteringOrder = 2; scatteringOrder <= 4; ++scatteringOrder) { // line 7 in algorithm 4.1 calculateDeltaJ( - quadVao, scatteringOrder, *deltaJProgram, deltaJTable, @@ -1018,7 +1006,6 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { // line 8 in algorithm 4.1 calculateDeltaE( - quadVao, scatteringOrder, *irradianceSupTermsProgram, deltaETable, @@ -1028,7 +1015,6 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { // line 9 in algorithm 4.1 calculateDeltaS( - quadVao, scatteringOrder, *inScatteringSupTermsProgram, deltaSRayleighTable, @@ -1041,7 +1027,6 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { // line 10 in algorithm 4.1 calculateIrradiance( - quadVao, scatteringOrder, *irradianceFinalProgram, deltaETable @@ -1049,7 +1034,6 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { // line 11 in algorithm 4.1 calculateInscattering( - quadVao, scatteringOrder, *deltaSSupTermsProgram, deltaSRayleighTable @@ -1069,9 +1053,10 @@ void AtmosphereDeferredcaster::calculateAtmosphereParameters() { // Restores system state glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); global::renderEngine->openglStateCache().setViewportState(viewport); - glDeleteBuffers(1, &quadVao); - glDeleteVertexArrays(1, &quadVbo); + glDeleteBuffers(1, &quadVbo); + glDeleteVertexArrays(1, &quadVao); glDeleteFramebuffers(1, &calcFBO); + glBindVertexArray(0); LDEBUG("Ended precalculations for Atmosphere effects"); } diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.h b/modules/atmosphere/rendering/atmospheredeferredcaster.h index a117882f8e..6836352c0a 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.h +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.h @@ -93,22 +93,22 @@ public: private: void step3DTexture(ghoul::opengl::ProgramObject& prg, int layer); - void calculateTransmittance(GLuint vao); - GLuint calculateDeltaE(GLuint vao); - std::pair calculateDeltaS(GLuint vao); - void calculateIrradiance(GLuint vao); - void calculateInscattering(GLuint vao, GLuint deltaSRayleigh, GLuint deltaSMie); - void calculateDeltaJ(GLuint vao, int scatteringOrder, + void calculateTransmittance(); + GLuint calculateDeltaE(); + std::pair calculateDeltaS(); + void calculateIrradiance(); + void calculateInscattering(GLuint deltaSRayleigh, GLuint deltaSMie); + void calculateDeltaJ(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaJ, GLuint deltaE, GLuint deltaSRayleigh, GLuint deltaSMie); - void calculateDeltaE(GLuint vao, int scatteringOrder, + void calculateDeltaE(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaE, GLuint deltaSRayleigh, GLuint deltaSMie); - void calculateDeltaS(GLuint vao, int scatteringOrder, + void calculateDeltaS(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh, GLuint deltaJ); - void calculateIrradiance(GLuint vao, int scatteringOrder, + void calculateIrradiance(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaE); - void calculateInscattering(GLuint vao, int scatteringOrder, + void calculateInscattering(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh); From 817621617eda64ef22e968cc6f6f7fadc3d7efb0 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 23 Jul 2021 14:17:16 +0200 Subject: [PATCH 06/24] Check for nan in camera setting (closes #1686), add tracy zones to atmosphere rendering --- .../rendering/atmospheredeferredcaster.cpp | 22 ++++++++++++++++++ src/util/camera.cpp | 23 ++++++++++--------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index cafe67ef2d..3bc7f14edc 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -525,6 +525,8 @@ void AtmosphereDeferredcaster::setHardShadows(bool enabled) { } void AtmosphereDeferredcaster::calculateTransmittance() { + ZoneScoped + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -560,6 +562,8 @@ void AtmosphereDeferredcaster::calculateTransmittance() { } GLuint AtmosphereDeferredcaster::calculateDeltaE() { + ZoneScoped + GLuint deltaE = createTexture(_deltaETableSize, "DeltaE"); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); @@ -587,6 +591,8 @@ GLuint AtmosphereDeferredcaster::calculateDeltaE() { } std::pair AtmosphereDeferredcaster::calculateDeltaS() { + ZoneScoped + GLuint deltaSRayleigh = createTexture(_textureSize, "DeltaS Rayleigh", 3); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); GLuint deltaSMie = createTexture(_textureSize, "DeltaS Mie", 3); @@ -639,6 +645,8 @@ std::pair AtmosphereDeferredcaster::calculateDeltaS() { } void AtmosphereDeferredcaster::calculateIrradiance() { + ZoneScoped + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -666,6 +674,8 @@ void AtmosphereDeferredcaster::calculateIrradiance() { void AtmosphereDeferredcaster::calculateInscattering(GLuint deltaSRayleigh, GLuint deltaSMie) { + ZoneScoped + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -712,6 +722,8 @@ void AtmosphereDeferredcaster::calculateDeltaJ(int scatteringOrder, GLuint deltaJ, GLuint deltaE, GLuint deltaSRayleigh, GLuint deltaSMie) { + ZoneScoped + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaJ, 0); glViewport(0, 0, _textureSize.x, _textureSize.y); program.activate(); @@ -768,6 +780,8 @@ void AtmosphereDeferredcaster::calculateDeltaE(int scatteringOrder, GLuint deltaE, GLuint deltaSRayleigh, GLuint deltaSMie) { + ZoneScoped + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); program.activate(); @@ -805,6 +819,8 @@ void AtmosphereDeferredcaster::calculateDeltaS(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaSRayleigh, GLuint deltaJ) { + ZoneScoped + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); glViewport(0, 0, _textureSize.x, _textureSize.y); program.activate(); @@ -843,6 +859,8 @@ void AtmosphereDeferredcaster::calculateIrradiance(int scatteringOrder, ghoul::opengl::ProgramObject& program, GLuint deltaE) { + ZoneScoped + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -873,6 +891,8 @@ void AtmosphereDeferredcaster::calculateInscattering(int scatteringOrder, GLuint deltaSRayleigh) { + ZoneScoped + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -904,6 +924,8 @@ void AtmosphereDeferredcaster::calculateInscattering(int scatteringOrder, } void AtmosphereDeferredcaster::calculateAtmosphereParameters() { + ZoneScoped + using ProgramObject = ghoul::opengl::ProgramObject; std::unique_ptr deltaJProgram = ProgramObject::Build( "DeltaJ Program", diff --git a/src/util/camera.cpp b/src/util/camera.cpp index 0cd86da56a..4091bdb45b 100644 --- a/src/util/camera.cpp +++ b/src/util/camera.cpp @@ -42,14 +42,15 @@ Camera::Camera(const Camera& o) {} void Camera::setPositionVec3(glm::dvec3 pos) { - std::lock_guard _lock(_mutex); - _position = std::move(pos); - - _cachedCombinedViewMatrix.isDirty = true; + if (!glm::any(glm::isnan(pos))) { + std::lock_guard _lock(_mutex); + _position = std::move(pos); + _cachedCombinedViewMatrix.isDirty = true; + } } void Camera::setRotation(glm::dquat rotation) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _rotation = std::move(rotation); _cachedViewDirection.isDirty = true; _cachedLookupVector.isDirty = true; @@ -58,14 +59,14 @@ void Camera::setRotation(glm::dquat rotation) { } void Camera::setScaling(float scaling) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _scaling = scaling; _cachedViewScaleMatrix.isDirty = true; _cachedCombinedViewMatrix.isDirty = true; } void Camera::setMaxFov(float fov) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _maxFov = fov; _cachedSinMaxFov.isDirty = true; } @@ -75,7 +76,7 @@ void Camera::setParent(SceneGraphNode* parent) { } void Camera::rotate(glm::dquat rotation) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _rotation = std::move(rotation) * static_cast(_rotation); _cachedViewDirection.isDirty = true; @@ -224,20 +225,20 @@ Camera::SgctInternal::SgctInternal(const SgctInternal& o) {} void Camera::SgctInternal::setSceneMatrix(glm::mat4 sceneMatrix) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _sceneMatrix = std::move(sceneMatrix); } void Camera::SgctInternal::setViewMatrix(glm::mat4 viewMatrix) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _viewMatrix = std::move(viewMatrix); _cachedViewProjectionMatrix.isDirty = true; } void Camera::SgctInternal::setProjectionMatrix(glm::mat4 projectionMatrix) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _projectionMatrix = std::move(projectionMatrix); _cachedViewProjectionMatrix.isDirty = true; From 3ae1028a854eadec4a0447c72d6b9cbe406be4c2 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 26 Jul 2021 11:03:06 +0200 Subject: [PATCH 07/24] Print the identifier of the offending scene graph node when the specification fails --- src/scene/scene_lua.inl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index cb1d33fd52..8c231f8efc 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -654,7 +654,12 @@ int addSceneGraphNode(lua_State* L) { global::renderEngine->scene()->initializeNode(node); } catch (const documentation::SpecificationError& e) { - LERRORC("Scene", ghoul::to_string(e.result)); + std::string cat = + d.hasValue("Identifier") ? + d.value("Identifier") : + "Scene"; + LERRORC(cat, ghoul::to_string(e.result)); + return ghoul::lua::luaError( L, fmt::format("Error loading scene graph node: {}", e.what()) From e5b88ead92c07a8948c132922a002e2d2cc76acd Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 26 Jul 2021 11:52:43 +0200 Subject: [PATCH 08/24] Make it possible to pass any number of arguments to the print functions (#1635) --- src/scripting/scriptengine_lua.inl | 61 ++++++++++++++++-------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/scripting/scriptengine_lua.inl b/src/scripting/scriptengine_lua.inl index 8d550bbeca..a8b0fec9e2 100644 --- a/src/scripting/scriptengine_lua.inl +++ b/src/scripting/scriptengine_lua.inl @@ -30,37 +30,42 @@ namespace openspace::luascriptfunctions { int printInternal(ghoul::logging::LogLevel level, lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::printInternal"); - using ghoul::lua::luaTypeToString; - const int type = lua_type(L, 1); - switch (type) { - case LUA_TNONE: - case LUA_TLIGHTUSERDATA: - case LUA_TTABLE: - case LUA_TFUNCTION: - case LUA_TUSERDATA: - case LUA_TTHREAD: - log( - level, - "print", - fmt::format("Function parameter was of type '{}'", luaTypeToString(type)) - ); - break; - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - log(level, "print", std::to_string(ghoul::lua::value(L, 1))); - break; - case LUA_TNUMBER: - log(level, "print", std::to_string(ghoul::lua::value(L, 1))); - break; - case LUA_TSTRING: - log(level, "print", ghoul::lua::value(L, 1)); - break; + const int nArguments = lua_gettop(L); + for (int i = 1; i <= nArguments; i++) { + const int type = lua_type(L, i); + switch (type) { + case LUA_TNONE: + case LUA_TLIGHTUSERDATA: + case LUA_TTABLE: + case LUA_TFUNCTION: + case LUA_TUSERDATA: + case LUA_TTHREAD: + log( + level, + "print", + fmt::format( + "Function parameter was of type '{}'", luaTypeToString(type) + ) + ); + break; + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + log(level, "print", std::to_string(ghoul::lua::value(L, i))); + break; + case LUA_TNUMBER: + log(level, "print", std::to_string(ghoul::lua::value(L, i))); + break; + case LUA_TSTRING: + log(level, "print", ghoul::lua::value(L, i)); + break; + } } - lua_pop(L, 1); + + + lua_pop(L, nArguments); ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; From 7abc964b0ec568ec779218f695051f3f9416e5e1 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 26 Jul 2021 13:35:20 +0200 Subject: [PATCH 09/24] Add the ability to read files from disk (closes #1636) --- src/scripting/scriptengine.cpp | 7 +++++++ src/scripting/scriptengine_lua.inl | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/scripting/scriptengine.cpp b/src/scripting/scriptengine.cpp index 3e6941c354..d34b2a1afe 100644 --- a/src/scripting/scriptengine.cpp +++ b/src/scripting/scriptengine.cpp @@ -423,6 +423,13 @@ void ScriptEngine::addBaseLibrary() { "string", "Checks whether the provided file exists." }, + { + "readFile", + &luascriptfunctions::readFile, + {}, + "string", + "Reads a file from disk and return its contents" + }, { "directoryExists", &luascriptfunctions::directoryExists, diff --git a/src/scripting/scriptengine_lua.inl b/src/scripting/scriptengine_lua.inl index a8b0fec9e2..f43ae6e365 100644 --- a/src/scripting/scriptengine_lua.inl +++ b/src/scripting/scriptengine_lua.inl @@ -202,6 +202,32 @@ int fileExists(lua_State* L) { return 1; } +/** + * \ingroup LuaScripts + * readFile(string): + * Reads a file from disk and return its contents + */ +int readFile(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::readFile"); + + const std::string& file = ghoul::lua::value( + L, + 1, + ghoul::lua::PopValue::Yes + ); + std::filesystem::path p = absPath(file); + if (!std::filesystem::is_regular_file(p)) { + return ghoul::lua::luaError(L, fmt::format("Could not open file {}", file)); + } + + std::ifstream f(p); + std::stringstream buffer; + buffer << f.rdbuf(); + + ghoul::lua::push(L, buffer.str()); + return 1; +} + /** * \ingroup LuaScripts * directoryExists(string): From eb1de6fbd2be53899a9f4bd4e29c44280237808c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 26 Jul 2021 13:35:31 +0200 Subject: [PATCH 10/24] Update Ghoul repository --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 2ffa7b7f7a..323d11d2ee 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 2ffa7b7f7a9582f191e51d4f7b030ea764f86a4c +Subproject commit 323d11d2ee21c061d319820b6257cbfe48e53d5b From 043fb9c4e95f5f12aecd959339d880122403e234 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 26 Jul 2021 15:21:06 +0200 Subject: [PATCH 11/24] Prevent the failure of font loading from keeping file handles open and breaking everything else (#1627) --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 323d11d2ee..79b09090ae 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 323d11d2ee21c061d319820b6257cbfe48e53d5b +Subproject commit 79b09090ae31f960ead48870a948af348323a287 From a13f94da210f83681db9ed1eb45f97632caaff1f Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 27 Jul 2021 11:26:41 +0200 Subject: [PATCH 12/24] Add ability to print all types of information in the printInfo/... functions (closes #1635) --- ext/ghoul | 2 +- src/scripting/scriptengine_lua.inl | 33 +----------------------------- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 79b09090ae..0282811937 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 79b09090ae31f960ead48870a948af348323a287 +Subproject commit 0282811937bc5102ac4dad3a0b53bf72c28aac77 diff --git a/src/scripting/scriptengine_lua.inl b/src/scripting/scriptengine_lua.inl index f43ae6e365..1cdc5882f9 100644 --- a/src/scripting/scriptengine_lua.inl +++ b/src/scripting/scriptengine_lua.inl @@ -30,41 +30,10 @@ namespace openspace::luascriptfunctions { int printInternal(ghoul::logging::LogLevel level, lua_State* L) { - using ghoul::lua::luaTypeToString; - const int nArguments = lua_gettop(L); for (int i = 1; i <= nArguments; i++) { - const int type = lua_type(L, i); - switch (type) { - case LUA_TNONE: - case LUA_TLIGHTUSERDATA: - case LUA_TTABLE: - case LUA_TFUNCTION: - case LUA_TUSERDATA: - case LUA_TTHREAD: - log( - level, - "print", - fmt::format( - "Function parameter was of type '{}'", luaTypeToString(type) - ) - ); - break; - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - log(level, "print", std::to_string(ghoul::lua::value(L, i))); - break; - case LUA_TNUMBER: - log(level, "print", std::to_string(ghoul::lua::value(L, i))); - break; - case LUA_TSTRING: - log(level, "print", ghoul::lua::value(L, i)); - break; - } + log(level, "print", ghoul::lua::luaValueToString(L, i)); } - - lua_pop(L, nArguments); ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); From 5f139b81445b4eac84de20d4f20d8b3a46f7bb92 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 27 Jul 2021 14:14:19 +0200 Subject: [PATCH 13/24] Tune the look of the asset dialog --- .../ext/launcher/resources/qss/launcher.qss | 1 + .../ext/launcher/src/profile/assetsdialog.cpp | 14 ++++++-------- ext/ghoul | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss b/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss index 032ac15ccc..1b31494beb 100644 --- a/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss +++ b/apps/OpenSpace/ext/launcher/resources/qss/launcher.qss @@ -115,6 +115,7 @@ PropertiesDialog QListWidget { */ AssetsDialog QTreeView { min-width: 40em; + min-height: 40em; } /* diff --git a/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp index c2573cc381..a89b0c3ba3 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/assetsdialog.cpp @@ -129,10 +129,7 @@ AssetsDialog::AssetsDialog(openspace::Profile& profile, const std::string& asset { setWindowTitle("Assets"); _assetTreeModel.importModelData(assetBasePath, userAssetBasePath); - createWidgets(); -} -void AssetsDialog::createWidgets() { QBoxLayout* layout = new QVBoxLayout(this); { QLabel* heading = new QLabel("Select assets from /data/assets"); @@ -173,18 +170,19 @@ void AssetsDialog::createWidgets() { nRows, _assetTreeModel.index(-1, 0) ); - layout->addWidget(_assetTree); + layout->addWidget(_assetTree, 4); } { + QWidget* box = new QWidget; + QBoxLayout* boxLayout = new QVBoxLayout(box); QLabel* summaryHeading = new QLabel("Selection summary"); summaryHeading->setObjectName("heading"); - layout->addWidget(summaryHeading); - } - { + boxLayout->addWidget(summaryHeading); _summary = new QTextEdit; _summary->setReadOnly(true); _summary->setText(createTextSummary()); - layout->addWidget(_summary); + boxLayout->addWidget(_summary); + layout->addWidget(box, 1); } layout->addWidget(new Line); diff --git a/ext/ghoul b/ext/ghoul index 0282811937..0a7f66f9a1 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 0282811937bc5102ac4dad3a0b53bf72c28aac77 +Subproject commit 0a7f66f9a1cb050b9d6e803257ab1320259fa53d From 3e7f0d24ada846192035e31f86b9080859df8267 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 27 Jul 2021 16:35:41 +0200 Subject: [PATCH 14/24] Add support for DMS format support in the DashboardItemGlobeLocation (closes #1632) --- .../src/dashboarditemglobelocation.cpp | 121 +++++++++++++++--- .../src/dashboarditemglobelocation.h | 7 + src/util/coordinateconversion.cpp | 6 +- 3 files changed, 112 insertions(+), 22 deletions(-) diff --git a/modules/globebrowsing/src/dashboarditemglobelocation.cpp b/modules/globebrowsing/src/dashboarditemglobelocation.cpp index 0369043f4f..650e8557a0 100644 --- a/modules/globebrowsing/src/dashboarditemglobelocation.cpp +++ b/modules/globebrowsing/src/dashboarditemglobelocation.cpp @@ -39,6 +39,8 @@ #include #include +#pragma optimize ("", off) + namespace { constexpr const char* KeyFontMono = "Mono"; constexpr const float DefaultFontSize = 10.f; @@ -56,6 +58,12 @@ namespace { "This value determines the size of the font that is used to render the date." }; + constexpr openspace::properties::Property::PropertyInfo DisplayFormatInfo = { + "DisplayFormat", + "Display Format", + "Choosing the format in which the camera location is displayed" + }; + constexpr openspace::properties::Property::PropertyInfo SignificantDigitsInfo = { "SignificantDigits", "Significant Digits", @@ -69,6 +77,14 @@ namespace { // [[codegen::verbatim(FontSizeInfo.description)]] std::optional fontSize; + enum class DisplayFormat { + DecimalDegrees, + DegreeMinuteSeconds + }; + + // [[codegen::verbatim(DisplayFormatInfo.description)]] + std::optional displayFormat; + // [[codegen::verbatim(SignificantDigitsInfo.description)]] std::optional significantDigits; }; @@ -86,6 +102,7 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation( : DashboardItem(dictionary) , _fontName(FontNameInfo, KeyFontMono) , _fontSize(FontSizeInfo, DefaultFontSize, 10.f, 144.f, 1.f) + , _displayFormat(DisplayFormatInfo) , _significantDigits(SignificantDigitsInfo, 4, 1, 12) , _font(global::fontManager->font(KeyFontMono, 10)) { @@ -104,20 +121,54 @@ DashboardItemGlobeLocation::DashboardItemGlobeLocation( addProperty(_fontSize); auto updateFormatString = [this]() { - using namespace fmt::literals; - - _formatString = fmt::format( - "Position: {{:03.{0}f}}{{}}, {{:03.{0}f}}{{}} Altitude: {{:03.{0}f}} {{}}", - _significantDigits.value() - ); + switch (_displayFormat.value()) { + case static_cast(DisplayFormat::DecimalDegrees): + _formatString = fmt::format( + "Position: {{:03.{0}f}}, {{:03.{0}f}} " + "Altitude: {{:03.{0}f}} {{}}", + _significantDigits.value() + ); + break; + case static_cast(DisplayFormat::DegreeMinuteSeconds): + _formatString = fmt::format( + "Position: {{}}d {{}}' {{:03.{0}f}}\" {{}}, " + "{{}}d {{}}' {{:03.{0}f}}\" {{}} " + "Altitude: {{:03.{0}f}} {{}}", + _significantDigits.value() + ); + break; + } }; + + _displayFormat.addOptions({ + { static_cast(DisplayFormat::DecimalDegrees), "Decimal Degrees" }, + { static_cast(DisplayFormat::DegreeMinuteSeconds), "Degree Minute Seconds" } + }); + _displayFormat.onChange(updateFormatString); + addProperty(_displayFormat); + + if (p.displayFormat.has_value()) { + switch (*p.displayFormat) { + case Parameters::DisplayFormat::DecimalDegrees: + _displayFormat = static_cast(DisplayFormat::DecimalDegrees); + break; + case Parameters::DisplayFormat::DegreeMinuteSeconds: + _displayFormat = static_cast(DisplayFormat::DegreeMinuteSeconds); + break; + } + } + else { + _displayFormat = static_cast(DisplayFormat::DecimalDegrees); + } + + _significantDigits = p.significantDigits.value_or(_significantDigits); _significantDigits.onChange(updateFormatString); addProperty(_significantDigits); - updateFormatString(); _font = global::fontManager->font(_fontName, _fontSize); _buffer.resize(128); + updateFormatString(); } void DashboardItemGlobeLocation::render(glm::vec2& penPosition) { @@ -149,12 +200,6 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) { double lat = glm::degrees(geo2.lat); double lon = glm::degrees(geo2.lon); - bool isNorth = lat > 0.0; - lat = std::abs(lat); - - bool isEast = lon > 0.0; - lon = std::abs(lon); - double altitude = glm::length( cameraPositionModelSpace - posHandle.centerToReferenceSurface ); @@ -168,13 +213,49 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) { std::pair dist = simplifyDistance(altitude); std::fill(_buffer.begin(), _buffer.end(), char(0)); - char* end = fmt::format_to( - _buffer.data(), - _formatString.c_str(), - lat, isNorth ? "N" : "S", - lon, isEast ? "E" : "W", - dist.first, dist.second - ); + char* end = nullptr; + switch (_displayFormat.value()) { + case static_cast(DisplayFormat::DecimalDegrees): + { + end = fmt::format_to( + _buffer.data(), + _formatString, lat, lon, dist.first, dist.second + ); + break; + } + case static_cast(DisplayFormat::DegreeMinuteSeconds): + { + const bool isNorth = lat > 0.0; + lat = std::abs(lat); + + const bool isEast = lon > 0.0; + lon = std::abs(lon); + + const float latDeg = std::trunc(lat); + const float latDegRemainder = lat - latDeg; + const float latMin = std::trunc(latDegRemainder * 60.f); + const float latMinRemainder = latDegRemainder * 60.f - latMin; + const float latSec = latMinRemainder * 60.f; + + const float lonDeg = std::trunc(lon); + const float lonDegRemainder = lon - lonDeg; + const float lonMin = std::trunc(lonDegRemainder * 60.f); + const float lonMinRemainder = lonDegRemainder * 60.f - lonMin; + const float lonSec = lonMinRemainder * 60.f; + + + end = fmt::format_to( + _buffer.data(), + _formatString, + latDeg, latMin, latSec, isNorth ? "N" : "S", + lonDeg, lonMin, lonSec, isEast ? "E" : "W", + dist.first, dist.second + ); + + break; + } + } + std::string_view text = std::string_view(_buffer.data(), end - _buffer.data()); RenderFont(*_font, penPosition, text); diff --git a/modules/globebrowsing/src/dashboarditemglobelocation.h b/modules/globebrowsing/src/dashboarditemglobelocation.h index 13400ead72..3792732b04 100644 --- a/modules/globebrowsing/src/dashboarditemglobelocation.h +++ b/modules/globebrowsing/src/dashboarditemglobelocation.h @@ -27,6 +27,7 @@ #include +#include #include #include #include @@ -49,9 +50,15 @@ public: static documentation::Documentation Documentation(); private: + enum class DisplayFormat { + DecimalDegrees = 0, + DegreeMinuteSeconds + }; + properties::StringProperty _fontName; properties::FloatProperty _fontSize; + properties::OptionProperty _displayFormat; properties::IntProperty _significantDigits; std::shared_ptr _font; diff --git a/src/util/coordinateconversion.cpp b/src/util/coordinateconversion.cpp index cc5e28aae4..daaa9a34ea 100644 --- a/src/util/coordinateconversion.cpp +++ b/src/util/coordinateconversion.cpp @@ -32,9 +32,11 @@ namespace { constexpr const char* _loggerCat = "Coordinateconversion"; // J2000 Galactic reference frame - constexpr double A0 = glm::radians(192.8595); // Equatorial coordinates of the Galactic north pole + // Equatorial coordinates of the Galactic north pole + constexpr double A0 = glm::radians(192.8595); constexpr double D0 = glm::radians(27.1284); - constexpr double L0 = glm::radians(122.9320); // Galactic longitude of the equatorial north pole + // Galactic longitude of the equatorial north pole + constexpr double L0 = glm::radians(122.9320); void parseString(const std::string& str, int& hoursOrDegrees, int& minutes, double& seconds) From 6628b9f0b4011ab3f6c871cf0bc808e08183e9ab Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 28 Jul 2021 14:04:31 +0200 Subject: [PATCH 15/24] Parent the Gaia trail and model to the Earth Center to match the Horizons file (closes #1573); Fix mistake that caused the Gaia spacecraft to not point away from the Sun anymore --- .../solarsystem/missions/gaia/gaia.asset | 2 +- .../solarsystem/missions/gaia/trail.asset | 4 ++-- .../missions/gaia/transforms.asset | 2 +- .../scene/solarsystem/sun/transforms.asset | 20 ++++++++++++++++++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/data/assets/scene/solarsystem/missions/gaia/gaia.asset b/data/assets/scene/solarsystem/missions/gaia/gaia.asset index 2268aa01bd..638ad5833f 100644 --- a/data/assets/scene/solarsystem/missions/gaia/gaia.asset +++ b/data/assets/scene/solarsystem/missions/gaia/gaia.asset @@ -20,7 +20,7 @@ local Gaia = { XAxis = { 1.0, 0.0, 0.0 }, XAxisOrthogonal = true, YAxis = "Sun", - YAxisInverted = true + YAxisInvert = true }, Scale = { Type = "StaticScale", diff --git a/data/assets/scene/solarsystem/missions/gaia/trail.asset b/data/assets/scene/solarsystem/missions/gaia/trail.asset index ee00ea2a6c..64b8dfd8de 100644 --- a/data/assets/scene/solarsystem/missions/gaia/trail.asset +++ b/data/assets/scene/solarsystem/missions/gaia/trail.asset @@ -11,7 +11,7 @@ local trail = asset.syncedResource({ local GaiaTrail = { Identifier = "GaiaTrail", - Parent = earthTransforms.EarthBarycenter.Identifier, + Parent = earthTransforms.EarthCenter.Identifier, Renderable = { Type = "RenderableTrailTrajectory", Translation = { @@ -36,7 +36,7 @@ local GaiaTrail = { local GaiaTrailEclip = { Identifier = "GaiaTrail_Eclip", - Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Parent = sunTransforms.SunCenter.Identifier, Renderable = { Type = "RenderableTrailTrajectory", Enabled = false, diff --git a/data/assets/scene/solarsystem/missions/gaia/transforms.asset b/data/assets/scene/solarsystem/missions/gaia/transforms.asset index 5db3a1205c..83441604d5 100644 --- a/data/assets/scene/solarsystem/missions/gaia/transforms.asset +++ b/data/assets/scene/solarsystem/missions/gaia/transforms.asset @@ -11,7 +11,7 @@ local trail = asset.syncedResource({ local GaiaPosition = { Identifier = "GaiaPosition", - Parent = earthTransforms.EarthBarycenter.Identifier, + Parent = earthTransforms.EarthCenter.Identifier, Transform = { Translation = { Type = "HorizonsTranslation", diff --git a/data/assets/scene/solarsystem/sun/transforms.asset b/data/assets/scene/solarsystem/sun/transforms.asset index 29ab4120b8..ffa77be444 100644 --- a/data/assets/scene/solarsystem/sun/transforms.asset +++ b/data/assets/scene/solarsystem/sun/transforms.asset @@ -20,6 +20,24 @@ local SolarSystemBarycenter = { } } +local SunCenter = { + Identifier = "SunCenter", + Parent = SolarSystemBarycenter.Identifier, + Transform = { + Translation = { + Type = "SpiceTranslation", + Target = "SUN", + Observer = "SSB" + } + }, + GUI = { + Name = "SUN Center", + Path = "/Solar System/Sun", + Description = [[Spice frame for the Sun]], + Hidden = true + } +} + -- Spice frame for the Sun local SunIAU = { Identifier = "SunIAU", @@ -67,7 +85,7 @@ local SunECLIPJ2000 = { } } -assetHelper.registerSceneGraphNodesAndExport(asset, { SolarSystemBarycenter, SunIAU, SunECLIPJ2000 }) +assetHelper.registerSceneGraphNodesAndExport(asset, { SolarSystemBarycenter, SunCenter, SunIAU, SunECLIPJ2000 }) asset.meta = { From 309bce2e30c11715c2eef8e5d0c07ef18211c2bb Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 28 Jul 2021 14:49:29 +0200 Subject: [PATCH 16/24] Fix DebugAxis helper; Increase the sensitivity to prevent loss of color in debug axis (closes #1560) --- data/assets/util/debug_helper.asset | 2 +- .../rendering/renderablecartesianaxes.cpp | 14 ++++------- modules/base/shaders/axes_fs.glsl | 23 +++++++++++-------- modules/base/shaders/axes_vs.glsl | 16 ++++++------- modules/globebrowsing/src/tileprovider.cpp | 3 --- 5 files changed, 27 insertions(+), 31 deletions(-) diff --git a/data/assets/util/debug_helper.asset b/data/assets/util/debug_helper.asset index 6c75714d06..9b10fb04c6 100644 --- a/data/assets/util/debug_helper.asset +++ b/data/assets/util/debug_helper.asset @@ -67,7 +67,7 @@ local addCartesianAxes = function (specification) Parent = parent, Transform = { Scale = { - Type = "StaticScale", + Type = "NonUniformStaticScale", Scale = scale }, Translation = { diff --git a/modules/base/rendering/renderablecartesianaxes.cpp b/modules/base/rendering/renderablecartesianaxes.cpp index 9b658ac953..2228fa11e1 100644 --- a/modules/base/rendering/renderablecartesianaxes.cpp +++ b/modules/base/rendering/renderablecartesianaxes.cpp @@ -118,14 +118,7 @@ void RenderableCartesianAxes::initializeGL() { ); glGenVertexArrays(1, &_vaoId); - glGenBuffers(1, &_vBufferId); - glGenBuffers(1, &_iBufferId); - glBindVertexArray(_vaoId); - glBindBuffer(GL_ARRAY_BUFFER, _vBufferId); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferId); - glEnableVertexAttribArray(0); - glBindVertexArray(0); std::vector vertices({ Vertex{0.f, 0.f, 0.f}, @@ -140,7 +133,7 @@ void RenderableCartesianAxes::initializeGL() { 0, 3 }; - glBindVertexArray(_vaoId); + glGenBuffers(1, &_vBufferId); glBindBuffer(GL_ARRAY_BUFFER, _vBufferId); glBufferData( GL_ARRAY_BUFFER, @@ -149,8 +142,10 @@ void RenderableCartesianAxes::initializeGL() { GL_STATIC_DRAW ); + glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr); + glGenBuffers(1, &_iBufferId); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferId); glBufferData( GL_ELEMENT_ARRAY_BUFFER, @@ -158,6 +153,7 @@ void RenderableCartesianAxes::initializeGL() { indices.data(), GL_STATIC_DRAW ); + glBindVertexArray(0); } void RenderableCartesianAxes::deinitializeGL() { @@ -201,9 +197,9 @@ void RenderableCartesianAxes::render(const RenderData& data, RendererTasks&){ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnablei(GL_BLEND, 0); glEnable(GL_LINE_SMOOTH); + glLineWidth(3.0); glBindVertexArray(_vaoId); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferId); glDrawElements(GL_LINES, NVertexIndices, GL_UNSIGNED_INT, nullptr); glBindVertexArray(0); diff --git a/modules/base/shaders/axes_fs.glsl b/modules/base/shaders/axes_fs.glsl index 912657481c..182e24e973 100644 --- a/modules/base/shaders/axes_fs.glsl +++ b/modules/base/shaders/axes_fs.glsl @@ -33,17 +33,20 @@ uniform vec3 yColor; uniform vec3 zColor; Fragment getFragment() { - Fragment frag; + Fragment frag; - vec3 colorComponents = step(0.01, vs_positionModelSpace); + // We compare against a small value as the first vertex doesn't have a positional + // information (or rather it is 0) and we don't want to miss out on the color close to + // the origin + vec3 colorComponents = step(2e-32, vs_positionModelSpace); - frag.color.rgb = colorComponents.x * xColor + - colorComponents.y * yColor + - colorComponents.z * zColor; - frag.color.a = 1.0; + frag.color.rgb = colorComponents.x * xColor + + colorComponents.y * yColor + + colorComponents.z * zColor; + frag.color.a = 1.0; - frag.depth = vs_screenSpaceDepth; - frag.gPosition = vs_positionViewSpace; - frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); - return frag; + frag.depth = vs_screenSpaceDepth; + frag.gPosition = vs_positionViewSpace; + frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); + return frag; } diff --git a/modules/base/shaders/axes_vs.glsl b/modules/base/shaders/axes_vs.glsl index 539b4ddd18..feb654a310 100644 --- a/modules/base/shaders/axes_vs.glsl +++ b/modules/base/shaders/axes_vs.glsl @@ -34,13 +34,13 @@ uniform mat4 modelViewTransform; uniform mat4 projectionTransform; void main() { - vec4 positionViewSpace = modelViewTransform * vec4(in_position, 1.0); - vec4 positionClipSpace = projectionTransform * positionViewSpace; - vec4 positionScreenSpace = positionClipSpace; - positionScreenSpace.z = 0.0; - vs_positionModelSpace = in_position; - vs_screenSpaceDepth = positionScreenSpace.w; - vs_positionViewSpace = positionViewSpace; + vec4 positionViewSpace = modelViewTransform * vec4(in_position, 1.0); + vec4 positionClipSpace = projectionTransform * positionViewSpace; + vec4 positionScreenSpace = positionClipSpace; + positionScreenSpace.z = 0.0; + vs_positionModelSpace = in_position; + vs_screenSpaceDepth = positionScreenSpace.w; + vs_positionViewSpace = positionViewSpace; - gl_Position = positionScreenSpace; + gl_Position = positionScreenSpace; } diff --git a/modules/globebrowsing/src/tileprovider.cpp b/modules/globebrowsing/src/tileprovider.cpp index 53d75717f3..0f743ec592 100644 --- a/modules/globebrowsing/src/tileprovider.cpp +++ b/modules/globebrowsing/src/tileprovider.cpp @@ -228,9 +228,7 @@ Tile tile(TextTileProvider& t, const TileIndex& tileIndex) { // Keep track of defaultFBO and viewport to be able to reset state when done GLint defaultFBO; - //GLint viewport[4]; defaultFBO = global::renderEngine->openglStateCache().defaultFramebuffer(); - //glGetIntegerv(GL_VIEWPORT, viewport); // Render to texture glBindFramebuffer(GL_FRAMEBUFFER, t.fbo); @@ -252,7 +250,6 @@ Tile tile(TextTileProvider& t, const TileIndex& tileIndex) { glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); global::renderEngine->openglStateCache().resetViewportState(); - //glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); tile = Tile{ texture, std::nullopt, Tile::Status::OK }; t.tileCache->put(key, t.initData.hashKey, tile); From f676c780f5d1b215cacf79be367e74ffd6b1f484 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 28 Jul 2021 15:10:01 +0200 Subject: [PATCH 17/24] Prevent resetting of empty tileproviders (closes #1383) --- modules/globebrowsing/src/layermanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/globebrowsing/src/layermanager.cpp b/modules/globebrowsing/src/layermanager.cpp index 7aa19c6e60..51f0cc4dbc 100644 --- a/modules/globebrowsing/src/layermanager.cpp +++ b/modules/globebrowsing/src/layermanager.cpp @@ -156,7 +156,7 @@ void LayerManager::reset(bool includeDisabled) { for (std::unique_ptr& layerGroup : _layerGroups) { for (Layer* layer : layerGroup->layers()) { - if (layer->enabled() || includeDisabled) { + if ((layer->enabled() || includeDisabled) && layer->tileProvider()) { tileprovider::reset(*layer->tileProvider()); } } From c0941a124313dc4d0cb6106d032163ef5f90e5ed Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 29 Jul 2021 14:22:41 +0200 Subject: [PATCH 18/24] Reset the anchor/aim node when removing a scenegraph node (closes #1402) --- src/interaction/navigationhandler.cpp | 1 + src/scene/scene_lua.inl | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/interaction/navigationhandler.cpp b/src/interaction/navigationhandler.cpp index 620e87baf1..03843619d3 100644 --- a/src/interaction/navigationhandler.cpp +++ b/src/interaction/navigationhandler.cpp @@ -197,6 +197,7 @@ void NavigationHandler::deinitialize() { } void NavigationHandler::setFocusNode(SceneGraphNode* node) { + ghoul_assert(node, "Focus node must not be nullptr"); _orbitalNavigator.setFocusNode(node); _camera->setPositionVec3(anchorNode()->worldPosition()); } diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 8c231f8efc..b7e3af12b9 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -703,6 +704,15 @@ int removeSceneGraphNode(lua_State* L) { // Remove the node and all its children std::function removeNode = [&removeNode](SceneGraphNode* localNode) { + + if (localNode == global::navigationHandler->anchorNode()) { + global::navigationHandler->setFocusNode(sceneGraph()->root()); + } + + if (localNode == global::navigationHandler->orbitalNavigator().aimNode()) { + global::navigationHandler->orbitalNavigator().setAimNode(""); + } + std::vector children = localNode->children(); ghoul::mm_unique_ptr n = localNode->parent()->detachChild( @@ -852,6 +862,15 @@ int removeSceneGraphNodesFromRegex(lua_State* L) { // Remove all marked nodes std::function removeNode = [&removeNode, &markedList](SceneGraphNode* localNode) { + + if (localNode == global::navigationHandler->anchorNode()) { + global::navigationHandler->setFocusNode(sceneGraph()->root()); + } + + if (localNode == global::navigationHandler->orbitalNavigator().aimNode()) { + global::navigationHandler->orbitalNavigator().setAimNode(""); + } + std::vector children = localNode->children(); ghoul::mm_unique_ptr n = localNode->parent()->detachChild( From c4bddacfeb1d58a06230b061249dde52cb9ef835 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 30 Jul 2021 12:00:56 +0200 Subject: [PATCH 19/24] Remove nonfunctioning ABufferRenderer from RenderEngine --- CMakeLists.txt | 2 - include/openspace/engine/configuration.h | 8 +- include/openspace/rendering/abufferrenderer.h | 183 --- .../openspace/rendering/framebufferrenderer.h | 34 +- include/openspace/rendering/renderengine.h | 30 +- include/openspace/rendering/renderer.h | 83 -- modules/base/rendering/renderableplane.cpp | 16 +- modules/base/rendering/renderablesphere.cpp | 14 +- modules/base/rendering/renderabletrail.cpp | 16 +- .../renderablefieldlinessequence.cpp | 19 +- openspace.cfg | 1 - src/CMakeLists.txt | 7 - src/engine/configuration.cpp | 27 +- src/rendering/abufferrenderer.cpp | 1062 ----------------- src/rendering/renderengine.cpp | 212 +--- src/rendering/renderengine_lua.inl | 24 - 16 files changed, 64 insertions(+), 1674 deletions(-) delete mode 100644 include/openspace/rendering/abufferrenderer.h delete mode 100644 include/openspace/rendering/renderer.h delete mode 100644 src/rendering/abufferrenderer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b4b73947d7..c17d3703a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,8 +132,6 @@ if (MSVC) set(GHOUL_OPTIMIZATION_ENABLE_OTHER_OPTIMIZATIONS ${OPENSPACE_OPTIMIZATION_ENABLE_OTHER_OPTIMIZATIONS} CACHE BOOL "" FORCE) endif () -option(OPENSPACE_WITH_ABUFFER_RENDERER "Compile ABuffer Renderer" OFF) - if (UNIX) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -stdlib=libc++") diff --git a/include/openspace/engine/configuration.h b/include/openspace/engine/configuration.h index eed5c055c5..daf0ac7ee4 100644 --- a/include/openspace/engine/configuration.h +++ b/include/openspace/engine/configuration.h @@ -98,16 +98,14 @@ struct Configuration { bool usePerProfileCache = false; bool isRenderingOnMasterDisabled = false; - glm::dvec3 globalRotation = glm::dvec3(0.0); - glm::dvec3 screenSpaceRotation = glm::dvec3(0.0); - glm::dvec3 masterRotation = glm::dvec3(0.0); + glm::vec3 globalRotation = glm::vec3(0.0); + glm::vec3 screenSpaceRotation = glm::vec3(0.0); + glm::vec3 masterRotation = glm::vec3(0.0); bool isConsoleDisabled = false; bool bypassLauncher = false; std::map moduleConfigurations; - std::string renderingMethod = "Framebuffer"; - struct OpenGLDebugContext { bool isActive = false; bool isSynchronous = true; diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h deleted file mode 100644 index 5769c1e28c..0000000000 --- a/include/openspace/rendering/abufferrenderer.h +++ /dev/null @@ -1,183 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2021 * - * * - * 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. * - ****************************************************************************************/ - -#ifndef __OPENSPACE_CORE___ABUFFERRENDERER___H__ -#define __OPENSPACE_CORE___ABUFFERRENDERER___H__ - -#ifdef OPENSPACE_WITH_ABUFFER_RENDERER - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace ghoul::filesystem { class File; } - -namespace ghoul::opengl { - class ProgramObject; - class Texture; -} // namespace ghoul::opengl - -namespace openspace { - -struct RaycasterTask; -class RenderableVolume; -class Camera; -class Scene; -struct RaycastData; - -class ABufferRenderer : public Renderer, public RaycasterListener { -public: - virtual ~ABufferRenderer() = default; - - void initialize() override; - void deinitialize() override; - - void setResolution(glm::ivec2 res) override; - void setNAaSamples(int nAaSamples) override; - void setBlurrinessLevel(int level) override; - void setHDRExposure(float hdrExposure) override; - void setGamma(float gamma) override; - void setMaxWhite(float maxWhite) override; - void setToneMapOperator(int tmOp) override; - void setBloomThreMin(float minV) override; - void setBloomThreMax(float maxV) override; - void setBloomOrigFactor(float origFactor) override; - void setBloomNewFactor(float newFactor) override; - void setKey(float key) override; - void setYwhite(float white) override; - void setTmoSaturation(float sat) override; - void setHue(float hue) override; - void setValue(float value) override; - void setSaturation(float sat) override; - void setLightness(float lightness) override; - void setColorSpace(unsigned int colorspace) override; - - void enableBloom(bool enable) override; - void enableHistogram(bool enable) override; - - int nAaSamples() const override; - const std::vector& mSSAPattern() const override; - - using Renderer::preRaycast; - void preRaycast(const RaycasterTask& raycasterTask); - using Renderer::postRaycast; - void postRaycast(const RaycasterTask& raycasterTask); - - void update() override; - void render(Scene* scene, Camera* camera, float blackoutFactor) override; - - /** - * Update render data - * Responsible for calling renderEngine::setRenderData - */ - virtual void updateRendererData() override; - virtual void raycastersChanged(VolumeRaycaster& raycaster, - IsAttached attached) override; - -private: - void clear(); - void updateResolution(); - void updateRaycastData(); - void updateResolveDictionary(); - void updateMSAASamplingPattern(); - void saveTextureToMemory(GLenum color_buffer_attachment, int width, int height, - std::vector & memory) const; - - glm::ivec2 _resolution = glm::ivec2(0); - - bool _dirtyResolution = true; - bool _dirtyRendererData = true; - bool _dirtyRaycastData = true; - bool _dirtyResolveDictionary = true; - - std::unique_ptr _resolveProgram = nullptr; - - /** - * When a volume is attached or detached from the scene graph, - * the resolve program needs to be recompiled. - * The _volumes map keeps track of which volumes that can - * be rendered using the current resolve program, along with their raycast data - * (id, namespace, etc) - */ - std::map _raycastData; - std::map< - VolumeRaycaster*, std::unique_ptr - > _boundsPrograms; - std::vector _helperPaths; - - ghoul::Dictionary _resolveDictionary; - - GLuint _mainColorTexture; - GLuint _mainDepthTexture; - - GLuint _mainFramebuffer; - GLuint _screenQuad; - GLuint _anchorPointerTexture; - GLuint _anchorPointerTextureInitializer; - GLuint _atomicCounterBuffer; - GLuint _fragmentBuffer; - GLuint _fragmentTexture; - GLuint _vertexPositionBuffer; - int _nAaSamples; - int _blurrinessLevel = 1; - - float _hdrExposure = 0.4f; - float _hdrBackground = 2.8f; - float _gamma = 2.2f; - float _maxWhite = 1.f; - float _blackoutFactor; - bool _bloomEnabled = false; - float _bloomThresholdMin = 0.0; - float _bloomThresholdMax = 1.0; - float _bloomOrigFactor = 1.0; - float _bloomNewFactor = 1.0; - int _toneMapOperator = 0; - bool _histogramEnabled = false; - int _numberOfBins = 1024; // JCC TODO: Add a parameter control for this. - float _tmoKey = 0.18f; - float _tmoYwhite = 1e6f; - float _tmoSaturation = 1.0f; - float _hue = 1.f; - float _saturation = 1.f; - float _value = 1.f; - float _lightness = 1.f; - unsigned int _colorSpace = 1; - - std::vector _mSAAPattern; - - ghoul::Dictionary _rendererData; -}; - -} // namespace openspace - -#endif // OPENSPACE_WITH_ABUFFER_RENDERER - -#endif // __OPENSPACE_CORE___ABUFFERRENDERER___H__ diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index d76c2c5d88..f88e6460c3 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -25,8 +25,6 @@ #ifndef __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__ #define __OPENSPACE_CORE___FRAMEBUFFERRENDERER___H__ -#include -#include #include #include @@ -56,14 +54,14 @@ struct RaycasterTask; class Scene; struct UpdateStructures; -class FramebufferRenderer : public Renderer, public RaycasterListener, +class FramebufferRenderer : public RaycasterListener, public DeferredcasterListener { public: virtual ~FramebufferRenderer() = default; - void initialize() override; - void deinitialize() override; + void initialize(); + void deinitialize(); void updateResolution(); void updateRaycastData(); @@ -72,33 +70,33 @@ public: void updateFXAA(); void updateDownscaledVolume(); - void setResolution(glm::ivec2 res) override; - void setHDRExposure(float hdrExposure) override; - void setGamma(float gamma) override; - void setHue(float hue) override; - void setValue(float value) override; - void setSaturation(float sat) override; + void setResolution(glm::ivec2 res); + void setHDRExposure(float hdrExposure); + void setGamma(float gamma); + void setHue(float hue); + void setValue(float value); + void setSaturation(float sat); - void enableFXAA(bool enable) override; - void setDisableHDR(bool disable) override; + void enableFXAA(bool enable); + void setDisableHDR(bool disable); - void update() override; + void update(); void performRaycasterTasks(const std::vector& tasks, const glm::ivec4& viewport); void performDeferredTasks(const std::vector& tasks, const glm::ivec4& viewport); - void render(Scene* scene, Camera* camera, float blackoutFactor) override; + void render(Scene* scene, Camera* camera, float blackoutFactor); /** * Update render data * Responsible for calling renderEngine::setRenderData */ - virtual void updateRendererData() override; + virtual void updateRendererData(); virtual void raycastersChanged(VolumeRaycaster& raycaster, - RaycasterListener::IsAttached attached) override; + RaycasterListener::IsAttached attached); virtual void deferredcastersChanged(Deferredcaster& deferredcaster, - DeferredcasterListener::IsAttached isAttached) override; + DeferredcasterListener::IsAttached isAttached); private: using RaycasterProgObjMap = std::map< diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index d32734712c..388e0c8044 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,6 @@ namespace scripting { struct LuaLibrary; } class Camera; class RaycasterManager; class DeferredcasterManager; -class Renderer; class Scene; class SceneManager; class ScreenLog; @@ -63,12 +63,6 @@ struct ShutdownInformation; class RenderEngine : public properties::PropertyOwner { public: - enum class RendererImplementation { - Framebuffer = 0, - ABuffer, - Invalid - }; - RenderEngine(); ~RenderEngine(); @@ -80,9 +74,6 @@ public: Scene* scene(); void updateScene(); - const Renderer& renderer() const; - RendererImplementation rendererImplementation() const; - ghoul::opengl::OpenGLStateCache& openglStateCache(); void updateShaderPrograms(); @@ -120,24 +111,11 @@ public: void removeRenderProgram(ghoul::opengl::ProgramObject* program); - /** - * Set raycasting uniforms on the program object, and setup raycasting. - */ - void preRaycast(ghoul::opengl::ProgramObject& programObject); - - /** - * Tear down raycasting for the specified program object. - */ - void postRaycast(ghoul::opengl::ProgramObject& programObject); - /** * Set the camera to use for rendering */ void setCamera(Camera* camera); - - void setRendererFromString(const std::string& renderingMethod); - /** * Lets the renderer update the data to be brought into the rendererer programs * as a 'rendererData' variable in the dictionary. @@ -176,9 +154,6 @@ public: uint64_t frameNumber() const; private: - void setRenderer(std::unique_ptr renderer); - RendererImplementation rendererFromString(const std::string& renderingMethod) const; - void renderScreenLog(); void renderVersionInformation(); void renderCameraInformation(); @@ -188,8 +163,7 @@ private: Camera* _camera = nullptr; Scene* _scene = nullptr; - std::unique_ptr _renderer; - RendererImplementation _rendererImplementation = RendererImplementation::Invalid; + FramebufferRenderer _renderer; ghoul::Dictionary _rendererData; ghoul::Dictionary _resolveData; ScreenLog* _log = nullptr; diff --git a/include/openspace/rendering/renderer.h b/include/openspace/rendering/renderer.h deleted file mode 100644 index 6a9243592d..0000000000 --- a/include/openspace/rendering/renderer.h +++ /dev/null @@ -1,83 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2021 * - * * - * 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. * - ****************************************************************************************/ - -#ifndef __OPENSPACE_CORE___RENDERER___H__ -#define __OPENSPACE_CORE___RENDERER___H__ - -#include -#include - -namespace ghoul { class Dictionary; } -namespace ghoul::filesystem { class File; } -namespace ghoul::opengl { - class ProgramObject; - class Texture; -} // namespace ghoul::opengl - -namespace openspace { - -class RenderableVolume; -class Camera; -class Scene; - -class Renderer { -public: - virtual ~Renderer() = default; - - virtual void initialize() = 0; - virtual void deinitialize() = 0; - - virtual void setResolution(glm::ivec2 res) = 0; - virtual void setHDRExposure(float hdrExposure) = 0; - virtual void setGamma(float gamma) = 0; - virtual void setHue(float hue) = 0; - virtual void setValue(float value) = 0; - virtual void setSaturation(float sat) = 0; - virtual void enableFXAA(bool enable) = 0; - virtual void setDisableHDR(bool disable) = 0; - - /** - * Set raycasting uniforms on the program object, and setup raycasting. - */ - virtual void preRaycast(ghoul::opengl::ProgramObject& /*programObject*/) {}; - - /** - * Tear down raycasting for the specified program object. - */ - virtual void postRaycast(ghoul::opengl::ProgramObject& /*programObject*/) {}; - - - virtual void update() = 0; - - virtual void render(Scene* scene, Camera* camera, float blackoutFactor) = 0; - /** - * Update render data - * Responsible for calling renderEngine::setRenderData - */ - virtual void updateRendererData() = 0; -}; - -} // openspace - -#endif // __OPENSPACE_CORE___RENDERER___H__ diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 86401eb031..f8079ec26e 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -255,21 +255,7 @@ void RenderablePlane::render(const RenderData& data, RendererTasks&) { _shader->setUniform("multiplyColor", _multiplyColor); - bool usingFramebufferRenderer = global::renderEngine->rendererImplementation() == - RenderEngine::RendererImplementation::Framebuffer; - - bool usingABufferRenderer = global::renderEngine->rendererImplementation() == - RenderEngine::RendererImplementation::ABuffer; - - if (usingABufferRenderer) { - _shader->setUniform( - "additiveBlending", - _blendMode == static_cast(BlendMode::Additive) - ); - } - - bool additiveBlending = - (_blendMode == static_cast(BlendMode::Additive)) && usingFramebufferRenderer; + bool additiveBlending = (_blendMode == static_cast(BlendMode::Additive)); if (additiveBlending) { glDepthMask(false); glBlendFunc(GL_SRC_ALPHA, GL_ONE); diff --git a/modules/base/rendering/renderablesphere.cpp b/modules/base/rendering/renderablesphere.cpp index 4d05f81f3d..be23335a4e 100644 --- a/modules/base/rendering/renderablesphere.cpp +++ b/modules/base/rendering/renderablesphere.cpp @@ -398,24 +398,14 @@ void RenderableSphere::render(const RenderData& data, RendererTasks&) { glDisable(GL_CULL_FACE); } - bool usingFramebufferRenderer = global::renderEngine->rendererImplementation() == - RenderEngine::RendererImplementation::Framebuffer; - - bool usingABufferRenderer = global::renderEngine->rendererImplementation() == - RenderEngine::RendererImplementation::ABuffer; - - if (usingABufferRenderer && _useAdditiveBlending) { - _shader->setUniform("additiveBlending", true); - } - - if (usingFramebufferRenderer && _useAdditiveBlending) { + if (_useAdditiveBlending) { glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDepthMask(false); } _sphere->render(); - if (usingFramebufferRenderer && _useAdditiveBlending) { + if (_useAdditiveBlending) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(true); } diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 63e7d99764..509be6db13 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -430,14 +430,8 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) { /*glm::ivec2 resolution = global::renderEngine.renderingResolution(); _programObject->setUniform(_uniformCache.resolution, resolution);*/ - const bool usingFramebufferRenderer = - global::renderEngine->rendererImplementation() == - RenderEngine::RendererImplementation::Framebuffer; - - if (usingFramebufferRenderer) { - glDepthMask(false); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); const bool renderLines = (_appearance.renderingModes == RenderingModeLines) || (_appearance.renderingModes == RenderingModeLinesPoints); @@ -508,10 +502,8 @@ void RenderableTrail::render(const RenderData& data, RendererTasks&) { glBindVertexArray(0); - if (usingFramebufferRenderer) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthMask(true); - } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(true); _programObject->deactivate(); } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 95e075a9a6..8f58744cf4 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -1112,22 +1112,9 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& bool additiveBlending = false; if (_pColorABlendEnabled) { - const auto renderer = global::renderEngine->rendererImplementation(); - const bool usingFBufferRenderer = renderer == - RenderEngine::RendererImplementation::Framebuffer; - - const bool usingABufferRenderer = renderer == - RenderEngine::RendererImplementation::ABuffer; - - if (usingABufferRenderer) { - _shaderProgram->setUniform("usingAdditiveBlending", _pColorABlendEnabled); - } - - additiveBlending = usingFBufferRenderer; - if (additiveBlending) { - glDepthMask(false); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - } + additiveBlending = true; + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); } glBindVertexArray(_vertexArrayObject); diff --git a/openspace.cfg b/openspace.cfg index 3a5e56d9e0..b1afa57fd7 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -236,7 +236,6 @@ GlobalRotation = { 0.0, 0.0, 0.0 } MasterRotation = { 0.0, 0.0, 0.0 } ScreenSpaceRotation = { 0.0, 0.0, 0.0 } -RenderingMethod = "Framebuffer" OpenGLDebugContext = { Activate = true, FilterIdentifier = { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23d6ff8de2..3d5ef003ca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -108,7 +108,6 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/properties/vector/vec3property.cpp ${OPENSPACE_BASE_DIR}/src/properties/vector/vec4property.cpp ${OPENSPACE_BASE_DIR}/src/query/query.cpp - ${OPENSPACE_BASE_DIR}/src/rendering/abufferrenderer.cpp ${OPENSPACE_BASE_DIR}/src/rendering/dashboard.cpp ${OPENSPACE_BASE_DIR}/src/rendering/dashboard_lua.inl ${OPENSPACE_BASE_DIR}/src/rendering/dashboarditem.cpp @@ -284,7 +283,6 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/properties/vector/vec3property.h ${OPENSPACE_BASE_DIR}/include/openspace/properties/vector/vec4property.h ${OPENSPACE_BASE_DIR}/include/openspace/query/query.h - ${OPENSPACE_BASE_DIR}/include/openspace/rendering/abufferrenderer.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboard.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboarditem.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboardtextitem.h @@ -298,7 +296,6 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/rendering/raycasterlistener.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/raycastermanager.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderable.h - ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderer.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderengine.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/screenspacerenderable.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/texturecomponent.h @@ -464,10 +461,6 @@ endif () set_openspace_compile_settings(openspace-core) target_link_libraries(openspace-core PUBLIC Ghoul spice external-curl) -if (OPENSPACE_WITH_ABUFFER_RENDERER) - target_compile_definitions(openspace-core PUBLIC "OPENSPACE_WITH_ABUFFER_RENDERER") -endif () - # Just in case, create the bin directory add_custom_command( TARGET openspace-core diff --git a/src/engine/configuration.cpp b/src/engine/configuration.cpp index 7194824f06..ad7b113f67 100644 --- a/src/engine/configuration.cpp +++ b/src/engine/configuration.cpp @@ -161,15 +161,6 @@ namespace { // resolution ('framebuffer'). This value defaults to 'window' std::optional onScreenTextScaling; - // List from RenderEngine::setRendererFromString - enum class RenderingMethod { - Framebuffer, - ABuffer - }; - // The renderer that is use after startup. The renderer 'ABuffer' requires support - // for at least OpenGL 4.3 - std::optional renderingMethod; - // Toggles whether the master in a multi-application setup should be rendering or // just managing the state of the network. This is desired in cases where the // master computer does not have the resources to render a scene @@ -178,16 +169,16 @@ namespace { // Applies a global view rotation. Use this to rotate the position of the focus // node away from the default location on the screen. This setting persists even // when a new focus node is selected. Defined using roll, pitch, yaw in radians - std::optional globalRotation; + std::optional globalRotation; // Applies a view rotation for only the master node, defined using roll, pitch yaw // in radians. This can be used to compensate the master view direction for tilted // display systems in clustered immersive environments - std::optional masterRotation; + std::optional masterRotation; // Applies a global rotation for all screenspace renderables. Defined using roll, // pitch, yaw in radians - std::optional screenSpaceRotation; + std::optional screenSpaceRotation; // If this value is set to 'true' the ingame console is disabled, locking the // system down against random access @@ -415,18 +406,6 @@ void parseLuaState(Configuration& configuration) { c.globalRotation = p.globalRotation.value_or(c.globalRotation); c.masterRotation = p.masterRotation.value_or(c.masterRotation); c.screenSpaceRotation = p.screenSpaceRotation.value_or(c.screenSpaceRotation); - if (p.renderingMethod.has_value()) { - switch (*p.renderingMethod) { - case Parameters::RenderingMethod::Framebuffer: - c.renderingMethod = "Framebuffer"; - break; - case Parameters::RenderingMethod::ABuffer: - c.renderingMethod = "ABuffer"; - break; - default: - throw ghoul::MissingCaseException(); - } - } c.isConsoleDisabled = p.disableInGameConsole.value_or(c.isConsoleDisabled); if (p.logging.has_value()) { if (p.logging->logLevel.has_value()) { diff --git a/src/rendering/abufferrenderer.cpp b/src/rendering/abufferrenderer.cpp deleted file mode 100644 index 4b4f4d4654..0000000000 --- a/src/rendering/abufferrenderer.cpp +++ /dev/null @@ -1,1062 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2021 * - * * - * 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. * - ****************************************************************************************/ - -#ifdef OPENSPACE_WITH_ABUFFER_RENDERER - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - constexpr const char* _loggerCat = "ABufferRenderer"; - constexpr const char* BoundsFragmentShaderPath = - "${SHADERS}/abuffer/boundsabuffer.frag"; - constexpr const char* RenderFragmentShaderPath = - "${SHADERS}/abuffer/renderabuffer.frag"; - - constexpr int MaxRaycasters = 32; - constexpr int MaxLayers = 32; - constexpr int MaxAverageLayers = 8; -} // namespace - -namespace openspace { - -void ABufferRenderer::initialize() { - LINFO("Initializing ABufferRenderer"); - const GLfloat vertexData[] = { - // x y - -1.f, -1.f, - 1.f, 1.f, - -1.f, 1.f, - -1.f, -1.f, - 1.f, -1.f, - 1.f, 1.f, - }; - - glGenVertexArrays(1, &_screenQuad); - glBindVertexArray(_screenQuad); - - glGenBuffers(1, &_vertexPositionBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - - glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr); - glEnableVertexAttribArray(0); - - glGenTextures(1, &_anchorPointerTexture); - glGenBuffers(1, &_anchorPointerTextureInitializer); - glGenBuffers(1, &_atomicCounterBuffer); - glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer); - glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), nullptr, GL_DYNAMIC_COPY); - glGenBuffers(1, &_fragmentBuffer); - glGenTextures(1, &_fragmentTexture); - - glGenTextures(1, &_mainColorTexture); - glGenTextures(1, &_mainDepthTexture); - glGenFramebuffers(1, &_mainFramebuffer); - - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - - updateResolution(); - updateRendererData(); - updateRaycastData(); - updateResolveDictionary(); - updateMSAASamplingPattern(); - - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D_MULTISAMPLE, - _mainColorTexture, - 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, defaultFbo); - - try { - ghoul::Dictionary dict; - dict.setValue("resolveData", _resolveDictionary); - dict.setValue("rendererData", _rendererData); - - _resolveProgram = ghoul::opengl::ProgramObject::Build( - "ABuffer Resolve", - absPath("${SHADERS}/abuffer/resolveabuffer.vert"), - absPath("${SHADERS}/abuffer/resolveabuffer.frag"), - dict - ); - } catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } - - global::raycasterManager.addListener(*this); -} - -void ABufferRenderer::deinitialize() { - LINFO("Deinitializing ABufferRenderer"); - glDeleteBuffers(1, &_fragmentBuffer); - glDeleteTextures(1, &_fragmentTexture); - - glDeleteTextures(1, &_anchorPointerTexture); - glDeleteBuffers(1, &_anchorPointerTextureInitializer); - glDeleteBuffers(1, &_atomicCounterBuffer); - - glDeleteBuffers(1, &_vertexPositionBuffer); - glDeleteVertexArrays(1, &_screenQuad); - - global::raycasterManager.removeListener(*this); -} - -void ABufferRenderer::raycastersChanged(VolumeRaycaster&, IsAttached) { - _dirtyRaycastData = true; -} - -void ABufferRenderer::update() { - PerfMeasure("ABufferRenderer::update"); - - // Make sure that the fragment buffer has the correct resoliution - // according to the output render buffer size - if (_dirtyResolution) { - updateResolution(); - updateMSAASamplingPattern(); - } - - // Make sure that the renderengine gets the correct render data - // to feed into all render programs. - // This will trigger a recompilation of all the shader programs - // involved in rendering geometries. - if (_dirtyRendererData) { - updateRendererData(); - } - - // Make sure that all raycaster data is up to date. - if (_dirtyRaycastData) { - updateRaycastData(); - } - - // Make sure that the resolve dictionary is up to date. - // The resolve dictionary contains information for all - // ray casters, including shader include paths. - - if (_dirtyResolveDictionary) { - updateResolveDictionary(); - ghoul::Dictionary dict; - dict.setValue("resolveData", _resolveDictionary); - dict.setValue("rendererData", _rendererData); - _resolveProgram->setDictionary(dict); - } - - // If the resolve dictionary changed (or a file changed on disk) - // then rebuild the resolve program. - if (_resolveProgram->isDirty()) { - try { - _resolveProgram->rebuildFromFile(); - } catch (const ghoul::RuntimeError& error) { - LERRORC(error.component, error.message); - } - } - using K = VolumeRaycaster* const; - using V = std::unique_ptr; - for (std::pair& program : _boundsPrograms) { - if (program.second->isDirty()) { - try { - program.second->rebuildFromFile(); - } catch (const ghoul::RuntimeError& e) { - LERRORC(e.component, e.message); - } - } - } -} - -void ABufferRenderer::updateMSAASamplingPattern() { - // @CLEANUP(abock): This should probably be merged with the same code from the - // framebuffer renderer? - LINFO("Updating MSAA Sampling Pattern"); - - constexpr const int GridSize = 32; - GLfloat step = 2.f / static_cast(GridSize); - GLfloat sizeX = -1.f; - GLfloat sizeY = 1.f; - - constexpr const int NVertex = 4 * 6; - // openPixelSizeVertexData - GLfloat vertexData[GridSize * GridSize * NVertex]; - - for (int y = 0; y < GridSize; ++y) { - for (int x = 0; x < GridSize; ++x) { - vertexData[y * GridSize * NVertex + x * NVertex] = sizeX; - vertexData[y * GridSize * NVertex + x * NVertex + 1] = sizeY - step; - vertexData[y * GridSize * NVertex + x * NVertex + 2] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 3] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 4] = sizeX + step; - vertexData[y * GridSize * NVertex + x * NVertex + 5] = sizeY; - vertexData[y * GridSize * NVertex + x * NVertex + 6] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 7] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 8] = sizeX; - vertexData[y * GridSize * NVertex + x * NVertex + 9] = sizeY; - vertexData[y * GridSize * NVertex + x * NVertex + 10] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 11] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 12] = sizeX; - vertexData[y * GridSize * NVertex + x * NVertex + 13] = sizeY - step; - vertexData[y * GridSize * NVertex + x * NVertex + 14] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 15] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 16] = sizeX + step; - vertexData[y * GridSize * NVertex + x * NVertex + 17] = sizeY - step; - vertexData[y * GridSize * NVertex + x * NVertex + 18] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 19] = 1.f; - - vertexData[y * GridSize * NVertex + x * NVertex + 20] = sizeX + step; - vertexData[y * GridSize * NVertex + x * NVertex + 21] = sizeY; - vertexData[y * GridSize * NVertex + x * NVertex + 22] = 0.f; - vertexData[y * GridSize * NVertex + x * NVertex + 23] = 1.f; - - sizeX += step; - } - sizeX = -1.f; - sizeY -= step; - } - - GLuint pixelSizeQuadVAO = 0; - glGenVertexArrays(1, &pixelSizeQuadVAO); - glBindVertexArray(pixelSizeQuadVAO); - - GLuint pixelSizeQuadVBO = 0; - glGenBuffers(1, &pixelSizeQuadVBO); - glBindBuffer(GL_ARRAY_BUFFER, pixelSizeQuadVBO); - - glBufferData( - GL_ARRAY_BUFFER, - sizeof(GLfloat) * GridSize * GridSize * NVertex, - vertexData, - GL_STATIC_DRAW - ); - - // Position - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, nullptr); - glEnableVertexAttribArray(0); - - // Saves current state - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - - // Main framebuffer - - GLuint pixelSizeTexture = 0; - glGenTextures(1, &pixelSizeTexture); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, pixelSizeTexture); - - constexpr const GLsizei OnePixel = 1; - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA32F, - OnePixel, - OnePixel, - true - ); - - glViewport(0, 0, OnePixel, OnePixel); - - GLuint pixelSizeFramebuffer = 0; - glGenFramebuffers(1, &pixelSizeFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, pixelSizeFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D_MULTISAMPLE, - pixelSizeTexture, - 0 - ); - - GLenum textureBuffers[1] = { GL_COLOR_ATTACHMENT0 }; - glDrawBuffers(1, textureBuffers); - - glClearColor(0.f, 0.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT); - - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("MSAA Sampling pattern framebuffer is not complete"); - return; - } - - std::unique_ptr pixelSizeProgram = - ghoul::opengl::ProgramObject::Build( - "OnePixel MSAA", - absPath("${SHADERS}/framebuffer/pixelSizeMSAA.vert"), - absPath("${SHADERS}/framebuffer/pixelSizeMSAA.frag") - ); - - pixelSizeProgram->activate(); - - // Draw sub-pixel grid - glEnable(GL_SAMPLE_SHADING); - glBindVertexArray(pixelSizeQuadVAO); - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - glDrawArrays(GL_TRIANGLES, 0, GridSize * GridSize * 6); - glBindVertexArray(0); - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SAMPLE_SHADING); - - pixelSizeProgram->deactivate(); - - // Now we render the Nx1 quad strip - GLuint nOneStripFramebuffer = 0; - GLuint nOneStripVAO = 0; - GLuint nOneStripVBO = 0; - GLuint nOneStripTexture = 0; - - sizeX = -1.f; - step = 2.f / static_cast(_nAaSamples); - - std::vector nOneStripVertexData(_nAaSamples * (NVertex + 12)); - - for (int x = 0; x < _nAaSamples; ++x) { - nOneStripVertexData[x * (NVertex + 12)] = sizeX; - nOneStripVertexData[x * (NVertex + 12) + 1] = -1.f; - nOneStripVertexData[x * (NVertex + 12) + 2] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 3] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 4] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 5] = 0.f; - - nOneStripVertexData[x * (NVertex + 12) + 6] = sizeX + step; - nOneStripVertexData[x * (NVertex + 12) + 7] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 8] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 9] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 10] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 11] = 1.f; - - nOneStripVertexData[x * (NVertex + 12) + 12] = sizeX; - nOneStripVertexData[x * (NVertex + 12) + 13] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 14] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 15] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 16] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 17] = 0.f; - - nOneStripVertexData[x * (NVertex + 12) + 18] = sizeX; - nOneStripVertexData[x * (NVertex + 12) + 19] = -1.f; - nOneStripVertexData[x * (NVertex + 12) + 20] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 21] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 22] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 23] = 0.f; - - nOneStripVertexData[x * (NVertex + 12) + 24] = sizeX + step; - nOneStripVertexData[x * (NVertex + 12) + 25] = -1.f; - nOneStripVertexData[x * (NVertex + 12) + 26] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 27] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 28] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 29] = 1.f; - - nOneStripVertexData[x * (NVertex + 12) + 30] = sizeX + step; - nOneStripVertexData[x * (NVertex + 12) + 31] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 32] = 0.f; - nOneStripVertexData[x * (NVertex + 12) + 33] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 34] = 1.f; - nOneStripVertexData[x * (NVertex + 12) + 35] = 1.f; - - sizeX += step; - } - - glGenVertexArrays(1, &nOneStripVAO); - glBindVertexArray(nOneStripVAO); - glGenBuffers(1, &nOneStripVBO); - glBindBuffer(GL_ARRAY_BUFFER, nOneStripVBO); - glBufferData( - GL_ARRAY_BUFFER, - sizeof(GLfloat) * _nAaSamples * (NVertex + 12), - nOneStripVertexData.data(), - GL_STATIC_DRAW - ); - - // position - glVertexAttribPointer( - 0, - 4, - GL_FLOAT, - GL_FALSE, - sizeof(GLfloat) * 6, - nullptr - ); - glEnableVertexAttribArray(0); - - // texture coords - glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(GLfloat) * 6, - reinterpret_cast(sizeof(GLfloat) * 4) - ); - glEnableVertexAttribArray(1); - - // fbo texture buffer - glGenTextures(1, &nOneStripTexture); - glBindTexture(GL_TEXTURE_2D, nOneStripTexture); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA32F, - _nAaSamples, - OnePixel, - 0, - GL_RGBA, - GL_FLOAT, - nullptr - ); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glGenFramebuffers(1, &nOneStripFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, nOneStripFramebuffer); - glFramebufferTexture2D( - GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - nOneStripTexture, - 0 - ); - - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - LERROR("nOneStrip framebuffer is not complete"); - } - - glViewport(0, 0, _nAaSamples, OnePixel); - - std::unique_ptr nOneStripProgram = - ghoul::opengl::ProgramObject::Build( - "OneStrip MSAA", - absPath("${SHADERS}/framebuffer/nOneStripMSAA.vert"), - absPath("${SHADERS}/framebuffer/nOneStripMSAA.frag") - ); - - nOneStripProgram->activate(); - - ghoul::opengl::TextureUnit pixelSizeTextureUnit; - pixelSizeTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, pixelSizeTexture); - nOneStripProgram->setUniform("pixelSizeTexture", pixelSizeTextureUnit); - - // render strip - glDrawBuffers(1, textureBuffers); - - glClearColor(0.f, 1.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT); - glBindVertexArray(nOneStripVAO); - glDisable(GL_DEPTH_TEST); - glDepthMask(false); - for (int sample = 0; sample < _nAaSamples; ++sample) { - nOneStripProgram->setUniform("currentSample", sample); - glDrawArrays(GL_TRIANGLES, sample * 6, 6); - } - /*nOneStripProgram->setUniform("currentSample", 0); - glDrawArrays(GL_TRIANGLES, 0, 6 * _nAaSamples);*/ - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glBindVertexArray(0); - - saveTextureToMemory(GL_COLOR_ATTACHMENT0, _nAaSamples, 1, _mSAAPattern); - // Convert back to [-1, 1] range and then scales to 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 ABufferRenderer::render(Scene* scene, Camera* camera, float blackoutFactor) { - ZoneScoped - - const bool doPerformanceMeasurements = global::performanceManager.isEnabled(); - - PerfMeasure("ABufferRenderer::render"); - - if (!scene || !camera) { - return; - } - - ghoul::opengl::TextureUnit mainColorTextureUnit; - mainColorTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); - - ghoul::opengl::TextureUnit mainDepthTextureUnit; - mainDepthTextureUnit.activate(); - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - GLint defaultFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFbo); - glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Reset - clear(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - - // Step 1: Render geometries to the fragment buffer - - // Bind head-pointer image for read-write - glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); - glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); - glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); - - // Render the scene to the fragment buffer. Collect renderer tasks (active raycasters) - int renderBinMask = static_cast(Renderable::RenderBin::Background) | - static_cast(Renderable::RenderBin::Opaque) | - static_cast(Renderable::RenderBin::PreDeferredTransparent) | - static_cast(Renderable::RenderBin::PostDeferredTransparent) | - static_cast(Renderable::RenderBin::Overlay); - - Time time = global::timeManager.time(); - RenderData data{ *camera, psc(), time, doPerformanceMeasurements, renderBinMask, {} }; - RendererTasks tasks; - scene->render(data, tasks); - _blackoutFactor = blackoutFactor; - - glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); - - - // Step 2: Perform raycasting tasks requested by the scene - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { - VolumeRaycaster* raycaster = raycasterTask.raycaster; - ghoul::opengl::ProgramObject* program = _boundsPrograms[raycaster].get(); - if (program) { - program->activate(); - program->setUniform("_exit_", false); - raycaster->renderEntryPoints(raycasterTask.renderData, *program); - program->setUniform("_exit_", true); - raycaster->renderExitPoints(raycasterTask.renderData, *program); - program->deactivate(); - } - else { - LWARNING("Raycaster is not attached when trying to perform raycaster task"); - } - } - - - // Step 3: Resolve the buffer - _resolveProgram->activate(); - - // TEMPORARY GAMMA CORRECTION. - - glm::vec3 cameraPos = data.camera.position().vec3(); - float maxComponent = std::max( - std::max(std::abs(cameraPos.x), std::abs(cameraPos.y)), std::abs(cameraPos.z) - ); - float logDistance = std::log(glm::length(cameraPos / maxComponent) * maxComponent) - / std::log(10.f); - - const float minLogDist = 15.f; - const float maxLogDist = 20.f; - - float t = (logDistance - minLogDist) / (maxLogDist - minLogDist); - t = glm::clamp(t, 0.0f, 1.0f); - const float gamma = 1.f * (1.f - t) + 2.2f * t; - - _resolveProgram->setUniform("gamma", gamma); - - // END TEMPORARY GAMMA CORRECTION. - - _resolveProgram->setUniform("mainColorTexture", mainColorTextureUnit.unitNumber()); - _resolveProgram->setUniform("mainDepthTexture", mainDepthTextureUnit.unitNumber()); - _resolveProgram->setUniform("blackoutFactor", _blackoutFactor); - _resolveProgram->setUniform("nAaSamples", _nAaSamples); - - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { - preRaycast(raycasterTask); - } - - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - - for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { - postRaycast(raycasterTask); - } - - _resolveProgram->deactivate(); -} - -void ABufferRenderer::preRaycast(const RaycasterTask& raycasterTask) { - VolumeRaycaster& raycaster = *raycasterTask.raycaster; - const RaycastData& raycastData = _raycastData[&raycaster]; - const RenderData& renderData = raycasterTask.renderData; - - raycaster.preRaycast(raycastData, *_resolveProgram); - - glm::vec3 localCameraPosition; - bool isCameraInside = raycaster.isCameraInside(renderData, localCameraPosition); - int uniformIndex = raycastData.id + 1; // uniforms are indexed from 1 (not from 0) - _resolveProgram->setUniform( - "insideRaycaster" + std::to_string(uniformIndex), - isCameraInside - ); - if (isCameraInside) { - _resolveProgram->setUniform( - "cameraPosInRaycaster" + std::to_string(uniformIndex), - localCameraPosition - ); - } -} - -void ABufferRenderer::postRaycast(const RaycasterTask& raycasterTask) { - VolumeRaycaster& raycaster = *raycasterTask.raycaster; - const RaycastData& raycastData = _raycastData[&raycaster]; - - raycaster.postRaycast(raycastData, *_resolveProgram); -} - -void ABufferRenderer::setResolution(glm::ivec2 res) { - if (res != _resolution) { - _resolution = std::move(res); - _dirtyResolution = true; - } -} - -void ABufferRenderer::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 ABufferRenderer::setBlurrinessLevel(int level) { - ghoul_assert( - level > 0 && nAaSamples < 4, - "Blurriness level has to be between 1 and 3" - ); - _blurrinessLevel = level; -} - -void ABufferRenderer::setHDRExposure(float hdrExposure) { - _hdrExposure = hdrExposure; - if (_hdrExposure < 0.f) { - LERROR("HDR Exposure constant must be greater than zero."); - _hdrExposure = 1.0; - } -} - -void ABufferRenderer::setGamma(float gamma) { - _gamma = gamma; - if (_gamma < 0.f) { - LERROR("Gamma value must be greater than zero."); - _gamma = 2.2f; - } -} - -void ABufferRenderer::setMaxWhite(float maxWhite) { - _maxWhite = maxWhite; -} - -void ABufferRenderer::setToneMapOperator(int tmOp) { - _toneMapOperator = tmpOp; -}; - -void ABufferRenderer::setToneMapOperator(int tmOp) { - _toneMapOperator = tmOp; -} - -void ABufferRenderer::setBloomThreMin(float minV) { - _bloomThresholdMin = minV; -} - -void ABufferRenderer::setBloomThreMax(float maxV) { - _bloomThresholdMax = maxV; -} - -void ABufferRenderer::setBloomOrigFactor(float origFactor) { - _bloomOrigFactor = origFactor; -} - -void ABufferRenderer::setBloomNewFactor(float newFactor) { - _bloomNewFactor = newFactor; -} - -void ABufferRenderer::setKey(float key) { - _tmoKey = key; -} - -void ABufferRenderer::setYwhite(float white) { - _tmoYwhite = white; -} - -void ABufferRenderer::setTmoSaturation(float sat) { - _tmoSaturation = sat; -} - -void ABufferRenderer::setHue(float hue) { - _hue = hue; -} - -void ABufferRenderer::setValue(float value) { - _value = value; -} - -void ABufferRenderer::setSaturation(float sat) { - _saturation = sat; -} - -void ABufferRenderer::setLightness(float lightness) { - _lightness = lightness; -} - -void ABufferRenderer::setColorSpace(unsigned int colorspace) { - _colorSpace = colorspace; -} - -void ABufferRenderer::enableBloom(bool enable) { - _bloomEnabled = enable; -} - -void ABufferRenderer::enableHistogram(bool enable) { - _histogramEnabled = enable; -} - -int ABufferRenderer::nAaSamples() const { - return _nAaSamples; -} - -const std::vector& ABufferRenderer::mSSAPattern() const { - return _mSAAPattern; -} - -void ABufferRenderer::clear() { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); - glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); - - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_R32UI, - _resolution.x, - _resolution.y, - 0, - GL_RED_INTEGER, - GL_UNSIGNED_INT, - nullptr - ); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - - static const GLuint zero = 1; - glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); - glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); - glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); -} - -void ABufferRenderer::updateResolution() { - PerfMeasure("ABufferRenderer::updateResolution"); - - int totalPixels = _resolution.x * _resolution.y; - glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_R32UI, - _resolution.x, - _resolution.y, - 0, - GL_RED_INTEGER, - GL_UNSIGNED_INT, - nullptr - ); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); - glBufferData( - GL_PIXEL_UNPACK_BUFFER, - totalPixels * sizeof(GLuint), - nullptr, - GL_STATIC_DRAW - ); - - GLuint* data = reinterpret_cast( - glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY) - ); - memset(data, 0x00, totalPixels * sizeof(GLuint)); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - - glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); - glBufferData( - GL_TEXTURE_BUFFER, - MaxAverageLayers*totalPixels * sizeof(GLuint) * 4, - nullptr, - GL_DYNAMIC_COPY - ); - - glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); - glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); - glBindTexture(GL_TEXTURE_BUFFER, 0); - - glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainColorTexture); - - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_RGBA, - _resolution.x, - _resolution.y, - true - ); - - glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, _mainDepthTexture); - glTexImage2DMultisample( - GL_TEXTURE_2D_MULTISAMPLE, - _nAaSamples, - GL_DEPTH_COMPONENT32F, - _resolution.x, - _resolution.y, - true - ); - - _dirtyResolution = false; -} - -void ABufferRenderer::updateResolveDictionary() { - ghoul::Dictionary dict; - ghoul::Dictionary raycastersDict; - - for (const std::pair& raycastPair : _raycastData) { - ghoul::Dictionary innerDict; - int id = raycastPair.second.id; - std::string namespaceName = raycastPair.second.namespaceName; - std::string raycastPath = raycastPair.first->raycasterPath(); - - innerDict.setValue("id", id); - innerDict.setValue("namespace", namespaceName); - innerDict.setValue("bitmask", 1 << id); - innerDict.setValue("raycastPath", raycastPath); - - raycastersDict.setValue(std::to_string(id), innerDict); - } - - dict.setValue("raycasters", raycastersDict); - - ghoul::Dictionary helperPathsDict; - for (size_t i = 0; i < _helperPaths.size(); ++i) { - helperPathsDict.setValue(std::to_string(i), _helperPaths[i]); - } - - dict.setValue("helperPaths", helperPathsDict); - dict.setValue("raycastingEnabled", !_raycastData.empty()); - dict.setValue("storeSorted", true); - dict.setValue("nRaycasters", static_cast(_raycastData.size())); - - _resolveDictionary = dict; - - global::renderEngine.setResolveData(dict); - - _dirtyResolveDictionary = false; -} - -void ABufferRenderer::updateRaycastData() { - PerfMeasure("ABufferRenderer::updateRaycastData"); - - _raycastData.clear(); - _boundsPrograms.clear(); - _helperPaths.clear(); - - const std::vector& raycasters = - global::raycasterManager.raycasters(); - - std::map namespaceIndices; - // raycaster ids are positive integers starting at 0. (for raycasters, - // fragment type is id+1) - int nextId = 0; - int nextNamespaceIndex = 0; - - for (VolumeRaycaster* raycaster : raycasters) { - if (nextId > MaxRaycasters) { - int nIgnored = MaxRaycasters - static_cast(raycasters.size()); - LWARNING(fmt::format( - "ABufferRenderer does not support more than 32 raycasters. " - "Ignoring {} raycasters", - nIgnored - )); - break; - } - - RaycastData data; - data.id = nextId++; - - std::string helperPath = raycaster->helperPath(); - // Each new helper path generates a new namespace, - // to avoid glsl name collisions between raycaster implementaitons. - // Assign a new namespace or find an already created index. - - if (helperPath.empty()) { - data.namespaceName = "NAMESPACE_" + std::to_string(nextNamespaceIndex++); - } - else { - auto iter = namespaceIndices.find(helperPath); - if (iter == namespaceIndices.end()) { - int namespaceIndex = nextNamespaceIndex++; - data.namespaceName = std::to_string(namespaceIndex); - namespaceIndices[helperPath] = namespaceIndex; - _helperPaths.push_back(helperPath); - } - else { - data.namespaceName = "NAMESPACE_" + std::to_string(iter->second); - } - } - - _raycastData[raycaster] = data; - std::string vsPath = raycaster->boundsVertexShaderPath(); - std::string fsPath = raycaster->boundsFragmentShaderPath(); - ghoul::Dictionary dict; - - // set path to the current renderer's main fragment shader - dict.setValue("rendererData", _rendererData); - // parameterize the main fragment shader program with specific contents. - // fsPath should point to a shader file defining a Fragment getFragment() function - // instead of a void main() setting glFragColor, glFragDepth, etc. - dict.setValue("fragmentPath", fsPath); - dict.setValue("fragmentType", data.id + 1); - try { - _boundsPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( - "Volume " + std::to_string(data.id) + " bounds", - vsPath, - BoundsFragmentShaderPath, - dict - ); - } - catch (ghoul::RuntimeError& error) { - LERRORC(error.component, error.message); - } - } - - _dirtyRaycastData = false; - _dirtyResolveDictionary = true; -} - -void ABufferRenderer::updateRendererData() { - PerfMeasure("ABufferRenderer::updateRendererData"); - - ghoul::Dictionary dict; - dict.setValue("fragmentRendererPath", std::string(RenderFragmentShaderPath)); - dict.setValue("maxLayers", MaxLayers); - dict.setValue("maxTotalFragments", MaxLayers * _resolution.x * _resolution.y); - - _rendererData = dict; - - global::renderEngine.setRendererData(dict); - _dirtyRendererData = false; -} - -void ABufferRenderer::saveTextureToMemory(GLenum color_buffer_attachment, int width, - int height, std::vector& memory) const -{ - memory.clear(); - - memory.reserve(width * height * 3); - std::vector tmpMemory(width * height * 3); - - if (color_buffer_attachment != GL_DEPTH_ATTACHMENT) { - glReadBuffer(color_buffer_attachment); - glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, tmpMemory.data()); - - } - else { - glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, tmpMemory.data()); - } - - for (int i = 0; i < width * height * 3; ++i) { - memory[i] = static_cast(tmpMemory[i]); - } -} - -} // namespace openspace - -#else -int _StubToPreventLinkerWarningAboutMissingExportSymbols; -#endif // OPENSPACE_WITH_ABUFFER_RENDERER diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 21d63a2c28..a61e71fd9e 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -302,57 +301,27 @@ RenderEngine::RenderEngine() addProperty(_showVersionInfo); addProperty(_showCameraInfo); - _enableFXAA.onChange([this]() { - if (_renderer) { - _renderer->enableFXAA(_enableFXAA); - } - }); + _enableFXAA.onChange([this]() { _renderer.enableFXAA(_enableFXAA); }); addProperty(_enableFXAA); _disableHDRPipeline.onChange([this]() { - if (_renderer) { - _renderer->setDisableHDR(_disableHDRPipeline); - } + _renderer.setDisableHDR(_disableHDRPipeline); }); addProperty(_disableHDRPipeline); - _hdrExposure.onChange([this]() { - if (_renderer) { - _renderer->setHDRExposure(_hdrExposure); - } - }); + _hdrExposure.onChange([this]() { _renderer.setHDRExposure(_hdrExposure); }); addProperty(_hdrExposure); - _gamma.onChange([this]() { - if (_renderer) { - _renderer->setGamma(_gamma); - } - }); + _gamma.onChange([this]() { _renderer.setGamma(_gamma); }); addProperty(_gamma); - _hue.onChange([this]() { - if (_renderer) { - const float h = _hue / 360.f; - _renderer->setHue(h); - } - }); - + _hue.onChange([this]() { _renderer.setHue(_hue / 360.f); }); addProperty(_hue); - _saturation.onChange([this]() { - if (_renderer) { - _renderer->setSaturation(_saturation); - } - }); - + _saturation.onChange([this]() { _renderer.setSaturation(_saturation); }); addProperty(_saturation); - _value.onChange([this]() { - if (_renderer) { - _renderer->setValue(_value); - } - }); - + _value.onChange([this]() { _renderer.setValue(_value); }); addProperty(_value); addProperty(_globalBlackOutFactor); @@ -414,39 +383,16 @@ RenderEngine::RenderEngine() RenderEngine::~RenderEngine() {} // NOLINT -void RenderEngine::setRendererFromString(const std::string& renderingMethod) { - ZoneScoped - - _rendererImplementation = rendererFromString(renderingMethod); - - std::unique_ptr newRenderer = nullptr; - switch (_rendererImplementation) { - case RendererImplementation::Framebuffer: - newRenderer = std::make_unique(); - break; - case RendererImplementation::ABuffer: -#ifdef OPENSPACE_WITH_ABUFFER_RENDERER - newRenderer = std::make_unique(); -#endif // OPENSPACE_WITH_ABUFFER_RENDERER - break; - case RendererImplementation::Invalid: - LFATAL(fmt::format("Rendering method '{}' not available", renderingMethod)); - return; - } - - setRenderer(std::move(newRenderer)); -} - void RenderEngine::initialize() { ZoneScoped // We have to perform these initializations here as the OsEng has not been initialized // in our constructor - _globalRotation = static_cast(global::configuration->globalRotation); - _screenSpaceRotation = - static_cast(global::configuration->screenSpaceRotation); - _masterRotation = static_cast(global::configuration->masterRotation); + _globalRotation = global::configuration->globalRotation; + _screenSpaceRotation = global::configuration->screenSpaceRotation; + _masterRotation = global::configuration->masterRotation; _disableMasterRendering = global::configuration->isRenderingOnMasterDisabled; + _screenshotUseDate = global::configuration->shouldUseScreenshotDate; #ifdef GHOUL_USE_DEVIL ghoul::io::TextureReader::ref().addReader( @@ -499,8 +445,6 @@ void RenderEngine::initialize() { ); } } - - _screenshotUseDate = global::configuration->shouldUseScreenshotDate; } void RenderEngine::initializeGL() { @@ -508,21 +452,10 @@ void RenderEngine::initializeGL() { LTRACE("RenderEngine::initializeGL(begin)"); - std::string renderingMethod = global::configuration->renderingMethod; - if (renderingMethod == "ABuffer") { - using Version = ghoul::systemcapabilities::Version; - - // The default rendering method has a requirement of OpenGL 4.3, so if we are - // below that, we will fall back to frame buffer operation - if (OpenGLCap.openGLVersion() < Version{ 4,3,0 }) { - LINFO("Falling back to framebuffer implementation due to OpenGL limitations"); - renderingMethod = "Framebuffer"; - } - } - - LINFO(fmt::format("Setting renderer from string: {}", renderingMethod)); - setRendererFromString(renderingMethod); - + _renderer.setResolution(renderingResolution()); + _renderer.enableFXAA(_enableFXAA); + _renderer.setHDRExposure(_hdrExposure); + _renderer.initialize(); // set the close clip plane and the far clip plane to extreme values while in // development @@ -532,45 +465,15 @@ void RenderEngine::initializeGL() { // initialized window _horizFieldOfView = static_cast(global::windowDelegate->getHorizFieldOfView()); + configuration::Configuration::FontSizes fontSize = global::configuration->fontSize; { - ZoneScopedN("Font: FrameInfo") - TracyGpuZone("Font: FrameInfo") - _fontFrameInfo = global::fontManager->font( - KeyFontMono, - global::configuration->fontSize.frameInfo - ); - } - { - ZoneScopedN("Font: Shutdown") - TracyGpuZone("Font: Shutdown") - _fontShutdown = global::fontManager->font( - KeyFontMono, - global::configuration->fontSize.shutdown - ); - } - { - ZoneScopedN("Font: CameraInfo") - TracyGpuZone("Font: CameraInfo") - _fontCameraInfo = global::fontManager->font( - KeyFontMono, - global::configuration->fontSize.cameraInfo - ); - } - { - ZoneScopedN("Font: VersionInfo") - TracyGpuZone("Font: VersionInfo") - _fontVersionInfo = global::fontManager->font( - KeyFontMono, - global::configuration->fontSize.versionInfo - ); - } - { - ZoneScopedN("Font: Log") - TracyGpuZone("Font: Log") - _fontLog = global::fontManager->font( - KeyFontLight, - global::configuration->fontSize.log - ); + ZoneScopedN("Fonts") + TracyGpuZone("Fonts") + _fontFrameInfo = global::fontManager->font(KeyFontMono, fontSize.frameInfo); + _fontShutdown = global::fontManager->font(KeyFontMono, fontSize.shutdown); + _fontCameraInfo = global::fontManager->font(KeyFontMono, fontSize.cameraInfo); + _fontVersionInfo = global::fontManager->font(KeyFontMono, fontSize.versionInfo); + _fontLog = global::fontManager->font(KeyFontLight, fontSize.log); } { @@ -588,7 +491,7 @@ void RenderEngine::initializeGL() { void RenderEngine::deinitializeGL() { ZoneScoped - _renderer = nullptr; + _renderer.deinitialize(); } void RenderEngine::updateScene() { @@ -633,7 +536,7 @@ void RenderEngine::updateRenderer() { const bool windowResized = global::windowDelegate->windowHasResized(); if (windowResized) { - _renderer->setResolution(renderingResolution()); + _renderer.setResolution(renderingResolution()); using FR = ghoul::fontrendering::FontRenderer; FR::defaultRenderer().setFramebufferSize(fontResolution()); @@ -643,7 +546,7 @@ void RenderEngine::updateRenderer() { static_cast(global::windowDelegate->getHorizFieldOfView()); } - _renderer->update(); + _renderer.update(); } void RenderEngine::updateScreenSpaceRenderables() { @@ -737,9 +640,9 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat _lastFrameTime = now + std::chrono::microseconds(static_cast(delta)); } - const bool masterEnabled = delegate.isMaster() ? !_disableMasterRendering : true; - if (masterEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) { - _renderer->render( + const bool renderingEnabled = delegate.isMaster() ? !_disableMasterRendering : true; + if (renderingEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) { + _renderer.render( _scene, _camera, _globalBlackOutFactor @@ -776,7 +679,7 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat RenderFont(*_fontFrameInfo, penPosition, res); } - if (masterEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) { + if (renderingEnabled && !delegate.isGuiWindow() && _globalBlackOutFactor > 0.f) { ZoneScopedN("Render Screenspace Renderable") std::vector ssrs; @@ -968,14 +871,6 @@ void RenderEngine::setCamera(Camera* camera) { _camera = camera; } -const Renderer& RenderEngine::renderer() const { - return *_renderer; -} - -RenderEngine::RendererImplementation RenderEngine::rendererImplementation() const { - return _rendererImplementation; -} - ghoul::opengl::OpenGLStateCache& RenderEngine::openglStateCache() { if (_openglStateCache == nullptr) { _openglStateCache = ghoul::opengl::OpenGLStateCache::instance(); @@ -1127,39 +1022,10 @@ unsigned int RenderEngine::latestScreenshotNumber() const { return _latestScreenshotNumber; } -void RenderEngine::preRaycast(ghoul::opengl::ProgramObject& programObject) { - _renderer->preRaycast(programObject); -} - -void RenderEngine::postRaycast(ghoul::opengl::ProgramObject& programObject) { - _renderer->postRaycast(programObject); -} - -void RenderEngine::setRenderer(std::unique_ptr renderer) { - ZoneScoped - - if (_renderer) { - _renderer->deinitialize(); - } - - _renderer = std::move(renderer); - _renderer->setResolution(renderingResolution()); - _renderer->enableFXAA(_enableFXAA); - _renderer->setHDRExposure(_hdrExposure); - _renderer->initialize(); -} - scripting::LuaLibrary RenderEngine::luaLibrary() { return { "", { - { - "setRenderer", - &luascriptfunctions::setRenderer, - {}, - "string", - "Sets the renderer (ABuffer or FrameBuffer)" - }, { "addScreenSpaceRenderable", &luascriptfunctions::addScreenSpaceRenderable, @@ -1266,24 +1132,6 @@ std::vector RenderEngine::screenSpaceRenderables() const return res; } -RenderEngine::RendererImplementation RenderEngine::rendererFromString( - const std::string& renderingMethod) const -{ - const std::map RenderingMethods = { -#ifdef OPENSPACE_WITH_ABUFFER_RENDERER - { "ABuffer", RendererImplementation::ABuffer }, -#endif // OPENSPACE_WITH_ABUFFER_RENDERER - { "Framebuffer", RendererImplementation::Framebuffer } - }; - - if (RenderingMethods.find(renderingMethod) != RenderingMethods.end()) { - return RenderingMethods.at(renderingMethod); - } - else { - return RendererImplementation::Invalid; - } -} - void RenderEngine::renderCameraInformation() { ZoneScoped diff --git a/src/rendering/renderengine_lua.inl b/src/rendering/renderengine_lua.inl index 9bb26d0fcd..b011722f42 100644 --- a/src/rendering/renderengine_lua.inl +++ b/src/rendering/renderengine_lua.inl @@ -26,30 +26,6 @@ namespace openspace::luascriptfunctions { -/** -* \ingroup LuaScripts -* setRenderer(string): -* Set renderer -*/ -int setRenderer(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setRenderer"); - - const int type = lua_type(L, -1); - if (type != LUA_TSTRING) { - return ghoul::lua::luaError(L, "Expected argument of type 'string'"); - } - - const std::string& renderer = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); - global::renderEngine->setRendererFromString(renderer); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; -} - int addScreenSpaceRenderable(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addScreenSpaceRenderable"); From f6d74870bb2105b6216d807a90dfcf8cb608e760 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 30 Jul 2021 12:24:46 +0200 Subject: [PATCH 20/24] Don't disable the CEF UI when turning off Master rendering (#1699) --- src/rendering/framebufferrenderer.cpp | 2 +- src/rendering/renderengine.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 1a92b2f781..1f9913fe13 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -1254,7 +1254,7 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac TracyGpuZone("Apply TMO") GLDebugGroup group("Apply TMO"); - applyTMO(blackoutFactor, glm::ivec4(viewport[0], viewport[1], viewport[2], viewport[3])); + applyTMO(blackoutFactor, viewport); } if (_enableFXAA) { diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index a61e71fd9e..6168dfce2f 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -649,6 +650,14 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat ); } + // The CEF webbrowser fix has to be called at least once per frame and we are doing + // that in the renderer::render method. So if we disable the rendering, that fix is + // no longer called as we lose access to the Web UI. Since we are calling the fix + // many times anyway, we can just add one call to it here and not lose much + if (global::callback::webBrowserPerformanceHotfix) { + (*global::callback::webBrowserPerformanceHotfix)(); + } + if (_showFrameInformation) { ZoneScopedN("Show Frame Information") From 5b3a66156c403b39a2bb96870ae21c3f72faef65 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 30 Jul 2021 14:48:08 +0200 Subject: [PATCH 21/24] Remove unnecessary template specification for lock_guard --- ext/ghoul | 2 +- include/openspace/util/concurrentjobmanager.inl | 4 ++-- modules/sync/syncs/httpsynchronization.cpp | 2 +- modules/sync/syncs/urlsynchronization.cpp | 2 +- src/network/parallelpeer.cpp | 8 ++++---- src/rendering/loadingscreen.cpp | 8 ++++---- src/scene/sceneinitializer.cpp | 8 ++++---- src/scripting/scriptengine.cpp | 6 +++--- src/util/camera.cpp | 2 +- src/util/httprequest.cpp | 4 ++-- src/util/synchronizationwatcher.cpp | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 0a7f66f9a1..57e96a6a8d 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 0a7f66f9a1cb050b9d6e803257ab1320259fa53d +Subproject commit 57e96a6a8d10003eb22aaa471de8eec60d89df2c diff --git a/include/openspace/util/concurrentjobmanager.inl b/include/openspace/util/concurrentjobmanager.inl index a49dff3da9..0816b910c2 100644 --- a/include/openspace/util/concurrentjobmanager.inl +++ b/include/openspace/util/concurrentjobmanager.inl @@ -36,7 +36,7 @@ template void ConcurrentJobManager

::enqueueJob(std::shared_ptr> job) { threadPool.enqueue([this, job]() { job->execute(); - std::lock_guard lock(_finishedJobsMutex); + std::lock_guard lock(_finishedJobsMutex); _finishedJobs.push(job); }); } @@ -50,7 +50,7 @@ template std::shared_ptr> ConcurrentJobManager

::popFinishedJob() { ghoul_assert(!_finishedJobs.empty(), "There is no finished job to pop!"); - std::lock_guard lock(_finishedJobsMutex); + std::lock_guard lock(_finishedJobsMutex); return _finishedJobs.pop(); } diff --git a/modules/sync/syncs/httpsynchronization.cpp b/modules/sync/syncs/httpsynchronization.cpp index 18f2a34c7f..08bbb66953 100644 --- a/modules/sync/syncs/httpsynchronization.cpp +++ b/modules/sync/syncs/httpsynchronization.cpp @@ -228,7 +228,7 @@ bool HttpSynchronization::trySyncFromUrl(std::string listUrl) { return !_shouldCancel; } - std::lock_guard guard(sizeDataMutex); + std::lock_guard guard(sizeDataMutex); sizeData[line] = { p.totalBytesKnown, p.totalBytes, p.downloadedBytes }; diff --git a/modules/sync/syncs/urlsynchronization.cpp b/modules/sync/syncs/urlsynchronization.cpp index d53d79ca49..f0c418b02c 100644 --- a/modules/sync/syncs/urlsynchronization.cpp +++ b/modules/sync/syncs/urlsynchronization.cpp @@ -192,7 +192,7 @@ void UrlSynchronization::start() { &startedAllDownloads, &nDownloads](HttpRequest::Progress p) { if (p.totalBytesKnown) { - std::lock_guard guard(fileSizeMutex); + std::lock_guard guard(fileSizeMutex); fileSizes[url] = p.totalBytes; if (!_nTotalBytesKnown && startedAllDownloads && diff --git a/src/network/parallelpeer.cpp b/src/network/parallelpeer.cpp index 08bee3b496..49c6024433 100644 --- a/src/network/parallelpeer.cpp +++ b/src/network/parallelpeer.cpp @@ -199,7 +199,7 @@ void ParallelPeer::sendAuthentication() { } void ParallelPeer::queueInMessage(const ParallelConnection::Message& message) { - std::lock_guard unqlock(_receiveBufferMutex); + std::lock_guard unqlock(_receiveBufferMutex); _receiveBuffer.push_back(message); } @@ -221,7 +221,7 @@ void ParallelPeer::handleMessage(const ParallelConnection::Message& message) { } void ParallelPeer::analyzeTimeDifference(double messageTimestamp) { - std::lock_guard latencyLock(_latencyMutex); + std::lock_guard latencyLock(_latencyMutex); const double timeDiff = global::windowDelegate->applicationTime() - messageTimestamp; if (_latencyDiffs.empty()) { @@ -235,7 +235,7 @@ void ParallelPeer::analyzeTimeDifference(double messageTimestamp) { } double ParallelPeer::convertTimestamp(double messageTimestamp) { - std::lock_guard latencyLock(_latencyMutex); + std::lock_guard latencyLock(_latencyMutex); return messageTimestamp + _initialTimeDiff + _bufferTime; } @@ -495,7 +495,7 @@ void ParallelPeer::sendScript(std::string script) { void ParallelPeer::resetTimeOffset() { global::navigationHandler->keyframeNavigator().clearKeyframes(); global::timeManager->clearKeyframes(); - std::lock_guard latencyLock(_latencyMutex); + std::lock_guard latencyLock(_latencyMutex); _latencyDiffs.clear(); } diff --git a/src/rendering/loadingscreen.cpp b/src/rendering/loadingscreen.cpp index fcb131de23..451751a54b 100644 --- a/src/rendering/loadingscreen.cpp +++ b/src/rendering/loadingscreen.cpp @@ -283,7 +283,7 @@ void LoadingScreen::render() { glm::vec2 messageLl = glm::vec2(0.f); glm::vec2 messageUr = glm::vec2(0.f); if (_showMessage) { - std::lock_guard guard(_messageMutex); + std::lock_guard guard(_messageMutex); const glm::vec2 bboxMessage = _messageFont->boundingBox(_message); @@ -298,7 +298,7 @@ void LoadingScreen::render() { } if (_showNodeNames) { - std::lock_guard guard(_itemsMutex); + std::lock_guard guard(_itemsMutex); std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); @@ -485,7 +485,7 @@ void LoadingScreen::render() { } void LoadingScreen::postMessage(std::string message) { - std::lock_guard guard(_messageMutex); + std::lock_guard guard(_messageMutex); _message = std::move(message); } @@ -535,7 +535,7 @@ void LoadingScreen::updateItem(const std::string& itemIdentifier, // also would create any of the text information return; } - std::lock_guard guard(_itemsMutex); + std::lock_guard guard(_itemsMutex); auto it = std::find_if( _items.begin(), diff --git a/src/scene/sceneinitializer.cpp b/src/scene/sceneinitializer.cpp index 1e92860d26..9334cb3e62 100644 --- a/src/scene/sceneinitializer.cpp +++ b/src/scene/sceneinitializer.cpp @@ -66,7 +66,7 @@ void MultiThreadedSceneInitializer::initializeNode(SceneGraphNode* node) { } node->initialize(); - std::lock_guard g(_mutex); + std::lock_guard g(_mutex); _initializedNodes.push_back(node); _initializingNodes.erase(node); @@ -94,19 +94,19 @@ void MultiThreadedSceneInitializer::initializeNode(SceneGraphNode* node) { ); } - std::lock_guard g(_mutex); + std::lock_guard g(_mutex); _initializingNodes.insert(node); _threadPool.enqueue(initFunction); } std::vector MultiThreadedSceneInitializer::takeInitializedNodes() { - std::lock_guard g(_mutex); + std::lock_guard g(_mutex); std::vector nodes = std::move(_initializedNodes); return nodes; } bool MultiThreadedSceneInitializer::isInitializing() const { - std::lock_guard g(_mutex); + std::lock_guard g(_mutex); return !_initializingNodes.empty(); } diff --git a/src/scripting/scriptengine.cpp b/src/scripting/scriptengine.cpp index d34b2a1afe..dc917b8de8 100644 --- a/src/scripting/scriptengine.cpp +++ b/src/scripting/scriptengine.cpp @@ -694,7 +694,7 @@ void ScriptEngine::preSync(bool isMaster) { return; } - std::lock_guard guard(_slaveScriptsMutex); + std::lock_guard guard(_slaveScriptsMutex); while (!_incomingScripts.empty()) { QueueItem item = std::move(_incomingScripts.front()); _incomingScripts.pop(); @@ -728,7 +728,7 @@ void ScriptEngine::encode(SyncBuffer* syncBuffer) { void ScriptEngine::decode(SyncBuffer* syncBuffer) { ZoneScoped - std::lock_guard guard(_slaveScriptsMutex); + std::lock_guard guard(_slaveScriptsMutex); size_t nScripts; syncBuffer->decode(nScripts); @@ -757,7 +757,7 @@ void ScriptEngine::postSync(bool isMaster) { } } else { - std::lock_guard guard(_slaveScriptsMutex); + std::lock_guard guard(_slaveScriptsMutex); while (!_slaveScriptQueue.empty()) { try { runScript(_slaveScriptQueue.front()); diff --git a/src/util/camera.cpp b/src/util/camera.cpp index 4091bdb45b..551f129099 100644 --- a/src/util/camera.cpp +++ b/src/util/camera.cpp @@ -258,7 +258,7 @@ const glm::mat4& Camera::SgctInternal::projectionMatrix() const { const glm::mat4& Camera::SgctInternal::viewProjectionMatrix() const { //if (_cachedViewProjectionMatrix.isDirty) { - std::lock_guard _lock(_mutex); + std::lock_guard _lock(_mutex); _cachedViewProjectionMatrix.datum = _projectionMatrix * _viewMatrix; _cachedViewProjectionMatrix.isDirty = false; //} diff --git a/src/util/httprequest.cpp b/src/util/httprequest.cpp index 2250aa80f9..fe5c982b7d 100644 --- a/src/util/httprequest.cpp +++ b/src/util/httprequest.cpp @@ -245,7 +245,7 @@ AsyncHttpDownload::AsyncHttpDownload(AsyncHttpDownload&& d) {} void AsyncHttpDownload::start(HttpRequest::RequestOptions opt) { - std::lock_guard guard(_stateChangeMutex); + std::lock_guard guard(_stateChangeMutex); if (hasStarted()) { return; } @@ -286,7 +286,7 @@ void AsyncHttpDownload::download(HttpRequest::RequestOptions opt) { _httpRequest.onProgress([this](HttpRequest::Progress p) { // Return a non-zero value to cancel download // if onProgress returns false. - //std::lock_guard guard(_mutex); + //std::lock_guard guard(_mutex); const bool shouldContinue = callOnProgress(p); if (!shouldContinue) { return 1; diff --git a/src/util/synchronizationwatcher.cpp b/src/util/synchronizationwatcher.cpp index 5c14833970..98c724219d 100644 --- a/src/util/synchronizationwatcher.cpp +++ b/src/util/synchronizationwatcher.cpp @@ -41,7 +41,7 @@ SynchronizationWatcher::WatchHandle SynchronizationWatcher::watchSynchronization [this, synchronization, watchHandle, cb = std::move(callback)] (ResourceSynchronization::State state) { - std::lock_guard g(_mutex); + std::lock_guard g(_mutex); _pendingNotifications.push_back({ synchronization, state, watchHandle, cb }); } ); From c96764aa1c6c8f1d7d7603e255c787fb718a7565 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 30 Jul 2021 14:56:55 +0200 Subject: [PATCH 22/24] Remove Clang warnings --- .../rendering/atmospheredeferredcaster.cpp | 17 ++++++++++------- modules/base/rendering/renderablelabels.cpp | 14 +++++++------- modules/base/rendering/renderableprism.cpp | 10 ++++++++-- .../rendering/renderabledumeshes.cpp | 8 -------- .../src/dashboarditemglobelocation.cpp | 2 -- .../globebrowsing/src/globelabelscomponent.cpp | 2 +- modules/space/translation/spicetranslation.cpp | 2 +- .../dashboard/dashboarditeminstruments.cpp | 2 ++ .../spacecraftinstruments/util/labelparser.cpp | 3 +-- .../spacecraftinstruments/util/labelparser.h | 3 +-- 10 files changed, 31 insertions(+), 32 deletions(-) diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 3bc7f14edc..8bc8f1061c 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -90,7 +90,10 @@ namespace { return; } - std::vector px(size.x * size.y * 3, unsigned char(255)); + std::vector px( + size.x * size.y * 3, + static_cast(255) + ); glReadBuffer(colorBufferAttachment); glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, px.data()); @@ -198,9 +201,9 @@ namespace { GLuint createTexture(const glm::ivec3& size, std::string_view name, int components) { ghoul_assert(components == 3 || components == 4, "Only 3-4 components supported"); - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_3D, texture); + GLuint t; + glGenTextures(1, &t); + glBindTexture(GL_TEXTURE_3D, t); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -221,9 +224,9 @@ namespace { nullptr ); if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel(GL_TEXTURE, texture, name.size(), name.data()); + glObjectLabel(GL_TEXTURE, t, static_cast(name.size()), name.data()); } - return texture; + return t; } } // namespace @@ -239,9 +242,9 @@ AtmosphereDeferredcaster::AtmosphereDeferredcaster(float textureScale, , _nuSamples(static_cast(8 * textureScale)) , _muSamples(static_cast(128 * textureScale)) , _rSamples(static_cast(32 * textureScale)) + , _textureSize(_muSSamples * _nuSamples, _muSamples, _rSamples) , _shadowConfArray(std::move(shadowConfigArray)) , _saveCalculationTextures(saveCalculatedTextures) - , _textureSize(_muSSamples * _nuSamples, _muSamples, _rSamples) { std::memset(_uniformNameBuffer, '\0', sizeof(_uniformNameBuffer)); std::strcpy(_uniformNameBuffer, "shadowDataArray["); diff --git a/modules/base/rendering/renderablelabels.cpp b/modules/base/rendering/renderablelabels.cpp index 5125e2bed7..1d482d9d7d 100644 --- a/modules/base/rendering/renderablelabels.cpp +++ b/modules/base/rendering/renderablelabels.cpp @@ -224,21 +224,21 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown) , _color(ColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f)) - , _size(SizeInfo, 8.f, 0.5f, 30.f) , _fontSize(FontSizeInfo, 50.f, 1.f, 100.f) + , _size(SizeInfo, 8.f, 0.5f, 30.f) , _minMaxSize(MinMaxSizeInfo, glm::ivec2(8, 20), glm::ivec2(0), glm::ivec2(100)) - , _enableFadingEffect(EnableFadingEffectInfo, false) , _text(TextInfo, "") - , _fadeDistances(FadeDistancesInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f)) + , _enableFadingEffect(EnableFadingEffectInfo, false) , _fadeWidths(FadeWidthsInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f)) - , _orientationOption( - OrientationOptionInfo, - properties::OptionProperty::DisplayType::Dropdown - ) + , _fadeDistances(FadeDistancesInfo, glm::vec2(1.f), glm::vec2(0.f), glm::vec2(100.f)) , _fadeUnitOption( FadeUnitOptionInfo, properties::OptionProperty::DisplayType::Dropdown ) + , _orientationOption( + OrientationOptionInfo, + properties::OptionProperty::DisplayType::Dropdown + ) { const Parameters p = codegen::bake(dictionary); diff --git a/modules/base/rendering/renderableprism.cpp b/modules/base/rendering/renderableprism.cpp index 20f610d3c8..c14798a604 100644 --- a/modules/base/rendering/renderableprism.cpp +++ b/modules/base/rendering/renderableprism.cpp @@ -215,7 +215,10 @@ void RenderablePrism::updateVertexData() { for (int i = 0; i < 2; ++i) { float h = i * _length; // z value, 0 to _length - for (int j = 0, k = 0; j < _nShapeSegments && k < unitVertices.size(); ++j, k += 2) { + for (int j = 0, k = 0; + j < _nShapeSegments && k < static_cast(unitVertices.size()); + ++j, k += 2) + { float ux = unitVertices[k]; float uy = unitVertices[k + 1]; @@ -239,7 +242,10 @@ void RenderablePrism::updateVertexData() { _vertexArray.push_back(_length); } else { - for (int j = 0, k = 0; j < _nLines && k < unitVerticesLines.size(); ++j, k += 2) { + for (int j = 0, k = 0; + j < _nLines && k < static_cast(unitVerticesLines.size()); + ++j, k += 2) + { float ux = unitVerticesLines[k]; float uy = unitVerticesLines[k + 1]; diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 9fc7d78962..c28b0d5a0a 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -515,7 +515,6 @@ bool RenderableDUMeshes::readSpeckFile() { // (signaled by the keywords 'datavar', 'texturevar', and 'texture') std::string line; while (true) { - std::streampos position = file.tellg(); std::getline(file, line); if (file.eof()) { @@ -534,16 +533,9 @@ bool RenderableDUMeshes::readSpeckFile() { std::size_t found = line.find("mesh"); if (found == std::string::npos) { - //if (line.substr(0, 4) != "mesh") { - // we read a line that doesn't belong to the header, so we have to jump back - // before the beginning of the current line - //file.seekg(position); - //break; continue; } else { - - //if (line.substr(0, 4) == "mesh") { // mesh lines are structured as follows: // mesh -t texnum -c colorindex -s style { // where textnum is the index of the texture; diff --git a/modules/globebrowsing/src/dashboarditemglobelocation.cpp b/modules/globebrowsing/src/dashboarditemglobelocation.cpp index 650e8557a0..f318a64a14 100644 --- a/modules/globebrowsing/src/dashboarditemglobelocation.cpp +++ b/modules/globebrowsing/src/dashboarditemglobelocation.cpp @@ -39,8 +39,6 @@ #include #include -#pragma optimize ("", off) - namespace { constexpr const char* KeyFontMono = "Mono"; constexpr const float DefaultFontSize = 10.f; diff --git a/modules/globebrowsing/src/globelabelscomponent.cpp b/modules/globebrowsing/src/globelabelscomponent.cpp index ed3548ba9d..7f27aa1a37 100644 --- a/modules/globebrowsing/src/globelabelscomponent.cpp +++ b/modules/globebrowsing/src/globelabelscomponent.cpp @@ -203,8 +203,8 @@ GlobeLabelsComponent::GlobeLabelsComponent() : properties::PropertyOwner({ "Labels" }) , _enabled(EnabledInfo, false) , _fontSize(FontSizeInfo, 30.f, 1.f, 300.f) - , _minMaxSize(MinMaxSizeInfo, glm::ivec2(1, 1000), glm::ivec2(1), glm::ivec2(1000)) , _size(SizeInfo, 2.5, 0, 30) + , _minMaxSize(MinMaxSizeInfo, glm::ivec2(1, 1000), glm::ivec2(1), glm::ivec2(1000)) , _heightOffset(HeightOffsetInfo, 100.f, 0.f, 10000.f) , _color(ColorInfo, glm::vec3(1.f, 1.f, 0.f), glm::vec3(0.f), glm::vec3(1.f)) , _opacity(OpacityInfo, 1.f, 0.f, 1.f) diff --git a/modules/space/translation/spicetranslation.cpp b/modules/space/translation/spicetranslation.cpp index 98cf2231ef..427409069e 100644 --- a/modules/space/translation/spicetranslation.cpp +++ b/modules/space/translation/spicetranslation.cpp @@ -101,8 +101,8 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary) : _target(TargetInfo) , _observer(ObserverInfo) , _frame(FrameInfo, DefaultReferenceFrame) - , _cachedFrame(DefaultReferenceFrame) , _fixedDate(FixedDateInfo) + , _cachedFrame(DefaultReferenceFrame) { const Parameters p = codegen::bake(dictionary); diff --git a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp index 69a86f3129..aa4d5a8dfe 100644 --- a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp +++ b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp @@ -105,8 +105,10 @@ DashboardItemInstruments::DashboardItemInstruments(const ghoul::Dictionary& dict const Parameters p = codegen::bake(dictionary); _activeColor.setViewOption(properties::Property::ViewOptions::Color); + _activeColor = p.activeColor.value_or(_activeColor); addProperty(_activeColor); _activeFlash.setViewOption(properties::Property::ViewOptions::Color); + _activeFlash = p.flashColor.value_or(_activeFlash); addProperty(_activeFlash); } diff --git a/modules/spacecraftinstruments/util/labelparser.cpp b/modules/spacecraftinstruments/util/labelparser.cpp index 4baf2c41df..0f41396d03 100644 --- a/modules/spacecraftinstruments/util/labelparser.cpp +++ b/modules/spacecraftinstruments/util/labelparser.cpp @@ -42,8 +42,7 @@ namespace { namespace openspace { -LabelParser::LabelParser(std::string name, std::string fileName, - const ghoul::Dictionary& dictionary) +LabelParser::LabelParser(std::string fileName, const ghoul::Dictionary& dictionary) : _fileName(std::move(fileName)) { // get the different instrument types diff --git a/modules/spacecraftinstruments/util/labelparser.h b/modules/spacecraftinstruments/util/labelparser.h index 7478fb236f..b6a22dfdd2 100644 --- a/modules/spacecraftinstruments/util/labelparser.h +++ b/modules/spacecraftinstruments/util/labelparser.h @@ -31,8 +31,7 @@ namespace openspace { class LabelParser : public SequenceParser { public: - LabelParser(std::string name, std::string fileName, - const ghoul::Dictionary& translationDictionary); + LabelParser(std::string fileName, const ghoul::Dictionary& translationDictionary); bool create() override; From 90157ce463475fc66409aa6961eab1c14783420a Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 30 Jul 2021 15:01:21 +0200 Subject: [PATCH 23/24] Warnings and compile fixes for MSVC --- .../src/dashboarditemglobelocation.cpp | 20 +++++++++---------- .../dashboard/dashboarditeminstruments.cpp | 4 ++-- .../util/projectioncomponent.cpp | 18 +++-------------- tests/test_configuration.cpp | 12 +++-------- 4 files changed, 18 insertions(+), 36 deletions(-) diff --git a/modules/globebrowsing/src/dashboarditemglobelocation.cpp b/modules/globebrowsing/src/dashboarditemglobelocation.cpp index f318a64a14..2189b46524 100644 --- a/modules/globebrowsing/src/dashboarditemglobelocation.cpp +++ b/modules/globebrowsing/src/dashboarditemglobelocation.cpp @@ -229,17 +229,17 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) { const bool isEast = lon > 0.0; lon = std::abs(lon); - const float latDeg = std::trunc(lat); - const float latDegRemainder = lat - latDeg; - const float latMin = std::trunc(latDegRemainder * 60.f); - const float latMinRemainder = latDegRemainder * 60.f - latMin; - const float latSec = latMinRemainder * 60.f; + const double latDeg = std::trunc(lat); + const double latDegRemainder = lat - latDeg; + const double latMin = std::trunc(latDegRemainder * 60.f); + const double latMinRemainder = latDegRemainder * 60.f - latMin; + const double latSec = latMinRemainder * 60.f; - const float lonDeg = std::trunc(lon); - const float lonDegRemainder = lon - lonDeg; - const float lonMin = std::trunc(lonDegRemainder * 60.f); - const float lonMinRemainder = lonDegRemainder * 60.f - lonMin; - const float lonSec = lonMinRemainder * 60.f; + const double lonDeg = std::trunc(lon); + const double lonDegRemainder = lon - lonDeg; + const double lonMin = std::trunc(lonDegRemainder * 60.f); + const double lonMinRemainder = lonDegRemainder * 60.f - lonMin; + const double lonSec = lonMinRemainder * 60.f; end = fmt::format_to( diff --git a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp index aa4d5a8dfe..a5c2ab1f3b 100644 --- a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp +++ b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp @@ -74,10 +74,10 @@ namespace { struct [[codegen::Dictionary(DashboardItemInstruments)]] Parameters { // [[codegen::verbatim(ActiveColorInfo.description)]] - std::optional activeColor [[codegen::color()]]; + std::optional activeColor [[codegen::color()]]; // [[codegen::verbatim(FlashColorInfo.description)]] - std::optional flashColor [[codegen::color()]]; + std::optional flashColor [[codegen::color()]]; }; #include "dashboarditeminstruments_codegen.cpp" } // namespace diff --git a/modules/spacecraftinstruments/util/projectioncomponent.cpp b/modules/spacecraftinstruments/util/projectioncomponent.cpp index 3e48f3eba8..b51cf27352 100644 --- a/modules/spacecraftinstruments/util/projectioncomponent.cpp +++ b/modules/spacecraftinstruments/util/projectioncomponent.cpp @@ -253,21 +253,13 @@ void ProjectionComponent::initialize(const std::string& identifier, break; case Parameters::Type::ImageSequence: parsers.push_back( - std::make_unique( - identifier, - std::move(source), - translations - ) + std::make_unique(std::move(source), translations) ); break; case Parameters::Type::Hybrid: // first read labels parsers.push_back( - std::make_unique( - identifier, - std::move(source), - translations - ) + std::make_unique(std::move(source), translations) ); if (p.eventFile.has_value()) { @@ -297,11 +289,7 @@ void ProjectionComponent::initialize(const std::string& identifier, case Parameters::Type::ImageAndInstrumentTimes: { parsers.push_back( - std::make_unique( - identifier, - std::move(source), - translations - ) + std::make_unique(std::move(source), translations) ); if (!p.timesSequence.has_value()) { diff --git a/tests/test_configuration.cpp b/tests/test_configuration.cpp index 25aa84be4f..c01cd9ab66 100644 --- a/tests/test_configuration.cpp +++ b/tests/test_configuration.cpp @@ -315,19 +315,19 @@ TEST_CASE("Configuration: isRenderingOnMasterDisabled", "[configuration]") { TEST_CASE("Configuration: globalRotation", "[configuration]") { constexpr const char Extra[] = R"(GlobalRotation = { 1.0, 2.0, 3.0 })"; const Configuration c = loadConfiguration("globalRotation", Extra); - CHECK(c.globalRotation == glm::dvec3(1.0, 2.0, 3.0)); + CHECK(c.globalRotation == glm::vec3(1.0, 2.0, 3.0)); } TEST_CASE("Configuration: screenSpaceRotation", "[configuration]") { constexpr const char Extra[] = R"(ScreenSpaceRotation = { 1.0, 2.0, 3.0 })"; const Configuration c = loadConfiguration("screenSpaceRotation", Extra); - CHECK(c.screenSpaceRotation == glm::dvec3(1.0, 2.0, 3.0)); + CHECK(c.screenSpaceRotation == glm::vec3(1.0, 2.0, 3.0)); } TEST_CASE("Configuration: masterRotation", "[configuration]") { constexpr const char Extra[] = R"(MasterRotation = { 1.0, 2.0, 3.0 })"; const Configuration c = loadConfiguration("masterRotation", Extra); - CHECK(c.masterRotation == glm::dvec3(1.0, 2.0, 3.0)); + CHECK(c.masterRotation == glm::vec3(1.0, 2.0, 3.0)); } TEST_CASE("Configuration: isConsoleDisabled", "[configuration]") { @@ -381,12 +381,6 @@ ModuleConfigurations = { } } -TEST_CASE("Configuration: renderingMethod", "[configuration]") { - constexpr const char Extra[] = R"(RenderingMethod = "ABuffer")"; - const Configuration c = loadConfiguration("renderingMethod", Extra); - CHECK(c.renderingMethod == "ABuffer"); -} - TEST_CASE("Configuration: openGLDebugContext", "[configuration]") { Configuration defaultConf; { From dfca605d63b5e267d5c8306bec8f558eb2a5af52 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 30 Jul 2021 15:37:03 +0200 Subject: [PATCH 24/24] Add the optional ability to print a stacktrace with an OpenGL error (closes #1700) --- include/openspace/engine/configuration.h | 1 + openspace.cfg | 1 + src/engine/configuration.cpp | 8 ++++++++ src/engine/openspaceengine.cpp | 10 ++++++++++ tests/test_configuration.cpp | 4 ++++ 5 files changed, 24 insertions(+) diff --git a/include/openspace/engine/configuration.h b/include/openspace/engine/configuration.h index daf0ac7ee4..f20b2d8900 100644 --- a/include/openspace/engine/configuration.h +++ b/include/openspace/engine/configuration.h @@ -108,6 +108,7 @@ struct Configuration { struct OpenGLDebugContext { bool isActive = false; + bool printStacktrace = false; bool isSynchronous = true; struct IdentifierFilter { std::string type; diff --git a/openspace.cfg b/openspace.cfg index b1afa57fd7..6828473069 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -238,6 +238,7 @@ ScreenSpaceRotation = { 0.0, 0.0, 0.0 } OpenGLDebugContext = { Activate = true, + PrintStacktrace = false, FilterIdentifier = { { Type = "Other", Source = "API", Identifier = 131185 }, -- API_ID_RECOMPILE_FRAGMENT_SHADER performance warning has been generated. Fragment shader recompiled due to state change diff --git a/src/engine/configuration.cpp b/src/engine/configuration.cpp index ad7b113f67..454ee1f6a3 100644 --- a/src/engine/configuration.cpp +++ b/src/engine/configuration.cpp @@ -223,6 +223,11 @@ namespace { // Determines whether the OpenGL context should be a debug context bool activate; + // If this is set to 'true', everytime an OpenGL error is logged, the full + // stacktrace leading to the error is printed as well, making debugging under + // production situations much easier + std::optional printStacktrace; + // Determines whether the OpenGL debug callbacks are performed synchronously. // If set to 'true' the callbacks are in the same thread as the context and in // the scope of the OpenGL function that triggered the message. The default @@ -478,6 +483,9 @@ void parseLuaState(Configuration& configuration) { if (p.openGLDebugContext.has_value()) { const Parameters::OpenGLDebugContext& l = *p.openGLDebugContext; c.openGLDebugContext.isActive = l.activate; + c.openGLDebugContext.printStacktrace = l.printStacktrace.value_or( + c.openGLDebugContext.printStacktrace + ); c.openGLDebugContext.isSynchronous = l.synchronous.value_or( c.openGLDebugContext.isSynchronous ); diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index b75e828183..576b6ad730 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -560,6 +561,15 @@ void OpenSpaceEngine::initializeGL() { default: throw ghoul::MissingCaseException(); } + + if (global::configuration->openGLDebugContext.printStacktrace) { + std::string stackString = "Stacktrace\n"; + std::vector stack = ghoul::stackTrace(); + for (size_t i = 0; i < stack.size(); i++) { + stackString += fmt::format("{}: {}\n", i, stack[i]); + } + LDEBUGC(category, stackString); + } }; ghoul::opengl::debug::setDebugCallback(callback); } diff --git a/tests/test_configuration.cpp b/tests/test_configuration.cpp index c01cd9ab66..b3266665d5 100644 --- a/tests/test_configuration.cpp +++ b/tests/test_configuration.cpp @@ -388,6 +388,7 @@ TEST_CASE("Configuration: openGLDebugContext", "[configuration]") { constexpr const char Extra[] = R"(OpenGLDebugContext = { Activate = true })"; const Configuration c = loadConfiguration("openGLDebugContext1", Extra); CHECK(c.openGLDebugContext.isActive == true); + CHECK(c.openGLDebugContext.printStacktrace == false); CHECK( c.openGLDebugContext.isSynchronous == defaultConf.openGLDebugContext.isSynchronous @@ -451,6 +452,7 @@ OpenGLDebugContext = { Activate = true, Synchronous = true } constexpr const char Extra[] = R"( OpenGLDebugContext = { Activate = true, + PrintStacktrace = true, FilterIdentifier = { { Identifier = 1, Source = "API", Type = "Error" }, { Identifier = 2, Source = "Window System", Type = "Deprecated" }, @@ -467,6 +469,7 @@ OpenGLDebugContext = { )"; const Configuration c = loadConfiguration("openGLDebugContext3", Extra); CHECK(c.openGLDebugContext.isActive == true); + CHECK(c.openGLDebugContext.printStacktrace == true); CHECK( c.openGLDebugContext.isSynchronous == defaultConf.openGLDebugContext.isSynchronous @@ -515,6 +518,7 @@ OpenGLDebugContext = { Activate = true, FilterSeverity = { "High", "Medium" } } )"; const Configuration c = loadConfiguration("openGLDebugContext4", Extra); CHECK(c.openGLDebugContext.isActive == true); + CHECK(c.openGLDebugContext.printStacktrace == false); CHECK( c.openGLDebugContext.isSynchronous == defaultConf.openGLDebugContext.isSynchronous