mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 11:09:37 -06:00
Merge pull request #1012 from OpenSpace/feature/FastVolume
Feature/fast volume
This commit is contained in:
@@ -21,7 +21,7 @@ local MilkyWayVolumeGalaxy = {
|
||||
-- The center of the Milky Way is approximately 8 kiloparsec from the Sun.
|
||||
-- The x-axis of galactic coordinates points from the sun towards the center
|
||||
-- of the galaxy.
|
||||
Position = {8 * kiloparsec, 0, 0}
|
||||
Position = { 8 * kiloparsec, 0, 0 }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
@@ -29,12 +29,13 @@ local MilkyWayVolumeGalaxy = {
|
||||
StepSize = 0.01,
|
||||
AbsorptionMultiply = 200,
|
||||
EmissionMultiply = 250,
|
||||
Rotation = {3.1415926, 3.1248, 4.45741},
|
||||
Rotation = { 3.1415926, 3.1248, 4.45741 },
|
||||
Volume = {
|
||||
Type = "Volume",
|
||||
Filename = data .. "/MilkyWayRGBAVolume1024x1024x128.raw",
|
||||
Dimensions = {1024, 1024, 128},
|
||||
Size = {1.2E21, 1.2E21, 0.15E21}
|
||||
Dimensions = { 1024, 1024, 128 },
|
||||
Size = { 1.2E21, 1.2E21, 0.15E21 },
|
||||
Downscale = 0.4,
|
||||
},
|
||||
Points = {
|
||||
Type = "Points",
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
void updateDeferredcastData();
|
||||
void updateHDRAndFiltering();
|
||||
void updateFXAA();
|
||||
void updateDownscaledVolume();
|
||||
|
||||
void setResolution(glm::ivec2 res) override;
|
||||
void setHDRExposure(float hdrExposure) override;
|
||||
@@ -110,6 +111,9 @@ private:
|
||||
void resolveMSAA(float blackoutFactor);
|
||||
void applyTMO(float blackoutFactor);
|
||||
void applyFXAA();
|
||||
void updateDownscaleTextures();
|
||||
void updateExitVolumeTextures();
|
||||
void writeDownscaledVolume();
|
||||
|
||||
std::map<VolumeRaycaster*, RaycastData> _raycastData;
|
||||
RaycasterProgObjMap _exitPrograms;
|
||||
@@ -122,10 +126,13 @@ private:
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _hdrFilteringProgram;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _tmoProgram;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _fxaaProgram;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _downscaledVolumeProgram;
|
||||
|
||||
UniformCache(hdrFeedingTexture, blackoutFactor, hdrExposure, gamma,
|
||||
Hue, Saturation, Value) _hdrUniformCache;
|
||||
UniformCache(renderedTexture, inverseScreenSize) _fxaaUniformCache;
|
||||
UniformCache(downscaledRenderedVolume, downscaledRenderedVolumeDepth)
|
||||
_writeDownscaledVolumeUniformCache;
|
||||
|
||||
GLint _defaultFBO;
|
||||
GLuint _screenQuad;
|
||||
@@ -157,6 +164,13 @@ private:
|
||||
GLuint fxaaTexture;
|
||||
} _fxaaBuffers;
|
||||
|
||||
struct {
|
||||
GLuint framebuffer;
|
||||
GLuint colorTexture;
|
||||
GLuint depthbuffer;
|
||||
float currentDownscaleFactor = 1.f;
|
||||
} _downscaleVolumeRendering;
|
||||
|
||||
unsigned int _pingPongIndex = 0u;
|
||||
|
||||
bool _dirtyDeferredcastData;
|
||||
|
||||
@@ -128,6 +128,25 @@ public:
|
||||
* helper file) which should be a prefix to all symbols defined by the helper
|
||||
*/
|
||||
virtual std::string helperPath() const = 0;
|
||||
|
||||
void setMaxSteps(int nsteps);
|
||||
|
||||
int maxSteps() const;
|
||||
|
||||
void setDownscaleRender(float value);
|
||||
|
||||
float downscaleRender() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Maximum number of integration steps to be executed by the volume integrator.
|
||||
*/
|
||||
int _rayCastMaxSteps = 1000;
|
||||
|
||||
/**
|
||||
* Enable and set the downscale rendering of the volume. Used to improve performance.
|
||||
*/
|
||||
float _downscaleRenderConst = 1.0f;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -117,6 +117,19 @@ namespace {
|
||||
"Enabled points",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo DownscaleVolumeRenderingInfo = {
|
||||
"Downscale",
|
||||
"Downscale Factor Volume Rendering",
|
||||
"This value set the downscaling factor"
|
||||
" when rendering the current volume."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NumberOfRayCastingStepsInfo = {
|
||||
"Steps",
|
||||
"Number of RayCasting Steps",
|
||||
"This value set the number of integration steps during the raycasting procedure."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -135,6 +148,8 @@ namespace openspace {
|
||||
, _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), glm::vec3(0.f), glm::vec3(6.28f))
|
||||
, _downScaleVolumeRendering(DownscaleVolumeRenderingInfo, 1.f, 0.1f, 1.f)
|
||||
, _numberOfRayCastingSteps(NumberOfRayCastingStepsInfo, 1000.f, 1.f, 1000.f)
|
||||
{
|
||||
dictionary.getValue("VolumeRenderingEnabled", _volumeRenderingEnabled);
|
||||
dictionary.getValue("StarRenderingEnabled", _starRenderingEnabled);
|
||||
@@ -224,6 +239,23 @@ namespace openspace {
|
||||
LERROR("No volume dimensions specified.");
|
||||
}
|
||||
|
||||
if (volumeDictionary.hasKey(NumberOfRayCastingStepsInfo.identifier)) {
|
||||
_numberOfRayCastingSteps = static_cast<int>(
|
||||
volumeDictionary.value<float>(NumberOfRayCastingStepsInfo.identifier)
|
||||
);
|
||||
}
|
||||
else {
|
||||
LINFO("Number of raycasting steps not specified. Using default value.");
|
||||
}
|
||||
|
||||
_downScaleVolumeRendering.setVisibility(
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
);
|
||||
if (volumeDictionary.hasKey(DownscaleVolumeRenderingInfo.identifier)) {
|
||||
_downScaleVolumeRendering =
|
||||
volumeDictionary.value<float>(DownscaleVolumeRenderingInfo.identifier);
|
||||
}
|
||||
|
||||
if (!dictionary.hasKeyAndValue<ghoul::Dictionary>("Points")) {
|
||||
LERROR("No points dictionary specified.");
|
||||
}
|
||||
@@ -307,6 +339,8 @@ void RenderableGalaxy::initializeGL() {
|
||||
addProperty(_enabledPointsRatio);
|
||||
addProperty(_translation);
|
||||
addProperty(_rotation);
|
||||
addProperty(_downScaleVolumeRendering);
|
||||
addProperty(_numberOfRayCastingSteps);
|
||||
|
||||
// initialize points.
|
||||
if (!_pointsFilename.empty()) {
|
||||
@@ -470,6 +504,8 @@ void RenderableGalaxy::update(const UpdateData& data) {
|
||||
volumeTransform[3] += translation;
|
||||
_pointTransform[3] += translation;
|
||||
|
||||
_raycaster->setDownscaleRender(_downScaleVolumeRendering);
|
||||
_raycaster->setMaxSteps(_numberOfRayCastingSteps);
|
||||
_raycaster->setStepSize(_stepSize);
|
||||
_raycaster->setAspect(_aspect);
|
||||
_raycaster->setModelTransform(volumeTransform);
|
||||
|
||||
@@ -71,6 +71,8 @@ private:
|
||||
properties::FloatProperty _enabledPointsRatio;
|
||||
properties::Vec3Property _translation;
|
||||
properties::Vec3Property _rotation;
|
||||
properties::FloatProperty _downScaleVolumeRendering;
|
||||
properties::FloatProperty _numberOfRayCastingSteps;
|
||||
|
||||
std::unique_ptr<ghoul::opengl::Texture> _pointSpreadFunctionTexture;
|
||||
std::unique_ptr<ghoul::filesystem::File> _pointSpreadFunctionFile;
|
||||
|
||||
@@ -29,17 +29,18 @@ uniform float absorptionMultiply#{id} = 50.0;
|
||||
uniform float emissionMultiply#{id} = 1500.0;
|
||||
uniform sampler3D galaxyTexture#{id};
|
||||
|
||||
void sample#{id}(vec3 samplePos,
|
||||
void sample#{id}(
|
||||
vec3 samplePos,
|
||||
vec3 dir,
|
||||
inout vec3 accumulatedColor,
|
||||
inout vec3 accumulatedAlpha,
|
||||
inout float stepSize)
|
||||
{
|
||||
inout float stepSize
|
||||
) {
|
||||
vec3 aspect = aspect#{id};
|
||||
stepSize = maxStepSize#{id} / length(dir / aspect);
|
||||
|
||||
//Early ray termination on black parts of the data
|
||||
vec3 normalizedPos = samplePos*2.0 - 1.0;
|
||||
vec3 normalizedPos = samplePos * 2.f - 1.f;
|
||||
if (normalizedPos.x * normalizedPos.x + normalizedPos.y * normalizedPos.y > 0.7) {
|
||||
return;
|
||||
}
|
||||
@@ -51,12 +52,12 @@ void sample#{id}(vec3 samplePos,
|
||||
sampledColor = sampledColor*sampledColor;
|
||||
|
||||
// Fudge for the dust "spreading"
|
||||
sampledColor.a = clamp(sampledColor.a, 0.0, 1.0);
|
||||
sampledColor.a = pow(sampledColor.a, 0.7);
|
||||
sampledColor.a = clamp(sampledColor.a, 0.f, 1.f);
|
||||
sampledColor.a = pow(sampledColor.a, 0.7f);
|
||||
|
||||
// Absorption probability
|
||||
float scaledDensity = sampledColor.a * stepSize * absorptionMultiply#{id};
|
||||
vec3 alphaTint = vec3(0.3, 0.54, 0.85);
|
||||
vec3 alphaTint = vec3(0.3f, 0.54f, 0.85f);
|
||||
vec3 absorption = alphaTint * scaledDensity;
|
||||
|
||||
// Extinction
|
||||
@@ -67,10 +68,10 @@ void sample#{id}(vec3 samplePos,
|
||||
accumulatedColor.rgb +=
|
||||
sampledColor.rgb * stepSize * emissionMultiply#{id} * opacityCoefficient#{id};
|
||||
|
||||
vec3 oneMinusFrontAlpha = vec3(1.0) - accumulatedAlpha;
|
||||
vec3 oneMinusFrontAlpha = vec3(1.f) - accumulatedAlpha;
|
||||
accumulatedAlpha += oneMinusFrontAlpha * sampledColor.rgb * opacityCoefficient#{id};
|
||||
}
|
||||
|
||||
float stepSize#{id}(vec3 samplePos, vec3 dir) {
|
||||
return maxStepSize#{id} * length(dir * 1.0 / aspect#{id});
|
||||
return maxStepSize#{id} * length(dir * 1.f / aspect#{id});
|
||||
}
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/raycastermanager.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "Renderable ToyVolume";
|
||||
constexpr openspace::properties::Property::PropertyInfo SizeInfo = {
|
||||
"Size",
|
||||
"Size",
|
||||
@@ -66,6 +68,13 @@ namespace {
|
||||
"Color",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo DownscaleVolumeRenderingInfo = {
|
||||
"Downscale",
|
||||
"Downscale Factor Volume Rendering",
|
||||
"This value set the downscaling factor"
|
||||
" when rendering the current volume."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -78,6 +87,7 @@ RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary)
|
||||
, _translation(TranslationInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(10.f))
|
||||
, _rotation(RotationInfo, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0), glm::vec3(6.28f))
|
||||
, _color(ColorInfo, glm::vec4(1.f, 0.f, 0.f, 0.1f), glm::vec4(0.f), glm::vec4(1.f))
|
||||
, _downScaleVolumeRendering(DownscaleVolumeRenderingInfo, 1.f, 0.1f, 1.f)
|
||||
{
|
||||
if (dictionary.hasKeyAndValue<double>(ScalingExponentInfo.identifier)) {
|
||||
_scalingExponent = static_cast<int>(
|
||||
@@ -104,6 +114,22 @@ RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary)
|
||||
if (dictionary.hasKeyAndValue<double>(StepSizeInfo.identifier)) {
|
||||
_stepSize = static_cast<float>(dictionary.value<double>(StepSizeInfo.identifier));
|
||||
}
|
||||
|
||||
_downScaleVolumeRendering.setVisibility(
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
);
|
||||
if (dictionary.hasKey("Downscale")) {
|
||||
_downScaleVolumeRendering = dictionary.value<float>("Downscale");
|
||||
}
|
||||
|
||||
if (dictionary.hasKey("Steps")) {
|
||||
_rayCastSteps = static_cast<int>(dictionary.value<float>("Steps"));
|
||||
}
|
||||
else {
|
||||
LINFO("Number of raycasting steps not specified for ToyVolume."
|
||||
" Using default value.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RenderableToyVolume::~RenderableToyVolume() {}
|
||||
@@ -131,6 +157,7 @@ void RenderableToyVolume::initializeGL() {
|
||||
addProperty(_translation);
|
||||
addProperty(_rotation);
|
||||
addProperty(_color);
|
||||
addProperty(_downScaleVolumeRendering);
|
||||
}
|
||||
|
||||
void RenderableToyVolume::deinitializeGL() {
|
||||
@@ -167,6 +194,8 @@ void RenderableToyVolume::update(const UpdateData& data) {
|
||||
_raycaster->setStepSize(_stepSize);
|
||||
_raycaster->setModelTransform(transform);
|
||||
_raycaster->setTime(data.time.j2000Seconds());
|
||||
_raycaster->setDownscaleRender(_downScaleVolumeRendering);
|
||||
_raycaster->setMaxSteps(_rayCastSteps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,11 @@ private:
|
||||
properties::Vec3Property _translation;
|
||||
properties::Vec3Property _rotation;
|
||||
properties::Vec4Property _color;
|
||||
properties::FloatProperty _downScaleVolumeRendering;
|
||||
|
||||
std::unique_ptr<ToyVolumeRaycaster> _raycaster;
|
||||
|
||||
int _rayCastSteps = 1000;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -38,7 +38,6 @@ uniform float Hue;
|
||||
uniform float Saturation;
|
||||
uniform float Value;
|
||||
uniform float Lightness;
|
||||
uniform int nAaSamples;
|
||||
|
||||
uniform sampler2D hdrFeedingTexture;
|
||||
|
||||
|
||||
37
shaders/framebuffer/mergeDownscaledVolume.frag
Normal file
37
shaders/framebuffer/mergeDownscaledVolume.frag
Normal file
@@ -0,0 +1,37 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#version __CONTEXT__
|
||||
|
||||
layout (location = 0) out vec4 finalColor;
|
||||
|
||||
uniform sampler2D downscaledRenderedVolume;
|
||||
uniform sampler2D downscaledRenderedVolumeDepth;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
void main() {
|
||||
finalColor = texture(downscaledRenderedVolume, texCoord);
|
||||
gl_FragDepth = texture(downscaledRenderedVolumeDepth, texCoord).r;
|
||||
}
|
||||
33
shaders/framebuffer/mergeDownscaledVolume.vert
Normal file
33
shaders/framebuffer/mergeDownscaledVolume.vert
Normal file
@@ -0,0 +1,33 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#version __CONTEXT__
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
out vec2 texCoord;
|
||||
|
||||
void main() {
|
||||
texCoord = 0.5 + position.xy * 0.5;
|
||||
gl_Position = position;
|
||||
}
|
||||
@@ -28,10 +28,11 @@ uniform sampler2D exitColorTexture;
|
||||
uniform sampler2D exitDepthTexture;
|
||||
uniform sampler2D mainDepthTexture;
|
||||
|
||||
uniform bool insideRaycaster;
|
||||
uniform vec3 cameraPosInRaycaster;
|
||||
uniform vec2 windowSize;
|
||||
|
||||
uniform int rayCastSteps;
|
||||
|
||||
#include "blending.glsl"
|
||||
#include "rand.glsl"
|
||||
#include "floatoperations.glsl"
|
||||
@@ -45,17 +46,17 @@ uniform vec2 windowSize;
|
||||
out vec4 finalColor;
|
||||
|
||||
#define ALPHA_LIMIT 0.99
|
||||
#define RAYCAST_MAX_STEPS 1000
|
||||
|
||||
#include <#{getEntryPath}>
|
||||
|
||||
void main() {
|
||||
vec2 texCoord = vec2(gl_FragCoord.xy / windowSize);
|
||||
|
||||
// Boundary position in view space
|
||||
vec4 exitColorTexture = texture(exitColorTexture, texCoord);
|
||||
|
||||
// If we don't have an exit, discard the ray
|
||||
if (exitColorTexture.a < 1.0 || exitColorTexture.rgb == vec3(0.0)) {
|
||||
if (exitColorTexture.a < 1.f || exitColorTexture.rgb == vec3(0.f)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
@@ -63,13 +64,13 @@ void main() {
|
||||
vec3 exitPos = exitColorTexture.rgb;
|
||||
float exitDepth = denormalizeFloat(texture(exitDepthTexture, texCoord).x);
|
||||
|
||||
float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0
|
||||
float jitterFactor = 0.5f + 0.5f * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0
|
||||
|
||||
vec3 entryPos;
|
||||
float entryDepth;
|
||||
getEntry(entryPos, entryDepth);
|
||||
// If we don't have an entry, discard the ray
|
||||
if (entryPos == vec3(0.0)) {
|
||||
if (entryPos == vec3(0.f)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
@@ -79,30 +80,30 @@ void main() {
|
||||
vec3 direction = normalize(diff);
|
||||
float raycastDepth = length(diff);
|
||||
|
||||
float geoDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), 0).x);
|
||||
float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.0, 1.0);
|
||||
float geoDepth = denormalizeFloat((texture(mainDepthTexture, texCoord).x));
|
||||
float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.f, 1.f);
|
||||
raycastDepth = geoRatio * raycastDepth;
|
||||
|
||||
float currentDepth = 0.0;
|
||||
float currentDepth = 0.f;
|
||||
float nextStepSize = stepSize#{id}(position, direction);
|
||||
float currentStepSize;
|
||||
float previousJitterDistance = 0.0;
|
||||
float previousJitterDistance = 0.f;
|
||||
|
||||
int nSteps = 0;
|
||||
|
||||
int sampleIndex = 0;
|
||||
float opacityDecay = 1.0;
|
||||
float opacityDecay = 1.f;
|
||||
|
||||
vec3 accumulatedColor = vec3(0.0);
|
||||
vec3 accumulatedAlpha = vec3(0.0);
|
||||
vec3 accumulatedColor = vec3(0.f);
|
||||
vec3 accumulatedAlpha = vec3(0.f);
|
||||
|
||||
|
||||
for (nSteps = 0;
|
||||
(accumulatedAlpha.r < ALPHA_LIMIT || accumulatedAlpha.g < ALPHA_LIMIT ||
|
||||
accumulatedAlpha.b < ALPHA_LIMIT) && nSteps < RAYCAST_MAX_STEPS;
|
||||
accumulatedAlpha.b < ALPHA_LIMIT) && nSteps < rayCastSteps;
|
||||
++nSteps)
|
||||
{
|
||||
if (nextStepSize < raycastDepth / 10000000000.0) {
|
||||
if (nextStepSize < raycastDepth / 10000000000.f) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ void main() {
|
||||
currentDepth += currentStepSize;
|
||||
|
||||
float jitteredStepSize = currentStepSize * jitterFactor;
|
||||
vec3 jitteredPosition = position + direction*jitteredStepSize;
|
||||
vec3 jitteredPosition = position + direction * jitteredStepSize;
|
||||
position += direction * currentStepSize;
|
||||
|
||||
sample#{id}(jitteredPosition, direction, accumulatedColor, accumulatedAlpha, nextStepSize);
|
||||
@@ -122,8 +123,9 @@ void main() {
|
||||
nextStepSize = min(nextStepSize, maxStepSize);
|
||||
}
|
||||
|
||||
finalColor = vec4(accumulatedColor, (accumulatedAlpha.r + accumulatedAlpha.g + accumulatedAlpha.b) / 3);
|
||||
finalColor = vec4(accumulatedColor, (accumulatedAlpha.r + accumulatedAlpha.g + accumulatedAlpha.b) / 3.f);
|
||||
|
||||
finalColor.rgb /= finalColor.a ;
|
||||
|
||||
gl_FragDepth = normalizeFloat(entryDepth);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ namespace {
|
||||
"renderedTexture", "inverseScreenSize"
|
||||
};
|
||||
|
||||
constexpr const std::array<const char*, 2> DownscaledVolumeUniformNames = {
|
||||
"downscaledRenderedVolume", "downscaledRenderedVolumeDepth"
|
||||
};
|
||||
|
||||
constexpr const char* ExitFragmentShaderPath =
|
||||
"${SHADERS}/framebuffer/exitframebuffer.frag";
|
||||
constexpr const char* RaycastFragmentShaderPath =
|
||||
@@ -184,6 +188,11 @@ void FramebufferRenderer::initialize() {
|
||||
glGenFramebuffers(1, &_fxaaBuffers.fxaaFramebuffer);
|
||||
glGenTextures(1, &_fxaaBuffers.fxaaTexture);
|
||||
|
||||
// DownscaleVolumeRendering
|
||||
glGenFramebuffers(1, &_downscaleVolumeRendering.framebuffer);
|
||||
glGenTextures(1, &_downscaleVolumeRendering.colorTexture);
|
||||
glGenTextures(1, &_downscaleVolumeRendering.depthbuffer);
|
||||
|
||||
// Allocate Textures/Buffers Memory
|
||||
updateResolution();
|
||||
|
||||
@@ -307,11 +316,35 @@ void FramebufferRenderer::initialize() {
|
||||
LERROR("FXAA framebuffer is not complete");
|
||||
}
|
||||
|
||||
//================================================//
|
||||
//===== Downscale Volume Rendering Buffers =====//
|
||||
//================================================//
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _downscaleVolumeRendering.framebuffer);
|
||||
glFramebufferTexture(
|
||||
GL_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
_downscaleVolumeRendering.colorTexture,
|
||||
0
|
||||
);
|
||||
glFramebufferTexture(
|
||||
GL_FRAMEBUFFER,
|
||||
GL_DEPTH_ATTACHMENT,
|
||||
_downscaleVolumeRendering.depthbuffer,
|
||||
0
|
||||
);
|
||||
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
LERROR("Downscale Volume Rendering framebuffer is not complete");
|
||||
}
|
||||
|
||||
|
||||
// JCC: Moved to here to avoid NVidia: "Program/shader state performance warning"
|
||||
// Building programs
|
||||
updateHDRAndFiltering();
|
||||
updateFXAA();
|
||||
updateDeferredcastData();
|
||||
updateDownscaledVolume();
|
||||
|
||||
// Sets back to default FBO
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO);
|
||||
@@ -326,6 +359,11 @@ void FramebufferRenderer::initialize() {
|
||||
_fxaaUniformCache,
|
||||
FXAAUniformNames
|
||||
);
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*_downscaledVolumeProgram,
|
||||
_writeDownscaledVolumeUniformCache,
|
||||
DownscaledVolumeUniformNames
|
||||
);
|
||||
|
||||
global::raycasterManager.addListener(*this);
|
||||
global::deferredcasterManager.addListener(*this);
|
||||
@@ -342,6 +380,7 @@ void FramebufferRenderer::deinitialize() {
|
||||
glDeleteFramebuffers(1, &_hdrBuffers.hdrFilteringFramebuffer);
|
||||
glDeleteFramebuffers(1, &_fxaaBuffers.fxaaFramebuffer);
|
||||
glDeleteFramebuffers(1, &_pingPongBuffers.framebuffer);
|
||||
glDeleteFramebuffers(1, &_downscaleVolumeRendering.framebuffer);
|
||||
|
||||
glDeleteTextures(1, &_gBuffers.colorTexture);
|
||||
glDeleteTextures(1, &_gBuffers.depthTexture);
|
||||
@@ -350,7 +389,9 @@ void FramebufferRenderer::deinitialize() {
|
||||
glDeleteTextures(1, &_fxaaBuffers.fxaaTexture);
|
||||
glDeleteTextures(1, &_gBuffers.positionTexture);
|
||||
glDeleteTextures(1, &_gBuffers.normalTexture);
|
||||
|
||||
glDeleteTextures(1, &_downscaleVolumeRendering.colorTexture);
|
||||
glDeleteTextures(1, &_downscaleVolumeRendering.depthbuffer);
|
||||
|
||||
glDeleteTextures(1, &_pingPongBuffers.colorTexture[1]);
|
||||
|
||||
glDeleteTextures(1, &_exitColorTexture);
|
||||
@@ -459,6 +500,124 @@ void FramebufferRenderer::applyFXAA() {
|
||||
_fxaaProgram->deactivate();
|
||||
}
|
||||
|
||||
void FramebufferRenderer::updateDownscaleTextures() {
|
||||
glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.colorTexture);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA32F,
|
||||
_resolution.x * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
_resolution.y * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
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);
|
||||
float volumeBorderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, volumeBorderColor);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.depthbuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_DEPTH_COMPONENT32F,
|
||||
_resolution.x * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
_resolution.y * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
0,
|
||||
GL_DEPTH_COMPONENT,
|
||||
GL_FLOAT,
|
||||
nullptr
|
||||
);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
void FramebufferRenderer::writeDownscaledVolume() {
|
||||
const bool doPerformanceMeasurements = global::performanceManager.isEnabled();
|
||||
std::unique_ptr<performance::PerformanceMeasurement> perfInternal;
|
||||
|
||||
if (doPerformanceMeasurements) {
|
||||
perfInternal = std::make_unique<performance::PerformanceMeasurement>(
|
||||
"FramebufferRenderer::render::writeDownscaledVolume"
|
||||
);
|
||||
}
|
||||
|
||||
// Saving current OpenGL state
|
||||
GLboolean blendEnabled = glIsEnabledi(GL_BLEND, 0);
|
||||
|
||||
GLenum blendEquationRGB;
|
||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
|
||||
|
||||
GLenum blendEquationAlpha;
|
||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
|
||||
|
||||
GLenum blendDestAlpha;
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
|
||||
|
||||
GLenum blendDestRGB;
|
||||
glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB);
|
||||
|
||||
GLenum blendSrcAlpha;
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
|
||||
|
||||
GLenum blendSrcRGB;
|
||||
glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB);
|
||||
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
_downscaledVolumeProgram->activate();
|
||||
|
||||
ghoul::opengl::TextureUnit downscaledTextureUnit;
|
||||
downscaledTextureUnit.activate();
|
||||
glBindTexture(
|
||||
GL_TEXTURE_2D,
|
||||
_downscaleVolumeRendering.colorTexture
|
||||
);
|
||||
|
||||
_downscaledVolumeProgram->setUniform(
|
||||
_writeDownscaledVolumeUniformCache.downscaledRenderedVolume,
|
||||
downscaledTextureUnit
|
||||
);
|
||||
|
||||
ghoul::opengl::TextureUnit downscaledDepthUnit;
|
||||
downscaledDepthUnit.activate();
|
||||
glBindTexture(
|
||||
GL_TEXTURE_2D,
|
||||
_downscaleVolumeRendering.depthbuffer
|
||||
);
|
||||
|
||||
_downscaledVolumeProgram->setUniform(
|
||||
_writeDownscaledVolumeUniformCache.downscaledRenderedVolumeDepth,
|
||||
downscaledDepthUnit
|
||||
);
|
||||
|
||||
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glBindVertexArray(_screenQuad);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
_downscaledVolumeProgram->deactivate();
|
||||
|
||||
// Restores blending state
|
||||
glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha);
|
||||
glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha);
|
||||
|
||||
if (!blendEnabled) {
|
||||
glDisablei(GL_BLEND, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FramebufferRenderer::update() {
|
||||
if (_dirtyResolution) {
|
||||
updateResolution();
|
||||
@@ -492,6 +651,16 @@ void FramebufferRenderer::update() {
|
||||
);
|
||||
}
|
||||
|
||||
if (_downscaledVolumeProgram->isDirty()) {
|
||||
_downscaledVolumeProgram->rebuildFromFile();
|
||||
|
||||
ghoul::opengl::updateUniformLocations(
|
||||
*_downscaledVolumeProgram,
|
||||
_writeDownscaledVolumeUniformCache,
|
||||
DownscaledVolumeUniformNames
|
||||
);
|
||||
}
|
||||
|
||||
using K = VolumeRaycaster*;
|
||||
using V = std::unique_ptr<ghoul::opengl::ProgramObject>;
|
||||
for (const std::pair<const K, V>& program : _exitPrograms) {
|
||||
@@ -651,6 +820,39 @@ void FramebufferRenderer::updateResolution() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
// Downscale Volume Rendering
|
||||
glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.colorTexture);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA32F,
|
||||
_resolution.x * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
_resolution.y * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
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);
|
||||
float volumeBorderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, volumeBorderColor);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.depthbuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_DEPTH_COMPONENT32F,
|
||||
_resolution.x * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
_resolution.y * _downscaleVolumeRendering.currentDownscaleFactor,
|
||||
0,
|
||||
GL_DEPTH_COMPONENT,
|
||||
GL_FLOAT,
|
||||
nullptr
|
||||
);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
// Volume Rendering Textures
|
||||
glBindTexture(GL_TEXTURE_2D, _exitColorTexture);
|
||||
glTexImage2D(
|
||||
@@ -834,6 +1036,17 @@ void FramebufferRenderer::updateFXAA() {
|
||||
//_fxaaProgram->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
void FramebufferRenderer::updateDownscaledVolume() {
|
||||
_downscaledVolumeProgram = ghoul::opengl::ProgramObject::Build(
|
||||
"Write Downscaled Volume Program",
|
||||
absPath("${SHADERS}/framebuffer/mergeDownscaledVolume.vert"),
|
||||
absPath("${SHADERS}/framebuffer/mergeDownscaledVolume.frag")
|
||||
);
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
//_downscaledVolumeProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes);
|
||||
//_downscaledVolumeProgram->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFactor) {
|
||||
// Set OpenGL default rendering state
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO);
|
||||
@@ -959,7 +1172,20 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector<RaycasterTask>
|
||||
exitProgram->deactivate();
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers.framebuffer);
|
||||
if (raycaster->downscaleRender() < 1.f) {
|
||||
float scaleDown = raycaster->downscaleRender();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _downscaleVolumeRendering.framebuffer);
|
||||
glViewport(0, 0, _resolution.x * scaleDown, _resolution.y * scaleDown);
|
||||
if (_downscaleVolumeRendering.currentDownscaleFactor != scaleDown) {
|
||||
_downscaleVolumeRendering.currentDownscaleFactor = scaleDown;
|
||||
updateDownscaleTextures();
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers.framebuffer);
|
||||
}
|
||||
|
||||
glm::vec3 cameraPosition;
|
||||
bool isCameraInside = raycaster->isCameraInside(
|
||||
raycasterTask.renderData,
|
||||
@@ -991,6 +1217,8 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector<RaycasterTask>
|
||||
}
|
||||
|
||||
if (raycastProgram) {
|
||||
raycastProgram->setUniform("rayCastSteps", raycaster->maxSteps());
|
||||
|
||||
raycaster->preRaycast(_raycastData[raycaster], *raycastProgram);
|
||||
|
||||
ghoul::opengl::TextureUnit exitColorTextureUnit;
|
||||
@@ -1008,7 +1236,16 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector<RaycasterTask>
|
||||
glBindTexture(GL_TEXTURE_2D, _gBuffers.depthTexture);
|
||||
raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit);
|
||||
|
||||
raycastProgram->setUniform("windowSize", static_cast<glm::vec2>(_resolution));
|
||||
if (raycaster->downscaleRender() < 1.f) {
|
||||
float scaleDown = raycaster->downscaleRender();
|
||||
raycastProgram->setUniform(
|
||||
"windowSize",
|
||||
glm::vec2(_resolution.x * scaleDown, _resolution.y * scaleDown)
|
||||
);
|
||||
}
|
||||
else {
|
||||
raycastProgram->setUniform("windowSize", static_cast<glm::vec2>(_resolution));
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
@@ -1029,12 +1266,17 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector<RaycasterTask>
|
||||
else {
|
||||
LWARNING("Raycaster is not attached when trying to perform raycaster task");
|
||||
}
|
||||
|
||||
if (raycaster->downscaleRender() < 1.f) {
|
||||
glViewport(0, 0, _resolution.x, _resolution.y);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _gBuffers.framebuffer);
|
||||
writeDownscaledVolume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferRenderer::performDeferredTasks(
|
||||
const std::vector<DeferredcasterTask>& tasks
|
||||
)
|
||||
const std::vector<DeferredcasterTask>& tasks)
|
||||
{
|
||||
for (const DeferredcasterTask& deferredcasterTask : tasks) {
|
||||
Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster;
|
||||
|
||||
@@ -33,4 +33,20 @@ bool VolumeRaycaster::isCameraInside(const RenderData&, glm::vec3&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void VolumeRaycaster::setMaxSteps(int nsteps) {
|
||||
_rayCastMaxSteps = nsteps;
|
||||
}
|
||||
|
||||
int VolumeRaycaster::maxSteps() const {
|
||||
return _rayCastMaxSteps;
|
||||
}
|
||||
|
||||
void VolumeRaycaster::setDownscaleRender(float value) {
|
||||
_downscaleRenderConst = value;
|
||||
}
|
||||
|
||||
float VolumeRaycaster::downscaleRender() const {
|
||||
return _downscaleRenderConst;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user