mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 13:33:38 +02:00
Fixed bugs in stereo
This commit is contained in:
parent
086ba998c8
commit
9f9fe909b0
4 changed files with 56 additions and 42 deletions
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue