Switched to full screen depth and normals

This commit is contained in:
Olivier Prat 2018-09-25 10:01:30 +02:00
parent 9cebdbd507
commit 190996e670
5 changed files with 40 additions and 38 deletions

View file

@ -41,15 +41,16 @@ gpu::PipelinePointer AmbientOcclusionEffect::_buildNormalsPipeline;
AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() { AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() {
} }
bool AmbientOcclusionFramebuffer::update(const gpu::TexturePointer& linearDepthBuffer, int resolutionLevel, bool isStereo) { bool AmbientOcclusionFramebuffer::update(const gpu::TexturePointer& linearDepthBuffer, int resolutionLevel, int depthResolutionLevel, bool isStereo) {
// If the depth buffer or size changed, we need to delete our FBOs // If the depth buffer or size changed, we need to delete our FBOs
bool reset = false; bool reset = false;
if (_linearDepthTexture != linearDepthBuffer) { if (_linearDepthTexture != linearDepthBuffer) {
_linearDepthTexture = linearDepthBuffer; _linearDepthTexture = linearDepthBuffer;
reset = true; reset = true;
} }
if (_resolutionLevel != resolutionLevel || isStereo != _isStereo) { if (_resolutionLevel != resolutionLevel || isStereo != _isStereo || _depthResolutionLevel != depthResolutionLevel) {
_resolutionLevel = resolutionLevel; _resolutionLevel = resolutionLevel;
_depthResolutionLevel = depthResolutionLevel;
_isStereo = isStereo; _isStereo = isStereo;
reset = true; reset = true;
} }
@ -103,7 +104,7 @@ void AmbientOcclusionFramebuffer::allocate() {
if (_isStereo) { if (_isStereo) {
sideSize.x >>= 1; sideSize.x >>= 1;
} }
sideSize = divideRoundUp(sideSize, 1 << std::min(1, _resolutionLevel)); sideSize = divideRoundUp(sideSize, 1 << _depthResolutionLevel);
if (_isStereo) { if (_isStereo) {
sideSize.x <<= 1; sideSize.x <<= 1;
} }
@ -117,11 +118,11 @@ void AmbientOcclusionFramebuffer::allocate() {
#if SSAO_USE_QUAD_SPLIT #if SSAO_USE_QUAD_SPLIT
{ {
auto splitSize = glm::ivec2(_normalFramebuffer->getSize()); auto splitSize = _frameSize;
if (_isStereo) { if (_isStereo) {
splitSize.x >>= 1; splitSize.x >>= 1;
} }
splitSize = divideRoundUp(splitSize, 2); splitSize = divideRoundUp(splitSize, 2 << _resolutionLevel);
if (_isStereo) { if (_isStereo) {
splitSize.x <<= 1; splitSize.x <<= 1;
} }
@ -531,6 +532,11 @@ void AmbientOcclusionEffect::updateGaussianDistribution() {
GaussianDistribution::evalSampling(filterTaps, SSAO_BLUR_GAUSSIAN_COEFS_COUNT, blurRadius, _aoParametersBuffer->getBlurDeviation()); GaussianDistribution::evalSampling(filterTaps, SSAO_BLUR_GAUSSIAN_COEFS_COUNT, blurRadius, _aoParametersBuffer->getBlurDeviation());
} }
int AmbientOcclusionEffect::getDepthResolutionLevel() const {
// Having some problems making a nice AO with Half resolution depth, so stick to full res.
return 0;
}
void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->hasViewFrustum()); assert(renderContext->args->hasViewFrustum());
@ -543,6 +549,9 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
const int resolutionLevel = _aoParametersBuffer->getResolutionLevel(); const int resolutionLevel = _aoParametersBuffer->getResolutionLevel();
const auto resolutionScale = powf(0.5f, resolutionLevel); const auto resolutionScale = powf(0.5f, resolutionLevel);
const auto depthResolutionLevel = getDepthResolutionLevel();
const auto depthResolutionScale = powf(0.5f, depthResolutionLevel);
auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto occlusionDepthTexture = linearDepthTexture; auto occlusionDepthTexture = linearDepthTexture;
auto sourceViewport = args->_viewport; auto sourceViewport = args->_viewport;
@ -550,13 +559,6 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
// We need to take the rounded up resolution. // We need to take the rounded up resolution.
auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel); auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel);
auto firstBlurViewport = sourceViewport; auto firstBlurViewport = sourceViewport;
#if SSAO_USE_QUAD_SPLIT
auto splitViewport = glm::ivec4{ 0, 0, _framebuffer->getOcclusionSplitTexture()->getWidth(), _framebuffer->getOcclusionSplitTexture()->getHeight() };
auto depthSideSize = glm::ivec2(linearDepthTexture->getDimensions());
if (args->isStereo()) {
depthSideSize.x >>= 1;
}
#endif
firstBlurViewport.w = divideRoundUp(firstBlurViewport.w, 1 << resolutionLevel); firstBlurViewport.w = divideRoundUp(firstBlurViewport.w, 1 << resolutionLevel);
if (!_gpuTimer) { if (!_gpuTimer) {
@ -567,11 +569,11 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>(); _framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
} }
if (resolutionLevel > 0) { if (depthResolutionLevel > 0) {
occlusionDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); occlusionDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
} }
if (_framebuffer->update(linearDepthTexture, resolutionLevel, args->isStereo())) { if (_framebuffer->update(linearDepthTexture, resolutionLevel, depthResolutionLevel, args->isStereo())) {
updateBlurParameters(); updateBlurParameters();
updateFramebufferSizes(); updateFramebufferSizes();
} }
@ -595,14 +597,10 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
auto occlusionNormalFramebuffer = _framebuffer->getNormalFramebuffer(); auto occlusionNormalFramebuffer = _framebuffer->getNormalFramebuffer();
auto occlusionNormalTexture = _framebuffer->getNormalTexture(); auto occlusionNormalTexture = _framebuffer->getNormalTexture();
auto normalViewport = glm::ivec4{ 0, 0, occlusionNormalFramebuffer->getWidth(), occlusionNormalFramebuffer->getHeight() }; auto normalViewport = glm::ivec4{ 0, 0, occlusionNormalFramebuffer->getWidth(), occlusionNormalFramebuffer->getHeight() };
auto splitSize = glm::ivec2(_framebuffer->getOcclusionSplitTexture()->getDimensions());
auto splitViewport = glm::ivec4{ 0, 0, splitSize.x, splitSize.y };
#endif #endif
auto occlusionDepthSideSize = glm::ivec2(occlusionDepthTexture->getDimensions()); auto occlusionDepthSize = glm::ivec2(occlusionDepthTexture->getDimensions());
if (args->isStereo()) {
occlusionDepthSideSize.x >>= 1;
}
const auto depthResolutionLevel = std::min(1, resolutionLevel);
const auto depthResolutionScale = powf(2.0f, depthResolutionLevel);
// Update sample rotation // Update sample rotation
const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / SSAO_SPLIT_COUNT); const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / SSAO_SPLIT_COUNT);
@ -636,7 +634,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
#if SSAO_USE_QUAD_SPLIT #if SSAO_USE_QUAD_SPLIT
batch.pushProfileRange("Normal Generation"); batch.pushProfileRange("Normal Generation");
model.setScale( glm::vec3((normalViewport.z * depthResolutionScale) / depthSideSize.x, (normalViewport.w * depthResolutionScale) / depthSideSize.y, 1.0f) ); model.setScale(glm::vec3(normalViewport.z / (sourceViewport.z * depthResolutionScale), normalViewport.w / (sourceViewport.w * depthResolutionScale), 1.0f));
batch.setModelTransform(model); batch.setModelTransform(model);
// Build face normals pass // Build face normals pass
@ -668,39 +666,39 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture); batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
{ {
const auto scale = glm::vec3( const auto scale = glm::vec3(
(splitViewport.z * 2.0f) / occlusionDepthSideSize.x, (splitSize.x * 2.0f * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
(splitViewport.w * 2.0f) / occlusionDepthSideSize.y, (splitSize.y * 2.0f * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
1.0f); 1.0f);
const auto pixelUV = glm::vec2(1.0f) / (glm::vec2(occlusionDepthSideSize) * glm::vec2(scale.x, scale.y)); const auto pixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionDepthSize);
batch.setViewportTransform(splitViewport); batch.setViewportTransform(splitViewport);
model.setScale(scale); model.setScale(scale);
model.setTranslation(glm::vec3(0.0f, 0.0f, 0.0f)); model.setTranslation(glm::vec3(-pixelOffset.x, -pixelOffset.y, 0.0f));
batch.setModelTransform(model); batch.setModelTransform(model);
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(0)); batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(0));
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]); batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
model.setTranslation(glm::vec3(pixelUV.x, 0.0f, 0.0f)); model.setTranslation(glm::vec3(pixelOffset.x, -pixelOffset.y, 0.0f));
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(1)); batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(1));
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]); batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]);
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
model.setTranslation(glm::vec3(pixelUV.x, pixelUV.y, 0.0f)); model.setTranslation(glm::vec3(pixelOffset.x, pixelOffset.y, 0.0f));
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(3)); batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(3));
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]); batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]);
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
model.setTranslation(glm::vec3(0.0f, pixelUV.y, 0.0f)); model.setTranslation(glm::vec3(-pixelOffset.x, pixelOffset.y, 0.0f));
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(2)); batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(2));
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]); batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]);
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
} }
#else #else
const auto scale = glm::vec3( const auto scale = glm::vec3(
(occlusionViewport.z / (depthSideSize.x * resolutionScale)) * fullDepthToHalfDepthSizeRatio.x, occlusionViewport.z / (framebufferSize.x * resolutionScale),
(occlusionViewport.w / (depthSideSize.y * resolutionScale)) * fullDepthToHalfDepthSizeRatio.y, occlusionViewport.w / (framebufferSize.y * resolutionScale),
1.0f); 1.0f);
model.setScale(scale); model.setScale(scale);
batch.setViewportTransform(occlusionViewport); batch.setViewportTransform(occlusionViewport);

