Finally, a clean HBAO!

This commit is contained in:
Olivier Prat 2018-09-27 10:44:06 +02:00
parent dee0a6afa2
commit 94a162893a
7 changed files with 134 additions and 105 deletions

View file

@ -222,7 +222,7 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
#else #else
numSamples{ 16 }, numSamples{ 16 },
#endif #endif
resolutionLevel{ 1 }, resolutionLevel{ 2 },
blurRadius{ 4 }, blurRadius{ 4 },
ditheringEnabled{ true }, ditheringEnabled{ true },
borderingEnabled{ true }, borderingEnabled{ true },
@ -235,6 +235,9 @@ AmbientOcclusionEffect::AOParameters::AOParameters() {
_radiusInfo = { 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f }; _radiusInfo = { 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f };
_ditheringInfo = { 0.0f, 0.0f, 0.01f, 1.0f }; _ditheringInfo = { 0.0f, 0.0f, 0.01f, 1.0f };
_sampleInfo = { 11.0f, 1.0f / 11.0f, 7.0f, 1.0f }; _sampleInfo = { 11.0f, 1.0f / 11.0f, 7.0f, 1.0f };
}
AmbientOcclusionEffect::BlurParameters::BlurParameters() {
_blurInfo = { 1.0f, 3.0f, 2.0f, 0.0f }; _blurInfo = { 1.0f, 3.0f, 2.0f, 0.0f };
} }
@ -269,14 +272,11 @@ void AmbientOcclusionEffect::configure(const Config& config) {
current.y = 1.0f / (1.0f - config.falloffAngle); current.y = 1.0f / (1.0f - config.falloffAngle);
} }
if (config.edgeSharpness != _aoParametersBuffer->getEdgeSharpness()) { if (config.edgeSharpness != _hblurParametersBuffer.get().getEdgeSharpness()) {
auto& current = _aoParametersBuffer.edit()._blurInfo; auto& hblur = _hblurParametersBuffer.edit()._blurInfo;
current.x = config.edgeSharpness; auto& vblur = _vblurParametersBuffer.edit()._blurInfo;
} hblur.x = config.edgeSharpness;
vblur.x = config.edgeSharpness;
if (config.blurDeviation != _aoParametersBuffer->getBlurDeviation()) {
auto& current = _aoParametersBuffer.edit()._blurInfo;
current.z = config.blurDeviation;
} }
if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) { if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
@ -327,9 +327,11 @@ void AmbientOcclusionEffect::configure(const Config& config) {
shouldUpdateBlurs = true; shouldUpdateBlurs = true;
} }
if (config.blurRadius != _aoParametersBuffer.get().getBlurRadius()) { if (config.blurRadius != _hblurParametersBuffer.get().getBlurRadius()) {
auto& current = _aoParametersBuffer.edit()._blurInfo; auto& hblur = _hblurParametersBuffer.edit()._blurInfo;
current.y = (float)config.blurRadius; auto& vblur = _vblurParametersBuffer.edit()._blurInfo;
hblur.y = (float)config.blurRadius;
vblur.y = (float)config.blurRadius;
} }
if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) { if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
@ -353,31 +355,47 @@ void AmbientOcclusionEffect::updateBlurParameters() {
auto& vblur = _vblurParametersBuffer.edit(); auto& vblur = _vblurParametersBuffer.edit();
auto& hblur = _hblurParametersBuffer.edit(); auto& hblur = _hblurParametersBuffer.edit();
auto frameSize = _framebuffer->getSourceFrameSize(); auto frameSize = _framebuffer->getSourceFrameSize();
if (_framebuffer->isStereo()) {
frameSize.x >>= 1;
}
const auto occlusionSize = divideRoundUp(frameSize, resolutionScale);
hblur.scaleHeight.x = 1.0f / frameSize.x; // Occlusion UV limit
hblur.scaleHeight.y = float(resolutionScale) / frameSize.x; hblur._blurInfo.z = occlusionSize.x / float(frameSize.x);
hblur.scaleHeight.z = frameSize.y / resolutionScale; hblur._blurInfo.w = occlusionSize.y / float(frameSize.y);
vblur.scaleHeight.x = 1.0f / frameSize.y; vblur._blurInfo.z = 1.0f;
vblur.scaleHeight.y = float(resolutionScale) / frameSize.y; vblur._blurInfo.w = occlusionSize.y / float(frameSize.y);
vblur.scaleHeight.z = frameSize.y;
// Depth axis
hblur._blurAxis.x = 1.0f / occlusionSize.x;
hblur._blurAxis.y = 0.0f;
vblur._blurAxis.x = 0.0f;
vblur._blurAxis.y = 1.0f / occlusionSize.y;
// Occlusion axis
hblur._blurAxis.z = hblur._blurAxis.x * hblur._blurInfo.z;
hblur._blurAxis.w = 0.0f;
vblur._blurAxis.z = 0.0f;
vblur._blurAxis.w = vblur._blurAxis.y * vblur._blurInfo.w;
} }
void AmbientOcclusionEffect::updateFramebufferSizes() { void AmbientOcclusionEffect::updateFramebufferSizes() {
auto& params = _aoParametersBuffer.edit(); auto& params = _aoParametersBuffer.edit();
const int widthScale = _framebuffer->isStereo() & 1; const int widthScale = _framebuffer->isStereo() & 1;
auto sourceFrameSize = _framebuffer->getSourceFrameSize(); auto sourceFrameSideSize = _framebuffer->getSourceFrameSize();
const int resolutionLevel = _aoParametersBuffer.get().getResolutionLevel(); sourceFrameSideSize.x >>= widthScale;
const float resolutionScale = powf(0.5f, resolutionLevel);
// Depth is at maximum half depth const int resolutionLevel = _aoParametersBuffer.get().getResolutionLevel();
const int depthResolutionLevel = std::min(1, resolutionLevel); // Depth is at maximum half depth
const float depthResolutionScale = powf(2.0f, depthResolutionLevel); const int depthResolutionLevel = getDepthResolutionLevel();
auto normalTextureSize = _framebuffer->getNormalTexture()->getDimensions(); const auto occlusionDepthFrameSize = divideRoundUp(sourceFrameSideSize, 1 << depthResolutionLevel);
auto occlusionDepthFrameSize = divideRoundUp(sourceFrameSize, depthResolutionLevel); const auto occlusionFrameSize = divideRoundUp(sourceFrameSideSize, 1 << resolutionLevel);
auto normalTextureSize = _framebuffer->getNormalTexture()->getDimensions();
sourceFrameSize.x >>= widthScale;
normalTextureSize.x >>= widthScale; normalTextureSize.x >>= widthScale;
occlusionDepthFrameSize.x >>= widthScale;
params._sideSizes[0].x = normalTextureSize.x; params._sideSizes[0].x = normalTextureSize.x;
params._sideSizes[0].y = normalTextureSize.y; params._sideSizes[0].y = normalTextureSize.y;
@ -386,7 +404,7 @@ void AmbientOcclusionEffect::updateFramebufferSizes() {
params._sideSizes[1].x = params._sideSizes[0].x; params._sideSizes[1].x = params._sideSizes[0].x;
params._sideSizes[1].y = params._sideSizes[0].y; params._sideSizes[1].y = params._sideSizes[0].y;
auto occlusionSplitSize = divideRoundUp(sourceFrameSize, 1 << (resolutionLevel + SSAO_USE_QUAD_SPLIT)); auto occlusionSplitSize = divideRoundUp(occlusionFrameSize, SSAO_SPLIT_COUNT);
params._sideSizes[1].z = occlusionSplitSize.x; params._sideSizes[1].z = occlusionSplitSize.x;
params._sideSizes[1].w = occlusionSplitSize.y; params._sideSizes[1].w = occlusionSplitSize.y;
} }
@ -491,7 +509,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
// We need to take the rounded up resolution. // We need to take the rounded up resolution.
auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel); auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel);
auto firstBlurViewport = sourceViewport; auto firstBlurViewport = sourceViewport;
firstBlurViewport.w = divideRoundUp(firstBlurViewport.w, 1 << resolutionLevel); firstBlurViewport.w = occlusionViewport.w;
if (!_gpuTimer) { if (!_gpuTimer) {
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
@ -550,9 +568,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.resetViewTransform(); batch.resetViewTransform();
Transform model;
batch.setProjectionTransform(glm::mat4()); batch.setProjectionTransform(glm::mat4());
batch.setModelTransform(model); batch.setModelTransform(Transform());
batch.pushProfileRange("Depth Mip Generation"); batch.pushProfileRange("Depth Mip Generation");
// We need this with the mips levels // We need this with the mips levels
@ -578,11 +595,12 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
postPixelOffset.y - prePixelOffset.y, postPixelOffset.y - prePixelOffset.y,
0.0f 0.0f
); );
Transform model;
model.setScale(uvScale); model.setScale(uvScale);
model.setTranslation(uvTranslate); model.setTranslation(uvTranslate);
batch.setModelTransform(model);
} }
batch.setModelTransform(model);
// Build face normals pass // Build face normals pass
batch.setViewportTransform(normalViewport); batch.setViewportTransform(normalViewport);
@ -608,11 +626,12 @@ 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 * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale), (splitSize.x * SSAO_SPLIT_COUNT) / float(occlusionViewport.z),
(splitSize.y * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale), (splitSize.y * SSAO_SPLIT_COUNT) / float(occlusionViewport.w),
1.0f); 1.0f);
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionDepthSize); const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionViewport.z, occlusionViewport.w);
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize.x, splitSize.y); const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize);
Transform model;
batch.setViewportTransform(splitViewport); batch.setViewportTransform(splitViewport);
@ -635,13 +654,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
} }
#else #else
batch.setViewportTransform(occlusionViewport); batch.setViewportTransform(occlusionViewport);
{ model.setIdentity();
const auto uvScale = glm::vec3(
(occlusionViewport.z * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
(occlusionViewport.w * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
1.0f);
model.setScale(uvScale);
}
batch.setModelTransform(model); batch.setModelTransform(model);
batch.setFramebuffer(occlusionFBO); batch.setFramebuffer(occlusionFBO);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]); batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
@ -666,8 +679,15 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
PROFILE_RANGE_BATCH(batch, "Bilateral Blur"); PROFILE_RANGE_BATCH(batch, "Bilateral Blur");
// Blur 1st pass // Blur 1st pass
batch.pushProfileRange("Horizontal"); batch.pushProfileRange("Horizontal");
model.setScale(resolutionScale); {
batch.setModelTransform(model); const auto uvScale = glm::vec3(
occlusionViewport.z / float(sourceViewport.z),
occlusionViewport.w / float(sourceViewport.w),
1.0f);
Transform model;
model.setScale(uvScale);
batch.setModelTransform(model);
}
batch.setViewportTransform(firstBlurViewport); batch.setViewportTransform(firstBlurViewport);
batch.setFramebuffer(occlusionBlurredFBO); batch.setFramebuffer(occlusionBlurredFBO);
// Use full resolution depth and normal for bilateral upscaling and blur // Use full resolution depth and normal for bilateral upscaling and blur
@ -680,8 +700,16 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
// Blur 2nd pass // Blur 2nd pass
batch.pushProfileRange("Vertical"); batch.pushProfileRange("Vertical");
model.setScale(glm::vec3(1.0f, resolutionScale, 1.0f)); {
batch.setModelTransform(model); const auto uvScale = glm::vec3(
1.0f,
occlusionViewport.w / float(sourceViewport.w),
1.0f);
Transform model;
model.setScale(uvScale);
batch.setModelTransform(model);
}
batch.setViewportTransform(sourceViewport); batch.setViewportTransform(sourceViewport);
batch.setFramebuffer(occlusionFBO); batch.setFramebuffer(occlusionFBO);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _vblurParametersBuffer); batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _vblurParametersBuffer);

