Fixed bugs in stereo

This commit is contained in:
Olivier Prat 2018-09-28 19:22:20 +02:00
parent 086ba998c8
commit 9f9fe909b0
4 changed files with 56 additions and 42 deletions

View file

@ -92,12 +92,13 @@ void AmbientOcclusionFramebuffer::allocate() {
{
auto width = _frameSize.x;
auto height = _frameSize.y;
auto sampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP);
_occlusionTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
_occlusionTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, sampler);
_occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
_occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture);
_occlusionBlurredTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
_occlusionBlurredTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, sampler);
_occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred"));
_occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture);
}
@ -108,7 +109,7 @@ void AmbientOcclusionFramebuffer::allocate() {
if (_isStereo) {
sideSize.x >>= 1;
}
sideSize = divideRoundUp(sideSize, 1 << _resolutionLevel);
sideSize >>= _resolutionLevel;
if (_isStereo) {
sideSize.x <<= 1;
}
@ -127,7 +128,7 @@ void AmbientOcclusionFramebuffer::allocate() {
if (_isStereo) {
splitSize.x >>= 1;
}
splitSize = divideRoundUp(splitSize, SSAO_SPLIT_COUNT << _resolutionLevel);
splitSize = divideRoundUp(_frameSize >> _resolutionLevel, SSAO_SPLIT_COUNT);
if (_isStereo) {
splitSize.x <<= 1;
}
@ -355,14 +356,13 @@ void AmbientOcclusionEffect::configure(const Config& config) {
void AmbientOcclusionEffect::updateBlurParameters() {
const auto resolutionLevel = _aoParametersBuffer->getResolutionLevel();
const auto resolutionScale = 1 << resolutionLevel;
auto& vblur = _vblurParametersBuffer.edit();
auto& hblur = _hblurParametersBuffer.edit();
auto frameSize = _framebuffer->getSourceFrameSize();
if (_framebuffer->isStereo()) {
frameSize.x >>= 1;
}
const auto occlusionSize = divideRoundUp(frameSize, resolutionScale);
const auto occlusionSize = frameSize >> resolutionLevel;
// Occlusion UV limit
hblur._blurAxis.z = occlusionSize.x / float(frameSize.x);
@ -381,18 +381,17 @@ void AmbientOcclusionEffect::updateBlurParameters() {
void AmbientOcclusionEffect::updateFramebufferSizes() {
auto& params = _aoParametersBuffer.edit();
const int widthScale = _framebuffer->isStereo() & 1;
const int stereoDivide = _framebuffer->isStereo() & 1;
auto sourceFrameSideSize = _framebuffer->getSourceFrameSize();
sourceFrameSideSize.x >>= widthScale;
sourceFrameSideSize.x >>= stereoDivide;
const int resolutionLevel = _aoParametersBuffer.get().getResolutionLevel();
// Depth is at maximum half depth
const int depthResolutionLevel = getDepthResolutionLevel();
const auto occlusionDepthFrameSize = divideRoundUp(sourceFrameSideSize, 1 << depthResolutionLevel);
const auto occlusionFrameSize = divideRoundUp(sourceFrameSideSize, 1 << resolutionLevel);
const auto occlusionDepthFrameSize = sourceFrameSideSize >> depthResolutionLevel;
const auto occlusionFrameSize = sourceFrameSideSize >> resolutionLevel;
auto normalTextureSize = _framebuffer->getNormalTexture()->getDimensions();
normalTextureSize.x >>= widthScale;
normalTextureSize.x >>= stereoDivide;
params._sideSizes[0].x = normalTextureSize.x;
params._sideSizes[0].y = normalTextureSize.y;
@ -485,12 +484,10 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
const auto depthResolutionScale = powf(0.5f, depthResolutionLevel);
const auto isHorizonBased = _aoParametersBuffer->isHorizonBased();
auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto occlusionDepthTexture = linearDepthTexture;
auto fullResDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto occlusionDepthTexture = fullResDepthTexture;
auto sourceViewport = args->_viewport;
// divideRoundUp is used two compute the quarter or half resolution render sizes.
// We choose to take the rounded up resolution.
auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel);
auto occlusionViewport = sourceViewport >> resolutionLevel;
auto firstBlurViewport = sourceViewport;
firstBlurViewport.w = occlusionViewport.w;
@ -506,7 +503,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
occlusionDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
}
if (_framebuffer->update(linearDepthTexture, resolutionLevel, depthResolutionLevel, args->isStereo())) {
if (_framebuffer->update(fullResDepthTexture, resolutionLevel, depthResolutionLevel, args->isStereo())) {
updateBlurParameters();
updateFramebufferSizes();
}
@ -538,7 +535,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
auto& sample = _aoFrameParametersBuffer[splitId].edit();
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
}
// _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
_frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) {
PROFILE_RANGE_BATCH(batch, "SSAO");
@ -567,7 +564,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.setModelTransform(Transform());
batch.setViewportTransform(normalViewport);
batch.setPipeline(buildNormalsPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture);
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, nullptr);
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
@ -651,8 +648,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.setModelTransform(model);
}
batch.setPipeline(bilateralBlurPipeline);
// Use full resolution depth and normal for bilateral upscaling and blur
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
// Use full resolution depth for bilateral upscaling and blur
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture);
#if SSAO_USE_QUAD_SPLIT
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
#else
@ -742,18 +739,18 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex
return;
}
auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto fullResDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto sourceViewport = args->_viewport;
auto occlusionViewport = sourceViewport;
auto resolutionLevel = ambientOcclusionUniforms->getResolutionLevel();
if (resolutionLevel > 0) {
linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
fullResDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
occlusionViewport = occlusionViewport >> ambientOcclusionUniforms->getResolutionLevel();
}
auto framebufferSize = glm::ivec2(linearDepthTexture->getDimensions());
auto framebufferSize = glm::ivec2(fullResDepthTexture->getDimensions());
float sMin = occlusionViewport.x / (float)framebufferSize.x;
float sWidth = occlusionViewport.z / (float)framebufferSize.x;
@ -779,7 +776,7 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex
batch.setUniformBuffer(render_utils::slot::buffer::SsaoDebugParams, _parametersBuffer);
batch.setPipeline(debugPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture);
batch.draw(gpu::TRIANGLE_STRIP, 4);

