mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 18:44:00 +02:00
Found bug with low res depth fetch in occlusion
This commit is contained in:
parent
9899eb6d3f
commit
dee0a6afa2
5 changed files with 64 additions and 56 deletions
|
@ -89,8 +89,6 @@ void AmbientOcclusionFramebuffer::allocate() {
|
|||
auto height = _frameSize.y;
|
||||
auto format = gpu::Element::COLOR_R_8;
|
||||
|
||||
//TEMPO OP
|
||||
format = gpu::Element::VEC4F_COLOR_RGBA;
|
||||
_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);
|
||||
|
@ -125,7 +123,7 @@ void AmbientOcclusionFramebuffer::allocate() {
|
|||
if (_isStereo) {
|
||||
splitSize.x >>= 1;
|
||||
}
|
||||
splitSize = divideRoundUp(splitSize, 2 << _resolutionLevel);
|
||||
splitSize = divideRoundUp(splitSize, SSAO_SPLIT_COUNT << _resolutionLevel);
|
||||
if (_isStereo) {
|
||||
splitSize.x <<= 1;
|
||||
}
|
||||
|
@ -133,9 +131,9 @@ void AmbientOcclusionFramebuffer::allocate() {
|
|||
auto height = splitSize.y;
|
||||
auto format = gpu::Element::COLOR_R_8;
|
||||
|
||||
_occlusionSplitTexture = gpu::Texture::createRenderBufferArray(format, width, height, SSAO_SPLIT_COUNT, gpu::Texture::SINGLE_MIP,
|
||||
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP));
|
||||
for (int i = 0; i < SSAO_SPLIT_COUNT; i++) {
|
||||
_occlusionSplitTexture = gpu::Texture::createRenderBufferArray(format, width, height, SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT, gpu::Texture::SINGLE_MIP,
|
||||
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
|
||||
for (int i = 0; i < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT; i++) {
|
||||
_occlusionSplitFramebuffers[i] = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
|
||||
_occlusionSplitFramebuffers[i]->setRenderBuffer(0, _occlusionSplitTexture, i);
|
||||
}
|
||||
|
@ -145,7 +143,7 @@ void AmbientOcclusionFramebuffer::allocate() {
|
|||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getOcclusionSplitFramebuffer(int index) {
|
||||
assert(index < SSAO_SPLIT_COUNT);
|
||||
assert(index < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT);
|
||||
if (!_occlusionSplitFramebuffers[index]) {
|
||||
allocate();
|
||||
}
|
||||
|
@ -220,7 +218,7 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
|
|||
blurDeviation{ 2.5f },
|
||||
numSpiralTurns{ 7.0f },
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
numSamples{ 3 },
|
||||
numSamples{ 1 },
|
||||
#else
|
||||
numSamples{ 16 },
|
||||
#endif
|
||||
|
@ -305,7 +303,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
r = r + f * (float)(index % B);
|
||||
index = index / B;
|
||||
}
|
||||
_randomSamples[i] = r * M_PI / config.numSamples;
|
||||
_randomSamples[i] = r * 2.0f * M_PI / config.numSamples;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,7 +443,7 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getGatherPipeline() {
|
|||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_gather);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
||||
state->setColorWriteMask(true, true, true, false);
|
||||
state->setColorWriteMask(true, true, true, true);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
_gatherPipeline = gpu::Pipeline::create(program, state);
|
||||
|
@ -458,7 +456,7 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getBuildNormalsPipeline() {
|
|||
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);
|
||||
state->setColorWriteMask(true, true, true, true);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
_buildNormalsPipeline = gpu::Pipeline::create(program, state);
|
||||
|
@ -537,8 +535,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
auto occlusionDepthSize = glm::ivec2(occlusionDepthTexture->getDimensions());
|
||||
|
||||
// Update sample rotation
|
||||
const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / SSAO_SPLIT_COUNT);
|
||||
for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT ; splitId++) {
|
||||
const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / (SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT));
|
||||
for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT ; splitId++) {
|
||||
auto& sample = _aoFrameParametersBuffer[splitId].edit();
|
||||
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
|
||||
}
|
||||
|
@ -568,7 +566,22 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
batch.pushProfileRange("Normal Generation");
|
||||
model.setScale(glm::vec3(normalViewport.z / (sourceViewport.z * depthResolutionScale), normalViewport.w / (sourceViewport.w * depthResolutionScale), 1.0f));
|
||||
{
|
||||
const auto uvScale = glm::vec3(
|
||||
normalViewport.z / (sourceViewport.z * depthResolutionScale),
|
||||
normalViewport.w / (sourceViewport.w * depthResolutionScale),
|
||||
1.0f);
|
||||
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionDepthSize);
|
||||
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(normalViewport.z, normalViewport.w);
|
||||
const auto uvTranslate = glm::vec3(
|
||||
postPixelOffset.x - prePixelOffset.x,
|
||||
postPixelOffset.y - prePixelOffset.y,
|
||||
0.0f
|
||||
);
|
||||
|
||||
model.setScale(uvScale);
|
||||
model.setTranslation(uvTranslate);
|
||||
}
|
||||
batch.setModelTransform(model);
|
||||
|
||||
// Build face normals pass
|
||||
|
@ -595,37 +608,30 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
||||
{
|
||||
const auto uvScale = glm::vec3(
|
||||
(splitSize.x * 2.0f * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
|
||||
(splitSize.y * 2.0f * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
|
||||
(splitSize.x * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
|
||||
(splitSize.y * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
|
||||
1.0f);
|
||||
const auto pixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionDepthSize);
|
||||
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionDepthSize);
|
||||
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize.x, splitSize.y);
|
||||
|
||||
batch.setViewportTransform(splitViewport);
|
||||
|
||||
model.setScale(uvScale);
|
||||
model.setTranslation(glm::vec3(-pixelOffset.x, -pixelOffset.y, 0.0f));
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(0));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
model.setTranslation(glm::vec3(pixelOffset.x, -pixelOffset.y, 0.0f));
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(1));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
model.setTranslation(glm::vec3(pixelOffset.x, pixelOffset.y, 0.0f));
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(3));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
model.setTranslation(glm::vec3(-pixelOffset.x, pixelOffset.y, 0.0f));
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(2));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
for (int y = 0; y < SSAO_SPLIT_COUNT; y++) {
|
||||
for (int x = 0; x < SSAO_SPLIT_COUNT; x++) {
|
||||
const int splitIndex = x + y * SSAO_SPLIT_COUNT;
|
||||
const auto uvTranslate = glm::vec3(
|
||||
postPixelOffset.x * (2 * x + 1) - prePixelOffset.x,
|
||||
postPixelOffset.y * (2 * y + 1) - prePixelOffset.y,
|
||||
0.0f
|
||||
);
|
||||
model.setTranslation(uvTranslate);
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(splitIndex));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[splitIndex]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
|
|
|
@ -64,7 +64,7 @@ protected:
|
|||
gpu::TexturePointer _normalTexture;
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
gpu::FramebufferPointer _occlusionSplitFramebuffers[SSAO_SPLIT_COUNT];
|
||||
gpu::FramebufferPointer _occlusionSplitFramebuffers[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
|
||||
gpu::TexturePointer _occlusionSplitTexture;
|
||||
#endif
|
||||
|
||||
|
@ -181,7 +181,7 @@ private:
|
|||
int getDepthResolutionLevel() const;
|
||||
|
||||
AOParametersBuffer _aoParametersBuffer;
|
||||
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT];
|
||||
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
|
||||
BlurParametersBuffer _vblurParametersBuffer;
|
||||
BlurParametersBuffer _hblurParametersBuffer;
|
||||
|
||||
|
@ -200,7 +200,7 @@ private:
|
|||
static gpu::PipelinePointer _buildNormalsPipeline;
|
||||
|
||||
AmbientOcclusionFramebufferPointer _framebuffer;
|
||||
std::array<float, 16 * SSAO_SPLIT_COUNT> _randomSamples;
|
||||
std::array<float, 3 * SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT> _randomSamples;
|
||||
int _frameId{ 0 };
|
||||
|
||||
gpu::RangeTimerPointer _gpuTimer;
|
||||
|
|
|
@ -160,7 +160,7 @@ const float TWO_PI = 6.2831852;
|
|||
|
||||
vec3 getUnitTapLocation(int sampleNumber, float spiralTurns, float spinAngle, float angleRange){
|
||||
// Radius relative to ssR
|
||||
float alpha = float(sampleNumber + 0.5) * getInvNumSamples();
|
||||
float alpha = float(sampleNumber) * getInvNumSamples();
|
||||
float angle = alpha * (spiralTurns * angleRange) + spinAngle;
|
||||
return vec3(cos(angle), sin(angle), alpha);
|
||||
}
|
||||
|
@ -244,11 +244,11 @@ float getZEyeAtPixel(ivec2 pixel, int level) {
|
|||
}
|
||||
|
||||
float getZEyeAtUV(vec2 texCoord, int level) {
|
||||
return -texture(depthPyramidTex, texCoord, level).x;
|
||||
return -textureLod(depthPyramidTex, texCoord, level).x;
|
||||
}
|
||||
|
||||
vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
|
||||
return normalize(texture(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
|
||||
return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
|
||||
}
|
||||
|
||||
vec3 getNormalEyeAtPixel(ivec2 pixel, int level) {
|
||||
|
@ -285,13 +285,14 @@ vec3 getMinDelta(vec3 centralPoint, vec3 offsetPointPos, vec3 offsetPointNeg) {
|
|||
vec3 delta1 = centralPoint - offsetPointNeg;
|
||||
float sqrLength0 = dot(delta0, delta0);
|
||||
float sqrLength1 = dot(delta1, delta1);
|
||||
return sqrLength0 < sqrLength1 ? delta0 : delta1;
|
||||
float epsilon = 1e-6;
|
||||
return sqrLength0 < sqrLength1 && sqrLength0>epsilon ? delta0 : delta1;
|
||||
}
|
||||
|
||||
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 fragPositionDyPos = buildPosition(side, fragUVPos + vec2(0, deltaDepthUV.y));
|
||||
vec3 fragPositionDyNeg = buildPosition(side, fragUVPos - vec2(0, deltaDepthUV.y));
|
||||
|
||||
vec3 fragPositionDx = getMinDelta(fragPosition, fragPositionDxPos, fragPositionDxNeg);
|
||||
|
@ -356,6 +357,7 @@ float computeHorizonFromTap(vec3 tapPositionES, vec3 fragPositionES, vec3 fragNo
|
|||
|
||||
float computeHorizon(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, vec3 fragNormalES, vec2 searchVec, vec2 pixelSearchVec, float searchRadius) {
|
||||
vec2 absSearchVec = abs(searchVec);
|
||||
pixelSearchVec = abs(pixelSearchVec);
|
||||
int stepCount = int(ceil(max(pixelSearchVec.x, pixelSearchVec.y)));
|
||||
float cosHorizonAngle = 0.0;
|
||||
|
||||
|
@ -488,7 +490,7 @@ vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTex
|
|||
int blurRadius = getBlurRadius();
|
||||
float blurRadialSigma = float(blurRadius) * 0.5;
|
||||
float blurRadialScale = 1.0 / (2.0*blurRadialSigma*blurRadialSigma);
|
||||
vec2 blurScales = -vec2(blurRadialScale, BLUR_EDGE_DISTANCE_SCALE) * getBlurEdgeSharpness();
|
||||
vec2 blurScales = -vec2(blurRadialScale, BLUR_EDGE_DISTANCE_SCALE * getBlurEdgeSharpness());
|
||||
|
||||
// negative side first
|
||||
for (int r = -blurRadius; r <= -1; ++r) {
|
||||
|
|
|
@ -28,12 +28,11 @@ void main(void) {
|
|||
// Gather the four splits of the occlusion result back into an interleaved full size
|
||||
// result (at the resolution level, of course)
|
||||
ivec2 destPixelCoord = ivec2(gl_FragCoord.xy);
|
||||
ivec2 sourcePixelCoord = destPixelCoord / 2;
|
||||
ivec2 splitImageSize = getWidthHeightRoundUp(getResolutionLevel()+1);
|
||||
int occlusionMapIndex = (destPixelCoord.x & 1) + ((destPixelCoord.y) & 1)*2;
|
||||
ivec2 sourcePixelCoord = destPixelCoord / SSAO_SPLIT_COUNT;
|
||||
ivec2 splitImageSize = getWidthHeightRoundUp(getResolutionLevel()+SSAO_SPLIT_LOG2_COUNT);
|
||||
ivec2 modPixelCoord = destPixelCoord % ivec2(SSAO_SPLIT_COUNT);
|
||||
int occlusionMapIndex = modPixelCoord.x + modPixelCoord.y*SSAO_SPLIT_COUNT;
|
||||
vec2 sourceUV = (sourcePixelCoord + vec2(0.5)) / splitImageSize;
|
||||
|
||||
sourcePixelCoord += (destPixelCoord & ivec2(1)) * splitImageSize;
|
||||
|
||||
outFragColor = texture(occlusionMaps, vec3(sourceUV, occlusionMapIndex));
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
#define SSAO_USE_QUAD_SPLIT 1
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
#define SSAO_SPLIT_COUNT 4
|
||||
#define SSAO_SPLIT_LOG2_COUNT 2
|
||||
#else
|
||||
#define SSAO_SPLIT_COUNT 1
|
||||
#define SSAO_SPLIT_LOG2_COUNT 0
|
||||
#endif
|
||||
#define SSAO_SPLIT_COUNT (1 << SSAO_SPLIT_LOG2_COUNT)
|
||||
|
||||
// glsl / C++ compatible source as interface for ambient occlusion
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in a new issue