View file

@ -149,14 +149,11 @@ public:
float getPerspectiveScale() const { return _resolutionInfo.z; } float getPerspectiveScale() const { return _resolutionInfo.z; }
float getObscuranceLevel() const { return _radiusInfo.w; } float getObscuranceLevel() const { return _radiusInfo.w; }
float getFalloffAngle() const { return (float)_ditheringInfo.z; } float getFalloffAngle() const { return (float)_ditheringInfo.z; }
float getEdgeSharpness() const { return (float)_blurInfo.x; }
float getBlurDeviation() const { return _blurInfo.z; }
float getNumSpiralTurns() const { return _sampleInfo.z; } float getNumSpiralTurns() const { return _sampleInfo.z; }
int getNumSamples() const { return (int)_sampleInfo.x; } int getNumSamples() const { return (int)_sampleInfo.x; }
bool isFetchMipsEnabled() const { return _sampleInfo.w; } bool isFetchMipsEnabled() const { return _sampleInfo.w; }
int getBlurRadius() const { return (int)_blurInfo.y; }
bool isDitheringEnabled() const { return _ditheringInfo.x; } bool isDitheringEnabled() const { return _ditheringInfo.x; }
bool isBorderingEnabled() const { return _ditheringInfo.w; } bool isBorderingEnabled() const { return _ditheringInfo.w; }
}; };
@ -165,11 +162,14 @@ public:
private: private:
// Class describing the uniform buffer with all the parameters common to the bilateral blur shaders // Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
class BlurParameters { class BlurParameters : public AmbientOcclusionBlurParams {
public: public:
glm::vec4 scaleHeight{ 0.0f };
BlurParameters() {} BlurParameters();
float getEdgeSharpness() const { return (float)_blurInfo.x; }
int getBlurRadius() const { return (int)_blurInfo.y; }
}; };
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>; using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;

