mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 20:29:10 +02:00
Using UVs for buildNormals
This commit is contained in:
parent
9f0201878d
commit
2e40a5f3ff
5 changed files with 97 additions and 57 deletions
|
@ -109,8 +109,8 @@ void AmbientOcclusionFramebuffer::allocate() {
|
|||
}
|
||||
auto width = sideSize.x;
|
||||
auto height = sideSize.y;
|
||||
|
||||
_normalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP));
|
||||
auto format = gpu::Element::COLOR_RGBA_32;
|
||||
_normalTexture = gpu::Texture::createRenderBuffer(format, 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);
|
||||
}
|
||||
|
@ -561,8 +561,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
}
|
||||
// _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
|
||||
|
||||
gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "AmbientOcclusion");
|
||||
gpu::doInBatch("AmbientOcclusionEffect::Depth mip creation", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "AO::Depth mip creation");
|
||||
batch.enableStereo(false);
|
||||
|
||||
_gpuTimer->begin(batch);
|
||||
|
@ -574,29 +574,57 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
batch.setModelTransform(model);
|
||||
|
||||
// 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();
|
||||
|
||||
_gpuTimer->end(batch);
|
||||
});
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
gpu::doInBatch("AmbientOcclusionEffect::Build Normals", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "AO::Build Normals");
|
||||
batch.enableStereo(false);
|
||||
|
||||
_gpuTimer->begin(batch);
|
||||
|
||||
batch.resetViewTransform();
|
||||
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
Transform model;
|
||||
auto depthTextureSize = linearDepthTexture->getDimensions();
|
||||
model.setScale( glm::vec3(occlusionViewport.z / (depthTextureSize.x * resolutionScale), occlusionViewport.w / (depthTextureSize.y * resolutionScale), 1.0f) );
|
||||
batch.setModelTransform(model);
|
||||
|
||||
// Build face normals pass
|
||||
batch.pushProfileRange("Build Normals");
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setPipeline(buildNormalsPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
|
||||
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);
|
||||
batch.setFramebuffer(occlusionNormalFramebuffer);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.popProfileRange();
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setPipeline(buildNormalsPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
|
||||
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);
|
||||
batch.setFramebuffer(occlusionNormalFramebuffer);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
_gpuTimer->end(batch);
|
||||
});
|
||||
#endif
|
||||
|
||||
gpu::doInBatch("AmbientOcclusionEffect::Occlusion", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "AO::Occlusion");
|
||||
batch.enableStereo(false);
|
||||
|
||||
_gpuTimer->begin(batch);
|
||||
|
||||
batch.resetViewTransform();
|
||||
|
||||
Transform model;
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.setModelTransform(model);
|
||||
|
||||
// Occlusion pass
|
||||
batch.pushProfileRange("Occlusion");
|
||||
|
||||
|
|
|
@ -73,19 +73,20 @@ void LinearDepthFramebuffer::allocate() {
|
|||
auto height = _frameSize.y;
|
||||
|
||||
// For Linear Depth:
|
||||
const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 5;
|
||||
// Point sampling of the depth is needed for the AmbientOcclusionEffect in HBAO, as well as the clamp to edge
|
||||
const auto depthSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
|
||||
const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 1;
|
||||
const auto depthSamplerFull = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_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,
|
||||
depthSampler);
|
||||
depthSamplerFull);
|
||||
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth"));
|
||||
_linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture);
|
||||
_linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
|
||||
|
||||
// For Downsampling:
|
||||
const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = LINEAR_DEPTH_MAX_MIP_LEVEL;
|
||||
const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = 5;
|
||||
// Point sampling of the depth, as well as the clamp to edge, are needed for the AmbientOcclusionEffect with HBAO
|
||||
const auto depthSamplerHalf = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
|
||||
_halfLinearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL,
|
||||
depthSampler);
|
||||
depthSamplerHalf);
|
||||
|
||||
_halfNormalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _halfFrameSize.x, _halfFrameSize.y, gpu::Texture::SINGLE_MIP,
|
||||
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT));
|
||||
|
@ -183,35 +184,47 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
|
|||
auto halfViewport = divideRoundUp(depthViewport, 2);
|
||||
float clearLinearDepth = args->getViewFrustum().getFarClip() * 2.0f;
|
||||
|
||||
gpu::doInBatch("LinearDepthPass::run", args->_context, [=](gpu::Batch& batch) {
|
||||
gpu::doInBatch("LinearDepthPass::ZtoLinearDepth", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "ZtoLinearDepth");
|
||||
_gpuTimer->begin(batch);
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setViewportTransform(depthViewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_linearDepthFramebuffer->getDepthFrameSize(), depthViewport));
|
||||
|
||||
batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
|
||||
|
||||
// LinearDepth
|
||||
batch.setViewportTransform(depthViewport);
|
||||
batch.setFramebuffer(linearDepthFBO);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(clearLinearDepth, 0.0f, 0.0f, 0.0f));
|
||||
batch.setPipeline(linearDepthPipeline);
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_linearDepthFramebuffer->getDepthFrameSize(), depthViewport));
|
||||
batch.setResourceTexture(ru::Texture::SurfaceGeometryDepth, depthBuffer);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
_gpuTimer->end(batch);
|
||||
});
|
||||
|
||||
gpu::doInBatch("LinearDepthPass::halfDepth", args->_context, [=](gpu::Batch& batch) {
|
||||
PROFILE_RANGE_BATCH(batch, "LinearDepthDownsample");
|
||||
_gpuTimer->begin(batch);
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
|
||||
batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
|
||||
|
||||
// Downsample
|
||||
batch.setViewportTransform(halfViewport);
|
||||
Transform model;
|
||||
model.setScale( glm::vec3((depthViewport.z >> 1) / float(halfViewport.z), (depthViewport.w >> 1) / float(halfViewport.w), 1.0f) );
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(downsampleFBO);
|
||||
batch.setResourceTexture(ru::Texture::SurfaceGeometryDepth, linearDepthTexture);
|
||||
batch.setResourceTexture(ru::Texture::SurfaceGeometryNormal, normalTexture);
|
||||
batch.setPipeline(downsamplePipeline);
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_linearDepthFramebuffer->getDepthFrameSize() >> 1, halfViewport));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
|
||||
_gpuTimer->end(batch);
|
||||
});
|
||||
|
||||
|
|
|
@ -282,25 +282,26 @@ vec4 fetchTap(ivec4 side, vec2 tapSidePixelPos, float tapRadius, vec2 sideImageS
|
|||
return P;
|
||||
}
|
||||
|
||||
vec3 buildPosition(ivec4 side, vec2 fragUVPos, ivec2 depthTexFragPixelPos, ivec2 deltaDepthTexPixel, vec2 uvScale) {
|
||||
depthTexFragPixelPos += deltaDepthTexPixel;
|
||||
fragUVPos += deltaDepthTexPixel * uvScale;
|
||||
float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0);
|
||||
vec3 buildPosition(ivec4 side, vec2 fragUVPos) {
|
||||
vec2 fetchUV = clamp(fragUVPos, vec2(0), vec2(1));
|
||||
fetchUV = mix(fetchUV, vec2((fetchUV.x + getStereoSide(side)) * 0.5, fetchUV.y), isStereo());
|
||||
float Zeye = getZEyeAtUV(fetchUV, 0);
|
||||
return evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
||||
}
|
||||
|
||||
vec3 getMinDelta(vec3 centralPoint, vec3 offsetPointPos, vec3 offsetPointNeg) {
|
||||
vec3 delta0 = offsetPointPos - centralPoint;
|
||||
vec3 delta1 = centralPoint - offsetPointNeg;
|
||||
return dot(delta0, delta0) < dot(delta1, delta1) ? delta0 : delta1;
|
||||
float sqrLength0 = dot(delta0, delta0);
|
||||
float sqrLength1 = dot(delta1, delta1);
|
||||
return sqrLength0 < sqrLength1 ? delta0 : delta1;
|
||||
}
|
||||
|
||||
vec3 buildNormal(ivec4 side, vec2 fragUVPos, ivec2 depthTexFragPixelPos, vec3 fragPosition, vec2 depthTextureSize) {
|
||||
vec2 uvScale = vec2(1.0) / depthTextureSize;
|
||||
vec3 fragPositionDxPos = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(1, 0), uvScale);
|
||||
vec3 fragPositionDyPos = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(0, 1), uvScale);
|
||||
vec3 fragPositionDxNeg = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(-1, 0), uvScale);
|
||||
vec3 fragPositionDyNeg = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(0, -1), uvScale);
|
||||
vec3 buildNormal(ivec4 side, vec2 fragUVPos, vec3 fragPosition, vec2 deltaDepthUV) {
|
||||
vec3 fragPositionDxPos = buildPosition(side, fragUVPos + vec2(deltaDepthUV.x, 0));
|
||||
vec3 fragPositionDyPos = buildPosition(side, fragUVPos + vec2(0, deltaDepthUV.y));
|
||||
vec3 fragPositionDxNeg = buildPosition(side, fragUVPos - vec2(deltaDepthUV.x, 0));
|
||||
vec3 fragPositionDyNeg = buildPosition(side, fragUVPos - vec2(0, deltaDepthUV.y));
|
||||
|
||||
vec3 fragPositionDx = getMinDelta(fragPosition, fragPositionDxPos, fragPositionDxNeg);
|
||||
vec3 fragPositionDy = getMinDelta(fragPosition, fragPositionDyPos, fragPositionDyNeg);
|
||||
|
|
|
@ -15,31 +15,28 @@
|
|||
<$declareAmbientOcclusion()$>
|
||||
<$declareFetchDepthPyramidMap()$>
|
||||
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
// Pixel being shaded
|
||||
vec2 fragCoord = gl_FragCoord.xy;
|
||||
ivec2 fragPixelPos = ivec2(fragCoord.xy);
|
||||
|
||||
// Fetch the z under the pixel (stereo or not) from full res depth
|
||||
int depthTextureRatio = 1 << getNormalsResolutionLevel();
|
||||
ivec2 depthTexFragPixelPos = fragPixelPos * depthTextureRatio;
|
||||
float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0);
|
||||
vec2 fragUVPos = varTexCoord0;
|
||||
|
||||
// Stereo side info based on the real viewport size of this pass
|
||||
ivec2 sideNormalsSize = ivec2( getNormalsSideSize() );
|
||||
ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideNormalsSize.x);
|
||||
|
||||
// From now on, fragPixelPos is the pixel pos in the side
|
||||
vec2 depthSideSize = getDepthTextureSideSize(0);
|
||||
vec2 sideImageSize = depthSideSize / float(depthTextureRatio);
|
||||
fragPixelPos.x -= side.y;
|
||||
vec2 fragUVPos = (vec2(fragPixelPos) + vec2(0.5)) / sideImageSize;
|
||||
// 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));
|
||||
|
||||
// The position and normal of the pixel fragment in Eye space
|
||||
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
||||
vec3 fragNormalES = buildNormal(side, fragUVPos, depthTexFragPixelPos, fragPositionES, depthSideSize);
|
||||
vec3 fragPositionES = buildPosition(side, fragUVPos);
|
||||
vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV);
|
||||
vec3 absFragNormalES = abs(fragNormalES);
|
||||
|
||||
fragNormalES /= max(absFragNormalES.z, max(absFragNormalES.x, absFragNormalES.y));
|
||||
|
|
|
@ -51,9 +51,10 @@ void main(void) {
|
|||
vec2 fragUVPos = (vec2(fragPixelPos) + vec2(0.5)) / sideImageSize;
|
||||
|
||||
// The position and normal of the pixel fragment in Eye space
|
||||
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
||||
vec3 fragPositionES = buildPosition(side, fragUVPos);
|
||||
#if !SSAO_USE_QUAD_SPLIT
|
||||
vec3 fragNormalES = buildNormal(side, fragUVPos, depthTexFragPixelPos, fragPositionES, depthSideSize);
|
||||
vec2 deltaDepthUV = vec2(1.0) / depthSideSize;
|
||||
vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV);
|
||||
#endif
|
||||
|
||||
// Choose the screen-space sample radius
|
||||
|
|
Loading…
Reference in a new issue