View file

@ -45,7 +45,7 @@ void LinearDepthFramebuffer::update(const gpu::TexturePointer& depthBuffer, cons
if (isStereo) {
_halfFrameSize.x >>= 1;
}
_halfFrameSize = divideRoundUp(_halfFrameSize, 2);
_halfFrameSize >>= 1;
if (isStereo) {
_halfFrameSize.x <<= 1;
}
@ -182,7 +182,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
auto downsamplePipeline = getDownsamplePipeline(renderContext);
auto depthViewport = args->_viewport;
auto halfViewport = divideRoundUp(depthViewport, 2);
auto halfViewport = depthViewport >> 1;
float clearLinearDepth = args->getViewFrustum().getFarClip() * 2.0f;
gpu::doInBatch("LinearDepthPass::run", args->_context, [=](gpu::Batch& batch) {

View file

@ -260,11 +260,20 @@ float getZEyeAtUV(vec2 texCoord, int level) {
return -textureLod(depthPyramidTex, texCoord, level).x;
}
float getZEyeAtUV(vec2 texCoord, int level, ivec2 texelOffset) {
return -textureLodOffset(depthPyramidTex, texCoord, level, texelOffset).x;
}
float getZEyeAtUV(ivec4 side, vec2 texCoord, int level) {
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo());
return getZEyeAtUV(texCoord, level);
}
float getZEyeAtUV(ivec4 side, vec2 texCoord, int level, ivec2 texelOffset) {
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo());
return getZEyeAtUV(texCoord, level, texelOffset);
}
vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
}
@ -301,20 +310,25 @@ vec3 buildPosition(ivec4 side, vec2 fragUVPos) {
return evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
}
vec3 buildPosition(ivec4 side, vec2 fragUVPos, ivec2 texelOffset, vec2 deltaUV) {
float Zeye = getZEyeAtUV(side, fragUVPos, 0, texelOffset);
return evalEyePositionFromZeye(side.x, Zeye, fragUVPos + texelOffset*deltaUV);
}
vec3 getMinDelta(vec3 centralPoint, vec3 offsetPointPos, vec3 offsetPointNeg) {
vec3 delta0 = offsetPointPos - centralPoint;
vec3 delta1 = centralPoint - offsetPointNeg;
float sqrLength0 = dot(delta0, delta0);
float sqrLength1 = dot(delta1, delta1);
float epsilon = 1e-6;
return sqrLength0 < sqrLength1 && sqrLength0>epsilon ? delta0 : delta1;
return sqrLength0 < sqrLength1 ? delta0 : delta1;
}
vec3 buildNormal(ivec4 side, vec2 fragUVPos, vec3 fragPosition, vec2 deltaDepthUV) {
vec3 fragPositionDxPos = buildPosition(side, fragUVPos + vec2(deltaDepthUV.x, 0));
vec3 fragPositionDxNeg = buildPosition(side, fragUVPos - vec2(deltaDepthUV.x, 0));
vec3 fragPositionDyPos = buildPosition(side, fragUVPos + vec2(0, deltaDepthUV.y));
vec3 fragPositionDyNeg = buildPosition(side, fragUVPos - vec2(0, deltaDepthUV.y));
vec3 fragPositionDxPos = buildPosition(side, fragUVPos, ivec2(1,0), deltaDepthUV);
vec3 fragPositionDxNeg = buildPosition(side, fragUVPos, ivec2(-1,0), deltaDepthUV);
vec3 fragPositionDyPos = buildPosition(side, fragUVPos, ivec2(0,1), deltaDepthUV);
vec3 fragPositionDyNeg = buildPosition(side, fragUVPos, ivec2(0,-1), deltaDepthUV);
vec3 fragPositionDx = getMinDelta(fragPosition, fragPositionDxPos, fragPositionDxNeg);
vec3 fragPositionDy = getMinDelta(fragPosition, fragPositionDyPos, fragPositionDyNeg);

View file

@ -43,7 +43,7 @@ int getBlurRadius() {
}
vec4 fetchOcclusionPacked(ivec4 side, vec2 texCoord) {
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo());
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side) * getBlurOcclusionUVLimit().x) * 0.5, isStereo());
return textureLod(occlusionMap, texCoord, 0);
}
@ -54,12 +54,11 @@ float evalBlurCoefficient(vec3 blurScales, float radialDistance, float zDistance
const float BLUR_EDGE_NORMAL_LIMIT = 0.25;
vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, vec2 depthTexCoord, float fragDepth, vec3 fragNormal) {
vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, float fragDepth, vec3 fragNormal) {
vec2 tapOcclusionTexCoord = getBlurOcclusionAxis() * r + occlusionTexCoord;
vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit();
if (tapOcclusionTexCoord.x < side.x || tapOcclusionTexCoord.x >= (side.x + occlusionTexCoordLimits.x)
|| tapOcclusionTexCoord.y < 0 || tapOcclusionTexCoord.y >= occlusionTexCoordLimits.y) {
if (any(lessThan(tapOcclusionTexCoord, vec2(0.0))) || any(greaterThanEqual(tapOcclusionTexCoord, occlusionTexCoordLimits)) ) {
return vec2(0.0);
}
@ -85,10 +84,10 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept
// Stereo side info
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
float fragDepth = getZEyeAtUV(side, depthTexCoord, 0);
float fragDepth = getZEyeAtUV(depthTexCoord, 0);
float fragDepthKey = CSZToDepthKey(fragDepth);
#if SSAO_BILATERAL_BLUR_USE_NORMAL
vec3 fragNormal = getNormalEyeAtUV(side, depthTexCoord, 0);
vec3 fragNormal = getNormalEyeAtUV(depthTexCoord, 0);
#else
vec3 fragNormal = vec3(0, 0, 1);
#endif
@ -98,9 +97,13 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept
int blurRadius = getBlurRadius();
vec3 blurScales = getBlurScales();
// From now on, occlusionTexCoord is the UV pos in the side
float sideTexCoord = occlusionTexCoord.x * 2.0 - getStereoSide(side) * getBlurOcclusionUVLimit().x;
occlusionTexCoord.x = mix(occlusionTexCoord.x, sideTexCoord, isStereo());
// negative side first
for (int r = -blurRadius; r <= -1; ++r) {
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepthKey, fragNormal);
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal);
}
// Central pixel contribution
@ -110,7 +113,7 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept
// then positive side
for (int r = 1; r <= blurRadius; ++r) {
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepthKey, fragNormal);
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal);
}
// Final normalization