View file

@ -115,14 +115,6 @@ int doFetchMips() {
return int(params._sampleInfo.w); return int(params._sampleInfo.w);
} }
float getBlurEdgeSharpness() {
return params._blurInfo.x;
}
int getBlurRadius() {
return int(params._blurInfo.y);
}
<@endfunc@> <@endfunc@>
<@func declareSamplingDisk()@> <@func declareSamplingDisk()@>
@ -247,6 +239,11 @@ float getZEyeAtUV(vec2 texCoord, int level) {
return -textureLod(depthPyramidTex, texCoord, level).x; return -textureLod(depthPyramidTex, texCoord, level).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);
}
vec3 getNormalEyeAtUV(vec2 texCoord, int level) { vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0)); return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
} }
@ -417,37 +414,42 @@ float evalVisibilityHBAO(ivec4 side, vec2 fragUVPos, vec2 invSideImageSize, vec2
<@endfunc@> <@endfunc@>
<@func declareBlurPass(axis)@> <@func declareBlurPass()@>
<$declarePackOcclusionDepth()$>
<$declareAmbientOcclusion()$> <$declareAmbientOcclusion()$>
<$declareFetchDepthPyramidMap()$> <$declareFetchDepthPyramidMap()$>
<$declarePackOcclusionDepth()$>
// the source occlusion texture // the source occlusion texture
layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap; layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
struct BlurParams {
vec4 scaleHeight;
};
layout(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer { layout(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer {
BlurParams blurParams; AmbientOcclusionBlurParams blurParams;
}; };
float getOcclusionBlurScale() { vec2 getBlurOcclusionAxis() {
return blurParams.scaleHeight.x; return blurParams._blurAxis.zw;
} }
float getDepthBlurScale() { vec2 getBlurDepthAxis() {
return blurParams.scaleHeight.y; return blurParams._blurAxis.xy;
} }
int getBlurImageHeight() { vec2 getBlurOcclusionUVLimit() {
return int(blurParams.scaleHeight.z); return blurParams._blurInfo.zw;
} }
float fetchOcclusion(vec2 coords) { float getBlurEdgeSharpness() {
vec3 raw = texture(occlusionMap, coords, 0).xyz; return blurParams._blurInfo.x;
}
int getBlurRadius() {
return int(blurParams._blurInfo.y);
}
float fetchOcclusion(ivec4 side, vec2 texCoord) {
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo());
vec3 raw = textureLod(occlusionMap, texCoord, 0).xyz;
return raw.x; return raw.x;
} }
@ -458,19 +460,19 @@ float evalBlurCoefficient(vec2 blurScales, float radialDistance, float zDistance
return exp2(dot(blurScales, distances*distances)); return exp2(dot(blurScales, distances*distances));
} }
vec2 evalTapWeightedValue(vec2 blurScales, ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float fragDepth) { vec2 evalTapWeightedValue(vec2 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, vec2 depthTexCoord, float fragDepth) {
ivec2 tapOffset = <$axis$> * r; vec2 tapOcclusionTexCoord = getBlurOcclusionAxis() * r + occlusionTexCoord;
ivec2 tapPixelCoord = destPixelCoord + ivec2(tapOffset); vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit();
if ((tapPixelCoord.x < side.y || tapPixelCoord.x >= side.z + side.y) || (tapPixelCoord.y < 0 || tapPixelCoord.y >= getBlurImageHeight())) { if (tapOcclusionTexCoord.x < side.x || tapOcclusionTexCoord.x >= (side.x + occlusionTexCoordLimits.x)
|| tapOcclusionTexCoord.y < 0 || tapOcclusionTexCoord.y >= occlusionTexCoordLimits.y) {
return vec2(0.0); return vec2(0.0);
} }
vec2 tapTexCoord = scaledTexCoord + tapOffset * getOcclusionBlurScale(); float tapOcclusion = fetchOcclusion(side, tapOcclusionTexCoord);
float tapOcclusion = fetchOcclusion(tapTexCoord);
tapTexCoord = fullTexCoord + tapOffset * getDepthBlurScale(); vec2 tapDepthTexCoord = getBlurDepthAxis() * r + depthTexCoord;
float tapDepth = getZEyeAtUV(tapTexCoord, 0); float tapDepth = getZEyeAtUV(side, tapDepthTexCoord, 0);
// range domain (the "bilateral" weight). As depth difference increases, decrease weight. // range domain (the "bilateral" weight). As depth difference increases, decrease weight.
float zDistance = tapDepth - fragDepth; float zDistance = tapDepth - fragDepth;
@ -479,11 +481,11 @@ vec2 evalTapWeightedValue(vec2 blurScales, ivec3 side, int r, ivec2 destPixelCoo
return vec2(tapOcclusion * weight, weight); return vec2(tapOcclusion * weight, weight);
} }
vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord) { vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 depthTexCoord) {
// Stereo side info // Stereo side info
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0); ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
float fragDepth = getZEyeAtUV(fullTexCoord, 0); float fragDepth = getZEyeAtUV(side, depthTexCoord, 0);
vec2 weightedSums = vec2(0.0); vec2 weightedSums = vec2(0.0);
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range // Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
@ -494,17 +496,17 @@ vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTex
// negative side first // negative side first
for (int r = -blurRadius; r <= -1; ++r) { for (int r = -blurRadius; r <= -1; ++r) {
weightedSums += evalTapWeightedValue(blurScales, side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, fragDepth); weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepth);
} }
// Central pixel contribution // Central pixel contribution
float mainWeight = 1.0; float mainWeight = 1.0;
float pixelOcclusion = fetchOcclusion(scaledTexCoord); float pixelOcclusion = fetchOcclusion(side, occlusionTexCoord);
weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight); weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight);
// then positive side // then positive side
for (int r = 1; r <= blurRadius; ++r) { for (int r = 1; r <= blurRadius; ++r) {
weightedSums += evalTapWeightedValue(blurScales, side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, fragDepth); weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepth);
} }
// Final normalization // Final normalization

