mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 03:37:17 +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 height = _frameSize.y;
|
||||||
auto format = gpu::Element::COLOR_R_8;
|
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));
|
_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 = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
|
||||||
_occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture);
|
_occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture);
|
||||||
|
@ -125,7 +123,7 @@ void AmbientOcclusionFramebuffer::allocate() {
|
||||||
if (_isStereo) {
|
if (_isStereo) {
|
||||||
splitSize.x >>= 1;
|
splitSize.x >>= 1;
|
||||||
}
|
}
|
||||||
splitSize = divideRoundUp(splitSize, 2 << _resolutionLevel);
|
splitSize = divideRoundUp(splitSize, SSAO_SPLIT_COUNT << _resolutionLevel);
|
||||||
if (_isStereo) {
|
if (_isStereo) {
|
||||||
splitSize.x <<= 1;
|
splitSize.x <<= 1;
|
||||||
}
|
}
|
||||||
|
@ -133,9 +131,9 @@ void AmbientOcclusionFramebuffer::allocate() {
|
||||||
auto height = splitSize.y;
|
auto height = splitSize.y;
|
||||||
auto format = gpu::Element::COLOR_R_8;
|
auto format = gpu::Element::COLOR_R_8;
|
||||||
|
|
||||||
_occlusionSplitTexture = gpu::Texture::createRenderBufferArray(format, width, height, SSAO_SPLIT_COUNT, gpu::Texture::SINGLE_MIP,
|
_occlusionSplitTexture = gpu::Texture::createRenderBufferArray(format, width, height, SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT, gpu::Texture::SINGLE_MIP,
|
||||||
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP));
|
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
|
||||||
for (int i = 0; i < SSAO_SPLIT_COUNT; i++) {
|
for (int i = 0; i < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT; i++) {
|
||||||
_occlusionSplitFramebuffers[i] = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
|
_occlusionSplitFramebuffers[i] = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
|
||||||
_occlusionSplitFramebuffers[i]->setRenderBuffer(0, _occlusionSplitTexture, i);
|
_occlusionSplitFramebuffers[i]->setRenderBuffer(0, _occlusionSplitTexture, i);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +143,7 @@ void AmbientOcclusionFramebuffer::allocate() {
|
||||||
|
|
||||||
#if SSAO_USE_QUAD_SPLIT
|
#if SSAO_USE_QUAD_SPLIT
|
||||||
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getOcclusionSplitFramebuffer(int index) {
|
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getOcclusionSplitFramebuffer(int index) {
|
||||||
assert(index < SSAO_SPLIT_COUNT);
|
assert(index < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT);
|
||||||
if (!_occlusionSplitFramebuffers[index]) {
|
if (!_occlusionSplitFramebuffers[index]) {
|
||||||
allocate();
|
allocate();
|
||||||
}
|
}
|
||||||
|
@ -220,7 +218,7 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
|
||||||
blurDeviation{ 2.5f },
|
blurDeviation{ 2.5f },
|
||||||
numSpiralTurns{ 7.0f },
|
numSpiralTurns{ 7.0f },
|
||||||
#if SSAO_USE_HORIZON_BASED
|
#if SSAO_USE_HORIZON_BASED
|
||||||
numSamples{ 3 },
|
numSamples{ 1 },
|
||||||
#else
|
#else
|
||||||
numSamples{ 16 },
|
numSamples{ 16 },
|
||||||
#endif
|
#endif
|
||||||
|
@ -305,7 +303,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
||||||
r = r + f * (float)(index % B);
|
r = r + f * (float)(index % B);
|
||||||
index = 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::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_gather);
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
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
|
// Good to go add the brand new pipeline
|
||||||
_gatherPipeline = gpu::Pipeline::create(program, state);
|
_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::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_buildNormals);
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
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
|
// Good to go add the brand new pipeline
|
||||||
_buildNormalsPipeline = gpu::Pipeline::create(program, state);
|
_buildNormalsPipeline = gpu::Pipeline::create(program, state);
|
||||||
|
@ -537,8 +535,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
auto occlusionDepthSize = glm::ivec2(occlusionDepthTexture->getDimensions());
|
auto occlusionDepthSize = glm::ivec2(occlusionDepthTexture->getDimensions());
|
||||||
|
|
||||||
// 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*SSAO_SPLIT_COUNT));
|
||||||
for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT ; splitId++) {
|
for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT ; splitId++) {
|
||||||
auto& sample = _aoFrameParametersBuffer[splitId].edit();
|
auto& sample = _aoFrameParametersBuffer[splitId].edit();
|
||||||
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
|
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
|
#if SSAO_USE_QUAD_SPLIT
|
||||||
batch.pushProfileRange("Normal Generation");
|
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);
|
batch.setModelTransform(model);
|
||||||
|
|
||||||
// Build face normals pass
|
// Build face normals pass
|
||||||
|
@ -595,38 +608,31 @@ 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 uvScale = glm::vec3(
|
const auto uvScale = glm::vec3(
|
||||||
(splitSize.x * 2.0f * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
|
(splitSize.x * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
|
||||||
(splitSize.y * 2.0f * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
|
(splitSize.y * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
|
||||||
1.0f);
|
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);
|
batch.setViewportTransform(splitViewport);
|
||||||
|
|
||||||
model.setScale(uvScale);
|
model.setScale(uvScale);
|
||||||
model.setTranslation(glm::vec3(-pixelOffset.x, -pixelOffset.y, 0.0f));
|
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.setModelTransform(model);
|
||||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(0));
|
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(splitIndex));
|
||||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[splitIndex]);
|
||||||
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);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
batch.setViewportTransform(occlusionViewport);
|
batch.setViewportTransform(occlusionViewport);
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,7 +64,7 @@ protected:
|
||||||
gpu::TexturePointer _normalTexture;
|
gpu::TexturePointer _normalTexture;
|
||||||
|
|
||||||
#if SSAO_USE_QUAD_SPLIT
|
#if SSAO_USE_QUAD_SPLIT
|
||||||
gpu::FramebufferPointer _occlusionSplitFramebuffers[SSAO_SPLIT_COUNT];
|
gpu::FramebufferPointer _occlusionSplitFramebuffers[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
|
||||||
gpu::TexturePointer _occlusionSplitTexture;
|
gpu::TexturePointer _occlusionSplitTexture;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ private:
|
||||||
int getDepthResolutionLevel() const;
|
int getDepthResolutionLevel() const;
|
||||||
|
|
||||||
AOParametersBuffer _aoParametersBuffer;
|
AOParametersBuffer _aoParametersBuffer;
|
||||||
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT];
|
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
|
||||||
BlurParametersBuffer _vblurParametersBuffer;
|
BlurParametersBuffer _vblurParametersBuffer;
|
||||||
BlurParametersBuffer _hblurParametersBuffer;
|
BlurParametersBuffer _hblurParametersBuffer;
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ private:
|
||||||
static gpu::PipelinePointer _buildNormalsPipeline;
|
static gpu::PipelinePointer _buildNormalsPipeline;
|
||||||
|
|
||||||
AmbientOcclusionFramebufferPointer _framebuffer;
|
AmbientOcclusionFramebufferPointer _framebuffer;
|
||||||
std::array<float, 16 * SSAO_SPLIT_COUNT> _randomSamples;
|
std::array<float, 3 * SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT> _randomSamples;
|
||||||
int _frameId{ 0 };
|
int _frameId{ 0 };
|
||||||
|
|
||||||
gpu::RangeTimerPointer _gpuTimer;
|
gpu::RangeTimerPointer _gpuTimer;
|
||||||
|
|
|
@ -160,7 +160,7 @@ const float TWO_PI = 6.2831852;
|
||||||
|
|
||||||
vec3 getUnitTapLocation(int sampleNumber, float spiralTurns, float spinAngle, float angleRange){
|
vec3 getUnitTapLocation(int sampleNumber, float spiralTurns, float spinAngle, float angleRange){
|
||||||
// Radius relative to ssR
|
// Radius relative to ssR
|
||||||
float alpha = float(sampleNumber + 0.5) * getInvNumSamples();
|
float alpha = float(sampleNumber) * getInvNumSamples();
|
||||||
float angle = alpha * (spiralTurns * angleRange) + spinAngle;
|
float angle = alpha * (spiralTurns * angleRange) + spinAngle;
|
||||||
return vec3(cos(angle), sin(angle), alpha);
|
return vec3(cos(angle), sin(angle), alpha);
|
||||||
}
|
}
|
||||||
|
@ -244,11 +244,11 @@ float getZEyeAtPixel(ivec2 pixel, int level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float getZEyeAtUV(vec2 texCoord, 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) {
|
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) {
|
vec3 getNormalEyeAtPixel(ivec2 pixel, int level) {
|
||||||
|
@ -285,13 +285,14 @@ vec3 getMinDelta(vec3 centralPoint, vec3 offsetPointPos, vec3 offsetPointNeg) {
|
||||||
vec3 delta1 = centralPoint - offsetPointNeg;
|
vec3 delta1 = centralPoint - offsetPointNeg;
|
||||||
float sqrLength0 = dot(delta0, delta0);
|
float sqrLength0 = dot(delta0, delta0);
|
||||||
float sqrLength1 = dot(delta1, delta1);
|
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 buildNormal(ivec4 side, vec2 fragUVPos, vec3 fragPosition, vec2 deltaDepthUV) {
|
||||||
vec3 fragPositionDxPos = buildPosition(side, fragUVPos + vec2(deltaDepthUV.x, 0));
|
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 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 fragPositionDyNeg = buildPosition(side, fragUVPos - vec2(0, deltaDepthUV.y));
|
||||||
|
|
||||||
vec3 fragPositionDx = getMinDelta(fragPosition, fragPositionDxPos, fragPositionDxNeg);
|
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) {
|
float computeHorizon(ivec4 side, vec2 fragUVPos, vec3 fragPositionES, vec3 fragNormalES, vec2 searchVec, vec2 pixelSearchVec, float searchRadius) {
|
||||||
vec2 absSearchVec = abs(searchVec);
|
vec2 absSearchVec = abs(searchVec);
|
||||||
|
pixelSearchVec = abs(pixelSearchVec);
|
||||||
int stepCount = int(ceil(max(pixelSearchVec.x, pixelSearchVec.y)));
|
int stepCount = int(ceil(max(pixelSearchVec.x, pixelSearchVec.y)));
|
||||||
float cosHorizonAngle = 0.0;
|
float cosHorizonAngle = 0.0;
|
||||||
|
|
||||||
|
@ -488,7 +490,7 @@ vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTex
|
||||||
int blurRadius = getBlurRadius();
|
int blurRadius = getBlurRadius();
|
||||||
float blurRadialSigma = float(blurRadius) * 0.5;
|
float blurRadialSigma = float(blurRadius) * 0.5;
|
||||||
float blurRadialScale = 1.0 / (2.0*blurRadialSigma*blurRadialSigma);
|
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
|
// negative side first
|
||||||
for (int r = -blurRadius; r <= -1; ++r) {
|
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
|
// Gather the four splits of the occlusion result back into an interleaved full size
|
||||||
// result (at the resolution level, of course)
|
// result (at the resolution level, of course)
|
||||||
ivec2 destPixelCoord = ivec2(gl_FragCoord.xy);
|
ivec2 destPixelCoord = ivec2(gl_FragCoord.xy);
|
||||||
ivec2 sourcePixelCoord = destPixelCoord / 2;
|
ivec2 sourcePixelCoord = destPixelCoord / SSAO_SPLIT_COUNT;
|
||||||
ivec2 splitImageSize = getWidthHeightRoundUp(getResolutionLevel()+1);
|
ivec2 splitImageSize = getWidthHeightRoundUp(getResolutionLevel()+SSAO_SPLIT_LOG2_COUNT);
|
||||||
int occlusionMapIndex = (destPixelCoord.x & 1) + ((destPixelCoord.y) & 1)*2;
|
ivec2 modPixelCoord = destPixelCoord % ivec2(SSAO_SPLIT_COUNT);
|
||||||
|
int occlusionMapIndex = modPixelCoord.x + modPixelCoord.y*SSAO_SPLIT_COUNT;
|
||||||
vec2 sourceUV = (sourcePixelCoord + vec2(0.5)) / splitImageSize;
|
vec2 sourceUV = (sourcePixelCoord + vec2(0.5)) / splitImageSize;
|
||||||
|
|
||||||
sourcePixelCoord += (destPixelCoord & ivec2(1)) * splitImageSize;
|
|
||||||
|
|
||||||
outFragColor = texture(occlusionMaps, vec3(sourceUV, occlusionMapIndex));
|
outFragColor = texture(occlusionMaps, vec3(sourceUV, occlusionMapIndex));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
#define SSAO_USE_QUAD_SPLIT 1
|
#define SSAO_USE_QUAD_SPLIT 1
|
||||||
|
|
||||||
#if SSAO_USE_QUAD_SPLIT
|
#if SSAO_USE_QUAD_SPLIT
|
||||||
#define SSAO_SPLIT_COUNT 4
|
#define SSAO_SPLIT_LOG2_COUNT 2
|
||||||
#else
|
#else
|
||||||
#define SSAO_SPLIT_COUNT 1
|
#define SSAO_SPLIT_LOG2_COUNT 0
|
||||||
#endif
|
#endif
|
||||||
|
#define SSAO_SPLIT_COUNT (1 << SSAO_SPLIT_LOG2_COUNT)
|
||||||
|
|
||||||
// glsl / C++ compatible source as interface for ambient occlusion
|
// glsl / C++ compatible source as interface for ambient occlusion
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in a new issue