mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 03:42:45 +02:00
Quarter resolution with split rendering
This commit is contained in:
parent
3493d40fd7
commit
8a11d18f0d
11 changed files with 194 additions and 91 deletions
|
@ -35,6 +35,7 @@ gpu::PipelinePointer AmbientOcclusionEffect::_hBlurPipeline;
|
|||
gpu::PipelinePointer AmbientOcclusionEffect::_vBlurPipeline;
|
||||
gpu::PipelinePointer AmbientOcclusionEffect::_mipCreationPipeline;
|
||||
gpu::PipelinePointer AmbientOcclusionEffect::_gatherPipeline;
|
||||
gpu::PipelinePointer AmbientOcclusionEffect::_buildNormalsPipeline;
|
||||
|
||||
AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() {
|
||||
}
|
||||
|
@ -66,6 +67,8 @@ void AmbientOcclusionFramebuffer::clear() {
|
|||
_occlusionTexture.reset();
|
||||
_occlusionBlurredFramebuffer.reset();
|
||||
_occlusionBlurredTexture.reset();
|
||||
_normalFramebuffer.reset();
|
||||
_normalTexture.reset();
|
||||
}
|
||||
|
||||
gpu::TexturePointer AmbientOcclusionFramebuffer::getLinearDepthTexture() {
|
||||
|
@ -73,18 +76,21 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getLinearDepthTexture() {
|
|||
}
|
||||
|
||||
void AmbientOcclusionFramebuffer::allocate() {
|
||||
|
||||
auto width = _frameSize.x;
|
||||
auto height = _frameSize.y;
|
||||
auto format = gpu::Element::COLOR_R_8;
|
||||
|
||||
_occlusionTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP));
|
||||
_occlusionTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
|
||||
_occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
|
||||
_occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture);
|
||||
|
||||
_occlusionBlurredTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP));
|
||||
_occlusionBlurredTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
|
||||
_occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred"));
|
||||
_occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture);
|
||||
|
||||
_normalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_R11G11B10, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP));
|
||||
_normalFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("ssaoNormals"));
|
||||
_normalFramebuffer->setRenderBuffer(0, _normalTexture);
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getOcclusionFramebuffer() {
|
||||
|
@ -115,6 +121,19 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getOcclusionBlurredTexture() {
|
|||
return _occlusionBlurredTexture;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getNormalFramebuffer() {
|
||||
if (!_normalFramebuffer) {
|
||||
allocate();
|
||||
}
|
||||
return _normalFramebuffer;
|
||||
}
|
||||
|
||||
gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
|
||||
if (!_normalTexture) {
|
||||
allocate();
|
||||
}
|
||||
return _normalTexture;
|
||||
}
|
||||
|
||||
class GaussianDistribution {
|
||||
public:
|
||||
|
@ -189,11 +208,11 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
|
|||
blurDeviation{ 2.5f },
|
||||
numSpiralTurns{ 7.0f },
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
numSamples{ 1 },
|
||||
numSamples{ 2 },
|
||||
#else
|
||||
numSamples{ 16 },
|
||||
#endif
|
||||
resolutionLevel{ 1 },
|
||||
resolutionLevel{ 2 },
|
||||
blurRadius{ 4 },
|
||||
ditheringEnabled{ true },
|
||||
borderingEnabled{ true },
|
||||
|
@ -262,8 +281,8 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
current.x = config.numSamples;
|
||||
current.y = 1.0f / config.numSamples;
|
||||
|
||||
// Regenerate halton sequence
|
||||
const int B = config.numSamples + 1;
|
||||
// Regenerate offsets
|
||||
const int B = 3;
|
||||
const float invB = 1.0f / (float)B;
|
||||
|
||||
for (int i = 0; i < _randomSamples.size(); i++) {
|
||||
|
@ -276,7 +295,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
r = r + f * (float)(index % B);
|
||||
index = index / B;
|
||||
}
|
||||
_randomSamples[i] = r;
|
||||
_randomSamples[i] = r * M_PI / config.numSamples;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,7 +315,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
|
||||
if (config.resolutionLevel != _aoParametersBuffer->getResolutionLevel()) {
|
||||
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
|
||||
current.x = (float) config.resolutionLevel;
|
||||
current.x = (float)config.resolutionLevel;
|
||||
shouldUpdateBlurs = true;
|
||||
|
||||
_aoFrameParametersBuffer[0].edit()._pixelOffsets = { 0, 0, 0, 0 };
|
||||
|
@ -307,7 +326,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
#endif
|
||||
}
|
||||
|
||||
if (config.blurRadius != _aoParametersBuffer->getBlurRadius()) {
|
||||
if (config.blurRadius != _aoParametersBuffer.get().getBlurRadius()) {
|
||||
auto& current = _aoParametersBuffer.edit()._blurInfo;
|
||||
current.y = (float)config.blurRadius;
|
||||
shouldUpdateGaussian = true;
|
||||
|
@ -361,7 +380,6 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() {
|
|||
return _occlusionPipeline;
|
||||
}
|
||||
|
||||
|
||||
const gpu::PipelinePointer& AmbientOcclusionEffect::getHBlurPipeline() {
|
||||
if (!_hBlurPipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_makeHorizontalBlur);
|
||||
|
@ -409,9 +427,24 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getGatherPipeline() {
|
|||
return _gatherPipeline;
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& AmbientOcclusionEffect::getBuildNormalsPipeline() {
|
||||
if (!_buildNormalsPipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_buildNormals);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
state->setColorWriteMask(true, true, true, false);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
_buildNormalsPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return _buildNormalsPipeline;
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::updateGaussianDistribution() {
|
||||
auto coefs = _aoParametersBuffer.edit()._gaussianCoefs;
|
||||
GaussianDistribution::evalSampling(coefs, SSAO_BLUR_GAUSSIAN_COEFS_COUNT, _aoParametersBuffer->getBlurRadius(), _aoParametersBuffer->getBlurDeviation());
|
||||
auto filterTaps = _aoParametersBuffer.edit()._blurFilterTaps;
|
||||
auto blurRadius = _aoParametersBuffer.get().getBlurRadius();
|
||||
|
||||
GaussianDistribution::evalSampling(filterTaps, SSAO_BLUR_GAUSSIAN_COEFS_COUNT, blurRadius, _aoParametersBuffer->getBlurDeviation() * 4.0f / blurRadius);
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
|
@ -436,7 +469,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
if (!_framebuffer) {
|
||||
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
||||
}
|
||||
|
||||
|
||||
const auto resolutionScale = powf(0.5f, _aoParametersBuffer->getResolutionLevel());
|
||||
if (_aoParametersBuffer->getResolutionLevel() > 0) {
|
||||
occlusionViewport = occlusionViewport >> _aoParametersBuffer->getResolutionLevel();
|
||||
|
@ -464,15 +497,19 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
#endif
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
auto gatherPipeline = getGatherPipeline();
|
||||
auto buildNormalsPipeline = getBuildNormalsPipeline();
|
||||
auto occlusionNormalFramebuffer = _framebuffer->getNormalFramebuffer();
|
||||
auto occlusionNormalTexture = _framebuffer->getNormalTexture();
|
||||
#endif
|
||||
auto fullNormalTexture = linearDepthFramebuffer->getNormalTexture();
|
||||
|
||||
// Update sample rotation
|
||||
const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / SSAO_SPLIT_COUNT);
|
||||
for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT ; splitId++) {
|
||||
auto& sample = _aoFrameParametersBuffer[splitId].edit();
|
||||
sample._angleInfo.x = _randomSamples[_frameId + SSAO_RANDOM_SAMPLE_COUNT * splitId] * M_PI;
|
||||
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
|
||||
}
|
||||
_frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
|
||||
// TEMPO OP _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
|
||||
|
||||
gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "AmbientOcclusion");
|
||||
|
@ -480,7 +517,6 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
|
||||
_gpuTimer->begin(batch);
|
||||
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
|
||||
Transform model;
|
||||
|
@ -490,53 +526,67 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
// We need this with the mips levels
|
||||
batch.pushProfileRange("Depth mip creation");
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
batch.setPipeline(mipCreationPipeline);
|
||||
batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
|
||||
batch.setPipeline(mipCreationPipeline);
|
||||
batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
|
||||
#else
|
||||
batch.generateTextureMips(occlusionDepthTexture);
|
||||
batch.generateTextureMips(occlusionDepthTexture);
|
||||
#endif
|
||||
batch.popProfileRange();
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
// Build derivative normals pass
|
||||
batch.pushProfileRange("Build Normals");
|
||||
batch.setViewportTransform(sourceViewport);
|
||||
batch.setPipeline(buildNormalsPipeline);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
|
||||
batch.setFramebuffer(occlusionNormalFramebuffer);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.popProfileRange();
|
||||
#endif
|
||||
|
||||
// Occlusion pass
|
||||
batch.pushProfileRange("Occlusion");
|
||||
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
batch.setFramebuffer(occlusionBlurredFBO);
|
||||
batch.setFramebuffer(occlusionBlurredFBO);
|
||||
#else
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
#endif
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(1.0f));
|
||||
batch.setPipeline(occlusionPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, occlusionDepthTexture);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(1.0f));
|
||||
batch.setPipeline(occlusionPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, occlusionDepthTexture);
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
{
|
||||
auto splitViewport = occlusionViewport >> SSAO_USE_QUAD_SPLIT;
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
||||
{
|
||||
auto splitViewport = occlusionViewport >> SSAO_USE_QUAD_SPLIT;
|
||||
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
splitViewport.x += splitViewport.z;
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
splitViewport.y += splitViewport.w;
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
splitViewport.x = 0;
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
#else
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
splitViewport.x += splitViewport.z;
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
splitViewport.y += splitViewport.w;
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
splitViewport.x = 0;
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
#else
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
#endif
|
||||
|
||||
batch.popProfileRange();
|
||||
|
@ -544,11 +594,11 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
#if SSAO_USE_QUAD_SPLIT
|
||||
// Gather back the four separate renders into one interleaved one
|
||||
batch.pushProfileRange("Gather");
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setPipeline(gatherPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setPipeline(gatherPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.popProfileRange();
|
||||
#endif
|
||||
|
||||
|
@ -561,6 +611,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
batch.setFramebuffer(occlusionBlurredFBO);
|
||||
// Use full resolution depth and normal for bilateral upscaling and blur
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, fullNormalTexture);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _hblurParametersBuffer);
|
||||
batch.setPipeline(firstHBlurPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionFBO->getRenderBuffer(0));
|
||||
|
|
|
@ -30,7 +30,10 @@ public:
|
|||
|
||||
gpu::FramebufferPointer getOcclusionBlurredFramebuffer();
|
||||
gpu::TexturePointer getOcclusionBlurredTexture();
|
||||
|
||||
|
||||
gpu::FramebufferPointer getNormalFramebuffer();
|
||||
gpu::TexturePointer getNormalTexture();
|
||||
|
||||
// Update the source framebuffer size which will drive the allocation of all the other resources.
|
||||
bool updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer);
|
||||
gpu::TexturePointer getLinearDepthTexture();
|
||||
|
@ -44,10 +47,13 @@ protected:
|
|||
|
||||
gpu::FramebufferPointer _occlusionFramebuffer;
|
||||
gpu::TexturePointer _occlusionTexture;
|
||||
|
||||
|
||||
gpu::FramebufferPointer _occlusionBlurredFramebuffer;
|
||||
gpu::TexturePointer _occlusionBlurredTexture;
|
||||
|
||||
|
||||
gpu::FramebufferPointer _normalFramebuffer;
|
||||
gpu::TexturePointer _normalTexture;
|
||||
|
||||
|
||||
glm::ivec2 _frameSize;
|
||||
};
|
||||
|
@ -168,12 +174,14 @@ private:
|
|||
static const gpu::PipelinePointer& getVBlurPipeline(); // second
|
||||
static const gpu::PipelinePointer& getMipCreationPipeline();
|
||||
static const gpu::PipelinePointer& getGatherPipeline();
|
||||
static const gpu::PipelinePointer& getBuildNormalsPipeline();
|
||||
|
||||
static gpu::PipelinePointer _occlusionPipeline;
|
||||
static gpu::PipelinePointer _hBlurPipeline;
|
||||
static gpu::PipelinePointer _vBlurPipeline;
|
||||
static gpu::PipelinePointer _mipCreationPipeline;
|
||||
static gpu::PipelinePointer _gatherPipeline;
|
||||
static gpu::PipelinePointer _buildNormalsPipeline;
|
||||
|
||||
AmbientOcclusionFramebufferPointer _framebuffer;
|
||||
std::array<float, 16 * SSAO_SPLIT_COUNT> _randomSamples;
|
||||
|
|
|
@ -28,11 +28,12 @@ namespace ru {
|
|||
LinearDepthFramebuffer::LinearDepthFramebuffer() {
|
||||
}
|
||||
|
||||
void LinearDepthFramebuffer::update(const gpu::TexturePointer& depthBuffer) {
|
||||
void LinearDepthFramebuffer::update(const gpu::TexturePointer& depthBuffer, const gpu::TexturePointer& normalTexture) {
|
||||
//If the depth buffer or size changed, we need to delete our FBOs
|
||||
bool reset = false;
|
||||
if (_primaryDepthTexture != depthBuffer) {
|
||||
if (_primaryDepthTexture != depthBuffer || _normalTexture != normalTexture) {
|
||||
_primaryDepthTexture = depthBuffer;
|
||||
_normalTexture = normalTexture;
|
||||
reset = true;
|
||||
}
|
||||
if (_primaryDepthTexture) {
|
||||
|
@ -100,6 +101,10 @@ gpu::TexturePointer LinearDepthFramebuffer::getLinearDepthTexture() {
|
|||
return _linearDepthTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer LinearDepthFramebuffer::getNormalTexture() {
|
||||
return _normalTexture;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer LinearDepthFramebuffer::getDownsampleFramebuffer() {
|
||||
if (!_downsampleFramebuffer) {
|
||||
allocate();
|
||||
|
@ -148,7 +153,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
|
|||
auto depthBuffer = deferredFramebuffer->getPrimaryDepthTexture();
|
||||
auto normalTexture = deferredFramebuffer->getDeferredNormalTexture();
|
||||
|
||||
_linearDepthFramebuffer->update(depthBuffer);
|
||||
_linearDepthFramebuffer->update(depthBuffer, normalTexture);
|
||||
|
||||
auto linearDepthFBO = _linearDepthFramebuffer->getLinearDepthFramebuffer();
|
||||
auto linearDepthTexture = _linearDepthFramebuffer->getLinearDepthTexture();
|
||||
|
|
|
@ -28,13 +28,14 @@ public:
|
|||
|
||||
gpu::FramebufferPointer getLinearDepthFramebuffer();
|
||||
gpu::TexturePointer getLinearDepthTexture();
|
||||
gpu::TexturePointer getNormalTexture();
|
||||
|
||||
gpu::FramebufferPointer getDownsampleFramebuffer();
|
||||
gpu::TexturePointer getHalfLinearDepthTexture();
|
||||
gpu::TexturePointer getHalfNormalTexture();
|
||||
|
||||
// Update the depth buffer which will drive the allocation of all the other resources according to its size.
|
||||
void update(const gpu::TexturePointer& depthBuffer);
|
||||
void update(const gpu::TexturePointer& depthBuffer, const gpu::TexturePointer& normalTexture);
|
||||
const glm::ivec2& getDepthFrameSize() const { return _frameSize; }
|
||||
|
||||
void setResolutionLevel(int level) { _resolutionLevel = std::max(0, level); }
|
||||
|
@ -48,6 +49,7 @@ protected:
|
|||
|
||||
gpu::FramebufferPointer _linearDepthFramebuffer;
|
||||
gpu::TexturePointer _linearDepthTexture;
|
||||
gpu::TexturePointer _normalTexture;
|
||||
|
||||
gpu::FramebufferPointer _downsampleFramebuffer;
|
||||
gpu::TexturePointer _halfLinearDepthTexture;
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#define RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS 4
|
||||
#define RENDER_UTILS_BUFFER_SSAO_FRAME_PARAMS 5
|
||||
#define RENDER_UTILS_TEXTURE_SSAO_DEPTH 1
|
||||
#define RENDER_UTILS_TEXTURE_SSAO_NORMAL 2
|
||||
#define RENDER_UTILS_TEXTURE_SSAO_OCCLUSION 0
|
||||
|
||||
// Temporal anti-aliasing
|
||||
|
@ -196,6 +197,7 @@ enum Texture {
|
|||
TaaNext = RENDER_UTILS_TEXTURE_TAA_NEXT,
|
||||
SsaoOcclusion = RENDER_UTILS_TEXTURE_SSAO_OCCLUSION,
|
||||
SsaoDepth = RENDER_UTILS_TEXTURE_SSAO_DEPTH,
|
||||
SsaoNormal = RENDER_UTILS_TEXTURE_SSAO_NORMAL,
|
||||
HighlightSceneDepth = RENDER_UTILS_TEXTURE_HIGHLIGHT_SCENE_DEPTH,
|
||||
HighlightDepth = RENDER_UTILS_TEXTURE_HIGHLIGHT_DEPTH,
|
||||
SurfaceGeometryDepth = RENDER_UTILS_TEXTURE_SG_DEPTH,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord
|
|
@ -98,32 +98,13 @@ float getBlurEdgeSharpness() {
|
|||
return params._blurInfo.x;
|
||||
}
|
||||
|
||||
#ifdef CONSTANT_GAUSSIAN
|
||||
const int BLUR_RADIUS = 4;
|
||||
const float gaussian[BLUR_RADIUS + 1] =
|
||||
// KEEP this dead code for eventual performance improvment
|
||||
// float[](0.356642, 0.239400, 0.072410, 0.009869);
|
||||
// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
|
||||
float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
|
||||
//float[](0.197413, 0.17467, 0.12098,0.065591,0.040059);
|
||||
// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
|
||||
|
||||
int getBlurRadius() {
|
||||
return BLUR_RADIUS;
|
||||
}
|
||||
|
||||
float getBlurCoef(int c) {
|
||||
return gaussian[c];
|
||||
}
|
||||
#else
|
||||
int getBlurRadius() {
|
||||
return int(params._blurInfo.y);
|
||||
}
|
||||
|
||||
float getBlurCoef(int c) {
|
||||
return params._gaussianCoefs[c];
|
||||
return params._blurFilterTaps[c];
|
||||
}
|
||||
#endif
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
|
@ -219,6 +200,7 @@ vec3 getTapLocationClampedSSAO(int sampleNumber, float spinAngle, float outerRad
|
|||
|
||||
// the depth pyramid texture
|
||||
layout(binding=RENDER_UTILS_TEXTURE_SSAO_DEPTH) uniform sampler2D depthPyramidTex;
|
||||
layout(binding=RENDER_UTILS_TEXTURE_SSAO_NORMAL) uniform sampler2D normalTex;
|
||||
|
||||
float getZEyeAtPixel(ivec2 pixel, int level) {
|
||||
return -texelFetch(depthPyramidTex, pixel, level).x;
|
||||
|
@ -228,8 +210,12 @@ float getZEyeAtUV(vec2 texCoord, int level) {
|
|||
return -texture(depthPyramidTex, texCoord, level).x;
|
||||
}
|
||||
|
||||
vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
|
||||
return normalize(texture(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
|
||||
}
|
||||
|
||||
int evalMipFromRadius(float radius) {
|
||||
const int LOG_MAX_OFFSET = 1;
|
||||
const int LOG_MAX_OFFSET = 2;
|
||||
const int MAX_MIP_LEVEL = 5;
|
||||
return clamp(findMSB(int(radius)) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
|
||||
}
|
||||
|
@ -406,24 +392,22 @@ float fetchOcclusion(vec2 coords) {
|
|||
return raw.x;
|
||||
}
|
||||
|
||||
const float BLUR_WEIGHT_OFFSET = 0.01;
|
||||
const float BLUR_EDGE_DISTANCE_SCALE = 300.0;
|
||||
|
||||
vec2 evalTapWeightedValue(ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float fragDepth) {
|
||||
ivec2 tapOffset = <$axis$> * r;
|
||||
ivec2 tapPixelCoord = destPixelCoord + tapOffset;
|
||||
ivec2 tapPixelCoord = destPixelCoord + ivec2(tapOffset);
|
||||
|
||||
if ((tapPixelCoord.x < side.y || tapPixelCoord.x >= side.z + side.y) || (tapPixelCoord.y < 0 || tapPixelCoord.y >= getBlurImageHeight())) {
|
||||
return vec2(0.0);
|
||||
}
|
||||
|
||||
vec2 tapTexCoord = scaledTexCoord + tapOffset * getOcclusionBlurScale();
|
||||
float tapOcclusion = fetchOcclusion(tapTexCoord);
|
||||
|
||||
tapTexCoord = fullTexCoord + tapOffset * getDepthBlurScale();
|
||||
float tapDepth = getZEyeAtUV(tapTexCoord, 0);
|
||||
|
||||
// spatial domain: offset gaussian tap
|
||||
float weight = BLUR_WEIGHT_OFFSET + getBlurCoef(abs(r));
|
||||
float weight = getBlurCoef(abs(r));
|
||||
|
||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
||||
float zDistance = tapDepth - fragDepth;
|
||||
|
@ -441,6 +425,7 @@ vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTex
|
|||
|
||||
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
|
||||
int blurRadius = getBlurRadius();
|
||||
|
||||
// negative side first
|
||||
for (int r = -blurRadius; r <= -1; ++r) {
|
||||
weightedSums += evalTapWeightedValue(side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, fragDepth);
|
||||
|
|
45
libraries/render-utils/src/ssao_buildNormals.slf
Normal file
45
libraries/render-utils/src/ssao_buildNormals.slf
Normal file
|
@ -0,0 +1,45 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// ssao_buildNormals.frag
|
||||
//
|
||||
// Created by Olivier Prat on 09/19/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include ssao.slh@>
|
||||
<$declareAmbientOcclusion()$>
|
||||
<$declareFetchDepthPyramidMap()$>
|
||||
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
vec2 sideImageSize = getSideImageSize(0);
|
||||
|
||||
// Pixel being shaded
|
||||
vec2 fragCoord = gl_FragCoord.xy;
|
||||
ivec2 fragPixelPos = ivec2(fragCoord.xy);
|
||||
|
||||
// Stereo side info
|
||||
ivec4 side = getStereoSideInfo(fragPixelPos.x, 0);
|
||||
|
||||
// From now on, fragPixelPos is the pixel pos in the side
|
||||
fragPixelPos.x -= side.y;
|
||||
vec2 fragUVPos = (vec2(fragPixelPos) + vec2(0.5)) / sideImageSize;
|
||||
|
||||
// Fetch the z under the pixel (stereo or not)
|
||||
float Zeye = getZEyeAtUV(fragUVPos, 0);
|
||||
|
||||
// The position and normal of the pixel fragment in Eye space
|
||||
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
||||
vec3 fragNormalES = evalEyeNormal(fragPositionES);
|
||||
vec3 absFragNormalES = abs(fragNormalES);
|
||||
|
||||
// Maximize encoding precision
|
||||
fragNormalES /= max(max(absFragNormalES.x, absFragNormalES.y), absFragNormalES.z);
|
||||
outFragColor = vec4(vec3(fragNormalES)*0.5 + vec3(0.5), 1.0);
|
||||
}
|
|
@ -46,7 +46,11 @@ void main(void) {
|
|||
|
||||
// The position and normal of the pixel fragment in Eye space
|
||||
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
vec3 fragNormalES = getNormalEyeAtUV(fragUVPos, 0);
|
||||
#else
|
||||
vec3 fragNormalES = evalEyeNormal(fragPositionES);
|
||||
#endif
|
||||
|
||||
// Choose the screen-space sample radius
|
||||
float diskPixelRadius = evalDiskRadius(fragPositionES.z, sideImageSize);
|
||||
|
|
|
@ -39,7 +39,7 @@ struct AmbientOcclusionParams {
|
|||
SSAO_VEC4 _ditheringInfo;
|
||||
SSAO_VEC4 _sampleInfo;
|
||||
SSAO_VEC4 _blurInfo;
|
||||
float _gaussianCoefs[SSAO_BLUR_GAUSSIAN_COEFS_COUNT];
|
||||
float _blurFilterTaps[SSAO_BLUR_GAUSSIAN_COEFS_COUNT];
|
||||
};
|
||||
|
||||
struct AmbientOcclusionFrameParams {
|
||||
|
|
|
@ -35,11 +35,12 @@ Rectangle {
|
|||
model: [
|
||||
"Radius:radius:2.0:false",
|
||||
"Level:obscuranceLevel:1.0:false",
|
||||
"Num Taps:numSamples:32:true",
|
||||
"Num Taps:numSamples:16:true",
|
||||
"Taps Spiral:numSpiralTurns:10.0:false",
|
||||
"Falloff Angle:falloffAngle:0.5:false",
|
||||
"Blur Edge Sharpness:edgeSharpness:1.0:false",
|
||||
"Blur Radius:blurRadius:15.0:false",
|
||||
"Blur Radius:blurRadius:15.0:true",
|
||||
"Resolution Downscale:resolutionLevel:2:true",
|
||||
]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
|
@ -57,7 +58,6 @@ Rectangle {
|
|||
Column {
|
||||
Repeater {
|
||||
model: [
|
||||
"resolutionLevel:resolutionLevel",
|
||||
"ditheringEnabled:ditheringEnabled",
|
||||
"fetchMipsEnabled:fetchMipsEnabled",
|
||||
"borderingEnabled:borderingEnabled"
|
||||
|
|
Loading…
Reference in a new issue