View file

@ -42,7 +42,7 @@ public:
#endif #endif
// Update the source framebuffer size which will drive the allocation of all the other resources. // Update the source framebuffer size which will drive the allocation of all the other resources.
bool update(const gpu::TexturePointer& linearDepthBuffer, int resolutionLevel, bool isStereo); bool update(const gpu::TexturePointer& linearDepthBuffer, int resolutionLevel, int depthResolutionLevel, bool isStereo);
gpu::TexturePointer getLinearDepthTexture(); gpu::TexturePointer getLinearDepthTexture();
const glm::ivec2& getSourceFrameSize() const { return _frameSize; } const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
bool isStereo() const { return _isStereo; } bool isStereo() const { return _isStereo; }
@ -70,6 +70,7 @@ protected:
glm::ivec2 _frameSize; glm::ivec2 _frameSize;
int _resolutionLevel{ 0 }; int _resolutionLevel{ 0 };
int _depthResolutionLevel{ 0 };
bool _isStereo{ false }; bool _isStereo{ false };
}; };
@ -177,6 +178,8 @@ private:
void updateGaussianDistribution(); void updateGaussianDistribution();
void updateBlurParameters(); void updateBlurParameters();
void updateFramebufferSizes(); void updateFramebufferSizes();
int getDepthResolutionLevel() const;
AOParametersBuffer _aoParametersBuffer; AOParametersBuffer _aoParametersBuffer;
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT]; FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT];

