Merge pull request #1012 from OpenSpace/feature/FastVolume

Feature/fast volume
This commit is contained in:
Alexander Bock
2019-12-16 09:52:00 +01:00
committed by GitHub
14 changed files with 469 additions and 35 deletions

View File

@@ -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",

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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});
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -38,7 +38,6 @@ uniform float Hue;
uniform float Saturation;
uniform float Value;
uniform float Lightness;
uniform int nAaSamples;
uniform sampler2D hdrFeedingTexture;

View 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;
}

View 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;
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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