diff --git a/data/assets/scene/milkyway/milkyway/volume.asset b/data/assets/scene/milkyway/milkyway/volume.asset index 76103612b3..0e54bd1535 100644 --- a/data/assets/scene/milkyway/milkyway/volume.asset +++ b/data/assets/scene/milkyway/milkyway/volume.asset @@ -32,16 +32,16 @@ local MilkyWayVolumeGalaxy = { Rotation = { 3.1415926, 3.1248, 4.45741 }, Volume = { Type = "Volume", - Filename = data .. "/MilkyWayRGBAVolume1024x1024x128.raw", + Filename = openspace.absPath(data .. "/MilkyWayRGBAVolume1024x1024x128.raw"), Dimensions = { 1024, 1024, 128 }, Size = { 1.2E21, 1.2E21, 0.15E21 }, Downscale = 0.4, }, Points = { Type = "Points", - Filename = data .. "/MilkyWayPoints.off", + Filename = openspace.absPath(data .. "/MilkyWayPoints.off"), EnabledPointsRatio = 0.3, - Texture = data .. "/halo.png" + Texture = openspace.absPath(data .. "/halo.png") } }, GUI = { diff --git a/ext/ghoul b/ext/ghoul index 8f17cc57d9..3c0d660924 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 8f17cc57d95cb5682aed07e087feb47d06824503 +Subproject commit 3c0d660924ea66ab65703cba7f794193c3c17d67 diff --git a/modules/galaxy/rendering/renderablegalaxy.cpp b/modules/galaxy/rendering/renderablegalaxy.cpp index 5964eff426..50cff4ca7a 100644 --- a/modules/galaxy/rendering/renderablegalaxy.cpp +++ b/modules/galaxy/rendering/renderablegalaxy.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,9 @@ #include #include #include +#include #include +#include namespace { constexpr int8_t CurrentCacheVersion = 1; @@ -94,12 +97,6 @@ namespace { "" // @TODO Missing documentation }; - constexpr openspace::properties::Property::PropertyInfo TranslationInfo = { - "Translation", - "Translation", - "" // @TODO Missing documentation - }; - constexpr openspace::properties::Property::PropertyInfo RotationInfo = { "Rotation", "Euler rotation", @@ -134,6 +131,57 @@ namespace { "This value set the number of integration steps during the raycasting procedure." }; + struct [[codegen::Dictionary(RenderableGalaxy)]] Parameters { + // [[codegen::verbatim(VolumeRenderingEnabledInfo.description)]] + std::optional volumeRenderingEnabled; + + // [[codegen::verbatim(StarRenderingEnabledInfo.description)]] + std::optional starRenderingEnabled; + + // [[codegen::verbatim(StepSizeInfo.description)]] + std::optional stepSizeInfo; + + // [[codegen::verbatim(AbsorptionMultiplyInfo.description)]] + std::optional absorptionMultiply; + + // [[codegen::verbatim(EmissionMultiplyInfo.description)]] + std::optional emissionMultiply; + + enum class StarRenderingMethod { + Points, + Billboards + }; + // [[codegen::verbatim(StarRenderingMethodInfo.description)]] + std::optional starRenderingMethod; + + // [[codegen::verbatim(RotationInfo.description)]] + std::optional rotation; + + struct Volume { + std::filesystem::path filename; + glm::ivec3 dimensions; + glm::vec3 size; + + // [[codegen::verbatim(NumberOfRayCastingStepsInfo.description)]] + std::optional steps; + + // [[codegen::verbatim(DownscaleVolumeRenderingInfo.description)]] + std::optional downscale; + }; + Volume volume; + + struct Points { + std::filesystem::path filename; + std::filesystem::path texture; + + // [[codegen::verbatim(EnabledPointsRatioInfo.description)]] + std::optional enabledPointsRatio; + }; + Points points; + }; +#include "renderablegalaxy_codegen.cpp" + + void saveCachedFile(const std::string& file, const std::vector& positions, const std::vector& colors, int64_t nPoints, float pointsRatio) @@ -165,6 +213,12 @@ namespace { ); } + float safeLength(const glm::vec3& vector) { + const float maxComponent = std::max( + std::max(std::abs(vector.x), std::abs(vector.y)), std::abs(vector.z) + ); + return glm::length(vector / maxComponent) * maxComponent; + } } // namespace namespace openspace { @@ -181,7 +235,6 @@ RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary) properties::OptionProperty::DisplayType::Dropdown ) , _enabledPointsRatio(EnabledPointsRatioInfo, 0.5f, 0.01f, 1.0f) - , _translation(TranslationInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f)) , _rotation( RotationInfo, glm::vec3(0.f), @@ -191,138 +244,44 @@ RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary) , _downScaleVolumeRendering(DownscaleVolumeRenderingInfo, 1.f, 0.1f, 1.f) , _numberOfRayCastingSteps(NumberOfRayCastingStepsInfo, 1000.f, 1.f, 1000.f) { - if (dictionary.hasKey("VolumeRenderingEnabled")) { - _volumeRenderingEnabled = dictionary.value("VolumeRenderingEnabled"); - } - if (dictionary.hasKey("StarRenderingEnabled")) { - _starRenderingEnabled = dictionary.value("StarRenderingEnabled"); - } + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasKey("StarRenderingMethod")) { - _starRenderingMethod = dictionary.value("StarRenderingMethod"); - } - - if (dictionary.hasValue(VolumeRenderingEnabledInfo.identifier)) { - _volumeRenderingEnabled = dictionary.value( - VolumeRenderingEnabledInfo.identifier - ); - } - - if (dictionary.hasValue(StarRenderingEnabledInfo.identifier)) { - _starRenderingEnabled = static_cast(StarRenderingEnabledInfo.identifier); - } - - if (dictionary.hasValue(StepSizeInfo.identifier)) { - _stepSize = static_cast(dictionary.value(StepSizeInfo.identifier)); - } - - if (dictionary.hasValue(AbsorptionMultiplyInfo.identifier)) { - _absorptionMultiply = static_cast( - dictionary.value(AbsorptionMultiplyInfo.identifier) - ); - } - - if (dictionary.hasValue(EmissionMultiplyInfo.identifier)) { - _emissionMultiply = static_cast( - dictionary.value(EmissionMultiplyInfo.identifier) - ); - } + _volumeRenderingEnabled = p.volumeRenderingEnabled.value_or(_volumeRenderingEnabled); + _starRenderingEnabled = p.starRenderingEnabled.value_or(_starRenderingEnabled); + _volumeRenderingEnabled = p.volumeRenderingEnabled.value_or(_volumeRenderingEnabled); + _stepSize = p.stepSizeInfo.value_or(_stepSize); + _absorptionMultiply = p.absorptionMultiply.value_or(_absorptionMultiply); + _emissionMultiply = p.emissionMultiply.value_or(_emissionMultiply); _starRenderingMethod.addOptions({ { 0, "Points" }, { 1, "Billboards" } }); - if (dictionary.hasKey(StarRenderingMethodInfo.identifier)) { - const std::string starRenderingMethod = dictionary.value( - StarRenderingMethodInfo.identifier - ); - if (starRenderingMethod == "Points") { - _starRenderingMethod = 0; - } - else if (starRenderingMethod == "Billboards") { - _starRenderingMethod = 1; + if (p.starRenderingMethod.has_value()) { + switch (*p.starRenderingMethod) { + case Parameters::StarRenderingMethod::Points: + _starRenderingMethod = 0; + break; + case Parameters::StarRenderingMethod::Billboards: + _starRenderingMethod = 1; + break; } } - if (dictionary.hasValue(TranslationInfo.identifier)) { - _translation = dictionary.value(TranslationInfo.identifier); - } + _rotation = p.rotation.value_or(_rotation); - if (dictionary.hasValue(RotationInfo.identifier)) { - _rotation = dictionary.value(RotationInfo.identifier); - } + _volumeFilename = p.volume.filename.string(); + _volumeDimensions = p.volume.dimensions; + _volumeSize = p.volume.size; + _numberOfRayCastingSteps = p.volume.steps.value_or(_numberOfRayCastingSteps); + _downScaleVolumeRendering = p.volume.downscale.value_or(_downScaleVolumeRendering); - if (!dictionary.hasValue("Volume")) { - LERROR("No volume dictionary specified."); - } - - ghoul::Dictionary volumeDictionary = dictionary.value("Volume"); - - if (volumeDictionary.hasValue("Filename")) { - _volumeFilename = absPath(volumeDictionary.value("Filename")); - } - else { - LERROR("No volume filename specified"); - } - - if (volumeDictionary.hasValue("Dimensions")) { - _volumeDimensions = volumeDictionary.value("Dimensions"); - } - else { - LERROR("No volume dimensions specifieds"); - } - - if (volumeDictionary.hasValue("Size")) { - _volumeSize = volumeDictionary.value("Size"); - } - else { - LERROR("No volume dimensions specified."); - } - - if (volumeDictionary.hasKey(NumberOfRayCastingStepsInfo.identifier)) { - _numberOfRayCastingSteps = static_cast( - volumeDictionary.value(NumberOfRayCastingStepsInfo.identifier) - ); - } - else { - LINFO("Number of raycasting steps not specified. Using default value."); - } - - _downScaleVolumeRendering.setVisibility(properties::Property::Visibility::Developer); - if (volumeDictionary.hasKey(DownscaleVolumeRenderingInfo.identifier)) { - _downScaleVolumeRendering = static_cast( - volumeDictionary.value(DownscaleVolumeRenderingInfo.identifier) - ); - } - - if (!dictionary.hasValue("Points")) { - LERROR("No points dictionary specified."); - } - - ghoul::Dictionary pointsDictionary = dictionary.value("Points"); - if (pointsDictionary.hasValue("Filename")) { - _pointsFilename = absPath(pointsDictionary.value("Filename")); - } - else { - LERROR("No points filename specified."); - } - - if (pointsDictionary.hasValue(EnabledPointsRatioInfo.identifier)) { - _enabledPointsRatio = static_cast( - pointsDictionary.value(EnabledPointsRatioInfo.identifier) - ); - } - - if (pointsDictionary.hasValue("Texture")) { - _pointSpreadFunctionTexturePath = - absPath(pointsDictionary.value("Texture")); - _pointSpreadFunctionFile = std::make_unique( - _pointSpreadFunctionTexturePath - ); - } - else { - LERROR("No points filename specified."); - } + _pointsFilename = p.points.filename.string(); + _enabledPointsRatio = p.points.enabledPointsRatio.value_or(_enabledPointsRatio); + _pointSpreadFunctionTexturePath = p.points.texture.string(); + _pointSpreadFunctionFile = std::make_unique( + _pointSpreadFunctionTexturePath + ); auto onChange = [&](bool enabled) { if (enabled) { @@ -342,8 +301,8 @@ RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary) addProperty(_emissionMultiply); addProperty(_starRenderingMethod); addProperty(_enabledPointsRatio); - addProperty(_translation); addProperty(_rotation); + _downScaleVolumeRendering.setVisibility(properties::Property::Visibility::Developer); addProperty(_downScaleVolumeRendering); addProperty(_numberOfRayCastingSteps); } @@ -352,8 +311,8 @@ void RenderableGalaxy::initialize() { ZoneScoped // Aspect is currently hardcoded to cubic voxels. - _aspect = static_cast(_volumeDimensions); - _aspect /= std::max(std::max(_aspect.x, _aspect.y), _aspect.z); + glm::vec3 d = _volumeDimensions; + _aspect = d / glm::compMax(d); // The volume volume::RawVolumeReader> reader( @@ -379,7 +338,7 @@ void RenderableGalaxy::initialize() { } else { FileSys.cacheManager()->removeCacheFile(_pointsFilename); - Result resPoint = loadPointFile(_pointsFilename); + Result resPoint = loadPointFile(); _pointPositionsCache = std::move(resPoint.positions); _pointColorsCache = std::move(resPoint.color); saveCachedFile( @@ -392,7 +351,7 @@ void RenderableGalaxy::initialize() { } } else { - Result res = loadPointFile(_pointsFilename); + Result res = loadPointFile(); ghoul_assert(res.success, "Point file loading failed"); _pointPositionsCache = std::move(res.positions); _pointColorsCache = std::move(res.color); @@ -485,42 +444,33 @@ void RenderableGalaxy::initializeGL() { UniformNamesBillboards ); - _pointsProgram->setIgnoreUniformLocationError( - ghoul::opengl::ProgramObject::IgnoreError::Yes - ); - - GLint positionAttrib = _pointsProgram->attributeLocation("in_position"); - GLint colorAttrib = _pointsProgram->attributeLocation("in_color"); - glGenVertexArrays(1, &_pointsVao); glGenBuffers(1, &_positionVbo); glGenBuffers(1, &_colorVbo); glBindVertexArray(_pointsVao); glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); - glBufferData(GL_ARRAY_BUFFER, + glBufferData( + GL_ARRAY_BUFFER, _pointPositionsCache.size() * sizeof(glm::vec3), _pointPositionsCache.data(), GL_STATIC_DRAW ); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); _pointPositionsCache.clear(); glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); - glBufferData(GL_ARRAY_BUFFER, + glBufferData( + GL_ARRAY_BUFFER, _pointColorsCache.size() * sizeof(glm::vec3), _pointColorsCache.data(), GL_STATIC_DRAW ); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, nullptr); _pointColorsCache.clear(); - glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); - glEnableVertexAttribArray(positionAttrib); - glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); - glEnableVertexAttribArray(colorAttrib); - glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); } @@ -544,7 +494,6 @@ void RenderableGalaxy::update(const UpdateData& data) { if (!_raycaster) { return; } - //glm::mat4 transform = glm::translate(, static_cast(_translation)); const glm::vec3 eulerRotation = static_cast(_rotation); glm::mat4 transform = glm::rotate( glm::mat4(1.f), @@ -556,14 +505,6 @@ void RenderableGalaxy::update(const UpdateData& data) { glm::mat4 volumeTransform = glm::scale(transform, _volumeSize); _pointTransform = transform; - //_pointTransform = glm::scale(transform, _pointScaling); - - const glm::vec4 translation = glm::vec4(_translation.value()*_volumeSize, 0.f); - - // Todo: handle floating point overflow, to actually support translation. - - volumeTransform[3] += translation; - _pointTransform[3] += translation; _raycaster->setDownscaleRender(_downScaleVolumeRendering); _raycaster->setMaxSteps(static_cast(_numberOfRayCastingSteps)); @@ -584,7 +525,7 @@ void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { const float length = safeLength(position); const glm::vec3 galaxySize = _volumeSize; - const float maxDim = std::max(std::max(galaxySize.x, galaxySize.y), galaxySize.z); + const float maxDim = glm::compMax(galaxySize); const float lowerRampStart = maxDim * 0.01f; const float lowerRampEnd = maxDim * 0.1f; @@ -605,7 +546,7 @@ void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { } else if (length < upperRampEnd) { opacityCoefficient = 1.f - (length - upperRampStart) / - (upperRampEnd - upperRampStart); //fade out + (upperRampEnd - upperRampStart); // fade out } else { opacityCoefficient = 0; @@ -622,22 +563,23 @@ void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { } } - // Render the stars - if (_starRenderingEnabled && _opacityCoefficient > 0.f) { - if (_starRenderingMethod == 1) { + if (!(_starRenderingEnabled && _opacityCoefficient > 0.f)) { + return; + } + + if (_starRenderingMethod == 1) { + if (_billboardsProgram) { renderBillboards(data); } - else { + } + else { + if (_pointsProgram) { renderPoints(data); } } } void RenderableGalaxy::renderPoints(const RenderData& data) { - if (!_pointsProgram) { - return; - } - glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDepthMask(false); glDisable(GL_DEPTH_TEST); @@ -680,7 +622,6 @@ void RenderableGalaxy::renderPoints(const RenderData& data) { glBindVertexArray(_pointsVao); glDrawArrays(GL_POINTS, 0, static_cast(_nPoints * _enabledPointsRatio)); - glBindVertexArray(0); _pointsProgram->deactivate(); @@ -691,10 +632,6 @@ void RenderableGalaxy::renderPoints(const RenderData& data) { } void RenderableGalaxy::renderBillboards(const RenderData& data) { - if (!_billboardsProgram) { - return; - } - // Change OpenGL Blending and Depth states glBlendFunc(GL_SRC_ALPHA, GL_ONE); glDepthMask(false); @@ -742,7 +679,6 @@ void RenderableGalaxy::renderBillboards(const RenderData& data) { glBindVertexArray(_pointsVao); glDrawArrays(GL_POINTS, 0, static_cast(_nPoints * _enabledPointsRatio)); - glBindVertexArray(0); _billboardsProgram->deactivate(); @@ -752,14 +688,7 @@ void RenderableGalaxy::renderBillboards(const RenderData& data) { global::renderEngine->openglStateCache().resetDepthState(); } -float RenderableGalaxy::safeLength(const glm::vec3& vector) const { - const float maxComponent = std::max( - std::max(std::abs(vector.x), std::abs(vector.y)), std::abs(vector.z) - ); - return glm::length(vector / maxComponent) * maxComponent; -} - -RenderableGalaxy::Result RenderableGalaxy::loadPointFile(const std::string&) { +RenderableGalaxy::Result RenderableGalaxy::loadPointFile() { std::vector pointPositions; std::vector pointColors; int64_t nPoints; @@ -779,11 +708,11 @@ RenderableGalaxy::Result RenderableGalaxy::loadPointFile(const std::string&) { _nPoints = static_cast(nPoints); // Read points - float x, y, z, r, g, b, a; for (size_t i = 0; i < static_cast(_nPoints * _enabledPointsRatio.maxValue()) + 1; ++i) { + float x, y, z, r, g, b, a; std::getline(pointFile, line); std::istringstream issp(line); issp >> x >> y >> z >> r >> g >> b >> a; @@ -838,10 +767,7 @@ RenderableGalaxy::Result RenderableGalaxy::loadCachedFile(const std::string& fil fileStream.read(reinterpret_cast(&nColors), sizeof(uint64_t)); std::vector colors; colors.resize(nColors); - fileStream.read( - reinterpret_cast(colors.data()), - nColors * sizeof(glm::vec3) - ); + fileStream.read(reinterpret_cast(colors.data()), nColors * sizeof(glm::vec3)); Result result; result.success = true; diff --git a/modules/galaxy/rendering/renderablegalaxy.h b/modules/galaxy/rendering/renderablegalaxy.h index 889f2953a2..45dbcd1df7 100644 --- a/modules/galaxy/rendering/renderablegalaxy.h +++ b/modules/galaxy/rendering/renderablegalaxy.h @@ -57,14 +57,13 @@ public: private: void renderPoints(const RenderData& data); void renderBillboards(const RenderData& data); - float safeLength(const glm::vec3& vector) const; struct Result { bool success; std::vector positions; std::vector color; }; - Result loadPointFile(const std::string& file); + Result loadPointFile(); Result loadCachedFile(const std::string& file); glm::vec3 _volumeSize = glm::vec3(0.f); @@ -76,7 +75,6 @@ private: properties::FloatProperty _emissionMultiply; properties::OptionProperty _starRenderingMethod; properties::FloatProperty _enabledPointsRatio; - properties::Vec3Property _translation; properties::Vec3Property _rotation; properties::FloatProperty _downScaleVolumeRendering; properties::FloatProperty _numberOfRayCastingSteps; diff --git a/modules/galaxy/shaders/galaxyraycast.glsl b/modules/galaxy/shaders/galaxyraycast.glsl index 5bc7bcb4c6..c8d4c870fe 100644 --- a/modules/galaxy/shaders/galaxyraycast.glsl +++ b/modules/galaxy/shaders/galaxyraycast.glsl @@ -29,17 +29,13 @@ uniform float absorptionMultiply#{id} = 50.0; uniform float emissionMultiply#{id} = 1500.0; uniform sampler3D galaxyTexture#{id}; -void sample#{id}( - vec3 samplePos, - vec3 dir, - inout vec3 accumulatedColor, - inout vec3 accumulatedAlpha, - inout float stepSize - ) { +void sample#{id}(vec3 samplePos, vec3 dir, inout vec3 accumulatedColor, + inout vec3 accumulatedAlpha, inout float stepSize) +{ vec3 aspect = aspect#{id}; stepSize = maxStepSize#{id} / length(dir / aspect); - //Early ray termination on black parts of the data + // Early ray termination on black parts of the data vec3 normalizedPos = samplePos * 2.f - 1.f; if (normalizedPos.x * normalizedPos.x + normalizedPos.y * normalizedPos.y > 0.7) { return; diff --git a/modules/galaxy/shaders/points_fs.glsl b/modules/galaxy/shaders/points_fs.glsl index 025834723f..faa4974546 100644 --- a/modules/galaxy/shaders/points_fs.glsl +++ b/modules/galaxy/shaders/points_fs.glsl @@ -37,7 +37,11 @@ Fragment getFragment() { float multipliedOpacityCoefficient = opacityCoefficient*opacityCoefficient; vec3 extinction = exp(vec3(0.6, 0.2, 0.3) - vs_color); - vec4 fullColor = vec4(vs_color*extinction*vs_starBrightness*multipliedOpacityCoefficient, opacityCoefficient); + + // We use the star brightness as the alpha value here to dim the stars as the camera + // moves further away. Otherwise they would occlude the main milkway image even though + // they themselves nolonger have any color contribution left + vec4 fullColor = vec4(vs_color*extinction*vs_starBrightness*multipliedOpacityCoefficient, vs_starBrightness); frag.color = fullColor; frag.depth = vs_screenSpaceDepth; diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 70c9b8bc07..1e489a4bb6 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -556,9 +556,6 @@ void FramebufferRenderer::updateDownscaleTextures() { } void FramebufferRenderer::writeDownscaledVolume() { - glEnablei(GL_BLEND, 0); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - _downscaledVolumeProgram->activate(); ghoul::opengl::TextureUnit downscaledTextureUnit; @@ -587,7 +584,12 @@ void FramebufferRenderer::writeDownscaledVolume() { glEnablei(GL_BLEND, 0); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + // (abock, 2021-04-30) I changed the blend function as the front-to-back blending + // didn't work for the milkyway volume and was causing the edges of the milkyway to + // disappear + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_ONE, GL_ONE); glDisable(GL_DEPTH_TEST);