View file

@ -28,11 +28,9 @@ 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 / SSAO_SPLIT_COUNT; ivec2 sourcePixelCoord = destPixelCoord >> SSAO_SPLIT_LOG2_COUNT;
ivec2 splitImageSize = getWidthHeightRoundUp(getResolutionLevel()+SSAO_SPLIT_LOG2_COUNT); ivec2 modPixelCoord = destPixelCoord & (SSAO_SPLIT_COUNT-1);
ivec2 modPixelCoord = destPixelCoord % ivec2(SSAO_SPLIT_COUNT); int occlusionMapIndex = modPixelCoord.x + (modPixelCoord.y << SSAO_SPLIT_LOG2_COUNT);
int occlusionMapIndex = modPixelCoord.x + modPixelCoord.y*SSAO_SPLIT_COUNT;
vec2 sourceUV = (sourcePixelCoord + vec2(0.5)) / splitImageSize;
outFragColor = texture(occlusionMaps, vec3(sourceUV, occlusionMapIndex)); outFragColor = texelFetch(occlusionMaps, ivec3(sourcePixelCoord, occlusionMapIndex), 0);
} }

View file

@ -15,8 +15,7 @@
// Hack comment // Hack comment
const ivec2 horizontal = ivec2(1,0); <$declareBlurPass()$>
<$declareBlurPass(horizontal)$>
layout(location=0) in vec4 varTexCoord0; layout(location=0) in vec4 varTexCoord0;