View file

@ -73,8 +73,9 @@ void LinearDepthFramebuffer::allocate() {
auto height = _frameSize.y; auto height = _frameSize.y;
// For Linear Depth: // For Linear Depth:
const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 1; const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 5;
const auto depthSamplerFull = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP); // Point sampling of the depth, as well as the clamp to edge, are needed for the AmbientOcclusionEffect with HBAO
const auto depthSamplerFull = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
_linearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, LINEAR_DEPTH_MAX_MIP_LEVEL, _linearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, LINEAR_DEPTH_MAX_MIP_LEVEL,
depthSamplerFull); depthSamplerFull);
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth")); _linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth"));

View file

@ -29,11 +29,11 @@ void main(void) {
ivec2 sideNormalsSize = ivec2( getNormalsSideSize() ); ivec2 sideNormalsSize = ivec2( getNormalsSideSize() );
ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideNormalsSize.x); ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideNormalsSize.x);
// From now on, fragUVPos is the UV pos in the side
fragUVPos.x = mix(fragUVPos.x, fragUVPos.x - getStereoSide(side) * 0.5, isStereo());
vec2 deltaDepthUV = vec2(1.0) / vec2(getDepthTextureSideSize(0)); vec2 deltaDepthUV = vec2(1.0) / vec2(getDepthTextureSideSize(0));
// From now on, fragUVPos is the UV pos in the side
fragUVPos.x = mix(fragUVPos.x, fragUVPos.x * 2.0 - getStereoSide(side), isStereo());
// The position and normal of the pixel fragment in Eye space // The position and normal of the pixel fragment in Eye space
vec3 fragPositionES = buildPosition(side, fragUVPos); vec3 fragPositionES = buildPosition(side, fragUVPos);
vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV); vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV);

View file

@ -37,7 +37,7 @@ void main(void) {
ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideOcclusionSize.x); ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideOcclusionSize.x);
// From now on, fragUVPos is the UV pos in the side // From now on, fragUVPos is the UV pos in the side
fragUVPos.x = mix(fragUVPos.x, fragUVPos.x - getStereoSide(side) * 0.5, isStereo()); fragUVPos.x = mix(fragUVPos.x, fragUVPos.x * 2.0 - getStereoSide(side), isStereo());
// The position and normal of the pixel fragment in Eye space // The position and normal of the pixel fragment in Eye space
vec2 deltaDepthUV = vec2(1.0) / sideDepthSize; vec2 deltaDepthUV = vec2(1.0) / sideDepthSize;