View file

@ -14,14 +14,12 @@
// Hack comment // Hack comment
const ivec2 vertical = ivec2(0,1); <$declareBlurPass()$>
<$declareBlurPass(vertical)$>
layout(location=0) in vec4 varTexCoord0; layout(location=0) in vec4 varTexCoord0;
layout(location=0) out vec4 outFragColor; layout(location=0) out vec4 outFragColor;
void main(void) { void main(void) {
float occlusion = getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw).x; outFragColor = vec4(getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw), 1.0);
outFragColor = vec4(occlusion, 0.0, 0.0, occlusion);
} }

View file

@ -27,10 +27,10 @@
// glsl / C++ compatible source as interface for ambient occlusion // glsl / C++ compatible source as interface for ambient occlusion
#ifdef __cplusplus #ifdef __cplusplus
# define SSAO_VEC4 glm::vec4 # define SSAO_VEC4 glm::vec4
# define SSAO_IVEC4 glm::ivec4 # define SSAO_MAT4 glm::mat4
#else #else
# define SSAO_VEC4 vec4 # define SSAO_VEC4 vec4
# define SSAO_IVEC4 ivec4 # define SSAO_MAT4 mat4
#endif #endif
struct AmbientOcclusionParams { struct AmbientOcclusionParams {
@ -38,7 +38,6 @@ struct AmbientOcclusionParams {
SSAO_VEC4 _radiusInfo; SSAO_VEC4 _radiusInfo;
SSAO_VEC4 _ditheringInfo; SSAO_VEC4 _ditheringInfo;
SSAO_VEC4 _sampleInfo; SSAO_VEC4 _sampleInfo;
SSAO_VEC4 _blurInfo;
SSAO_VEC4 _sideSizes[2]; SSAO_VEC4 _sideSizes[2];
}; };
@ -46,6 +45,11 @@ struct AmbientOcclusionFrameParams {
SSAO_VEC4 _angleInfo; SSAO_VEC4 _angleInfo;
}; };
struct AmbientOcclusionBlurParams {
SSAO_VEC4 _blurInfo;
SSAO_VEC4 _blurAxis;
};
#endif // RENDER_UTILS_SHADER_CONSTANTS_H #endif // RENDER_UTILS_SHADER_CONSTANTS_H
// <@if 1@> // <@if 1@>