aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2024-04-30 14:16:46 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2024-05-06 15:51:04 +0200
commita22a94a3363ce1907fb39c4bd1990b8542da7f61 (patch)
treefee7bb96423e42802051bb345d77724f7e01e434
parentb26d2cec2293e6b3efce6b695a58c11df1c78dae (diff)
Make SSAO multiview-aware
Change-Id: I12ab28dae42de99043415941b463a24c371eae14 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/quick3d/qquick3dcustommaterial.cpp18
-rw-r--r--src/runtimerender/graphobjects/qssgrendercustommaterial_p.h3
-rw-r--r--src/runtimerender/qssgrhicontext_p.h1
-rw-r--r--src/runtimerender/qssgrhicustommaterialsystem.cpp21
-rw-r--r--src/runtimerender/qssgshadermaterialadapter.cpp7
-rw-r--r--src/runtimerender/rendererimpl/qssgrendererimplshaders_p.h2
-rw-r--r--src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp4
-rw-r--r--src/runtimerender/rendererimpl/qssgrenderhelpers.cpp32
-rw-r--r--src/runtimerender/rendererimpl/qssgrenderpass.cpp2
-rw-r--r--src/runtimerender/res/effectlib/ssao.glsllib8
-rw-r--r--src/runtimerender/res/rhishaders/ssao.frag42
-rw-r--r--src/runtimerender/res/rhishaders/ssao.vert9
-rw-r--r--src/runtimerender/resourcemanager/qssgrendershaderlibrarymanager_p.h3
-rw-r--r--tests/manual/qmlxr/testscenes/models/object1.meshbin0 -> 184460 bytes
-rw-r--r--tests/manual/qmlxr/testscenes/ssao.qml28
15 files changed, 158 insertions, 22 deletions
diff --git a/src/quick3d/qquick3dcustommaterial.cpp b/src/quick3d/qquick3dcustommaterial.cpp
index a0426686..73c2a18e 100644
--- a/src/quick3d/qquick3dcustommaterial.cpp
+++ b/src/quick3d/qquick3dcustommaterial.cpp
@@ -1163,6 +1163,22 @@ QT_BEGIN_NAMESPACE
float aoFactor = texture(AO_TEXTURE, aoUV).x;
\endcode
+ \li \c AO_TEXTURE_ARRAY - Available only when multiview rendering is in use.
+ Similar to \c AO_TEXTURE, but this is a 2D texture array (sampler2DArray).
+ Use \c VIEW_INDEX as the layer (the third coordinate in the \c uv argument in
+ \c{texture()}). Portable custom materials that wish to function both with and
+ without multiview rendering, can do the following: \badcode
+ #if QSHADER_VIEW_COUNT >= 2
+ ivec2 aoSize = textureSize(AO_TEXTURE_ARRAY, 0).xy;
+ vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
+ float aoFactor = texture(AO_TEXTURE_ARRAY, vec3(aoUV, VIEW_INDEX)).x;
+ #else
+ ivec2 aoSize = textureSize(AO_TEXTURE, 0);
+ vec2 aoUV = (FRAGCOORD.xy) / vec2(aoSize);
+ float aoFactor = texture(AO_TEXTURE, aoUV).x;
+ #endif
+ \endcode
+
\li \c IBL_TEXTURE - It will not enable any special rendering pass, but it can
be used when the material has \l {Material::lightProbe} or the model is in the scope of
\l {SceneEnvironment::lightProbe}.
@@ -1592,6 +1608,8 @@ static void setCustomMaterialFlagsFromShader(QSSGRenderCustomMaterial *material,
material->m_renderFlags.setFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenTextureArray, true);
if (meta.flags.testFlag(QSSGCustomShaderMetaData::UsesScreenMipTextureArray))
material->m_renderFlags.setFlag(QSSGRenderCustomMaterial::RenderFlag::ScreenMipTextureArray, true);
+ if (meta.flags.testFlag(QSSGCustomShaderMetaData::UsesAoTextureArray))
+ material->m_renderFlags.setFlag(QSSGRenderCustomMaterial::RenderFlag::AoTextureArray, true);
// vertex only
if (meta.flags.testFlag(QSSGCustomShaderMetaData::OverridesPosition))
diff --git a/src/runtimerender/graphobjects/qssgrendercustommaterial_p.h b/src/runtimerender/graphobjects/qssgrendercustommaterial_p.h
index 6699ff91..2e8432da 100644
--- a/src/runtimerender/graphobjects/qssgrendercustommaterial_p.h
+++ b/src/runtimerender/graphobjects/qssgrendercustommaterial_p.h
@@ -108,7 +108,8 @@ struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGRenderCustomMaterial : public QSSGRende
ViewIndex = 1 << 13,
DepthTextureArray = 1 << 14,
ScreenTextureArray = 1 << 15,
- ScreenMipTextureArray = 1 << 16
+ ScreenMipTextureArray = 1 << 16,
+ AoTextureArray = 1 << 17
};
Q_DECLARE_FLAGS(RenderFlags, RenderFlag)
diff --git a/src/runtimerender/qssgrhicontext_p.h b/src/runtimerender/qssgrhicontext_p.h
index 6da57bbe..433c8860 100644
--- a/src/runtimerender/qssgrhicontext_p.h
+++ b/src/runtimerender/qssgrhicontext_p.h
@@ -264,6 +264,7 @@ enum class QSSGRhiSamplerBindingHints
LightmapTexture,
DepthTextureArray,
ScreenTextureArray,
+ AoTextureArray,
BindingMapSize
};
diff --git a/src/runtimerender/qssgrhicustommaterialsystem.cpp b/src/runtimerender/qssgrhicustommaterialsystem.cpp
index 3d0b1f1f..84a76a35 100644
--- a/src/runtimerender/qssgrhicustommaterialsystem.cpp
+++ b/src/runtimerender/qssgrhicustommaterialsystem.cpp
@@ -425,15 +425,24 @@ void QSSGCustomMaterialSystem::rhiPrepareRenderable(QSSGRhiGraphicsPipelineState
}
if (shaderPipeline->ssaoTexture()) {
- int binding = shaderPipeline->bindingForTexture("qt_aoTexture", int(QSSGRhiSamplerBindingHints::AoTexture));
- if (binding >= 0) {
- samplerBindingsSpecified.setBit(binding);
+ const int ssaoTextureBinding = shaderPipeline->bindingForTexture("qt_aoTexture", int(QSSGRhiSamplerBindingHints::AoTexture));
+ const int ssaoTextureArrayBinding = shaderPipeline->bindingForTexture("qt_aoTextureArray", int(QSSGRhiSamplerBindingHints::AoTextureArray));
+ if (ssaoTextureBinding >= 0 || ssaoTextureArrayBinding >= 0) {
// linear min/mag, no mipmap
QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
- bindings.addTexture(binding,
- QRhiShaderResourceBinding::FragmentStage,
- shaderPipeline->ssaoTexture(), sampler);
+ if (ssaoTextureBinding >= 0) {
+ samplerBindingsSpecified.setBit(ssaoTextureBinding);
+ bindings.addTexture(ssaoTextureBinding,
+ QRhiShaderResourceBinding::FragmentStage,
+ shaderPipeline->ssaoTexture(), sampler);
+ }
+ if (ssaoTextureArrayBinding >= 0) {
+ samplerBindingsSpecified.setBit(ssaoTextureArrayBinding);
+ bindings.addTexture(ssaoTextureArrayBinding,
+ QRhiShaderResourceBinding::FragmentStage,
+ shaderPipeline->ssaoTexture(), sampler);
+ }
} // else ignore, not an error
}
diff --git a/src/runtimerender/qssgshadermaterialadapter.cpp b/src/runtimerender/qssgshadermaterialadapter.cpp
index ed82fe1d..d2598e03 100644
--- a/src/runtimerender/qssgshadermaterialadapter.cpp
+++ b/src/runtimerender/qssgshadermaterialadapter.cpp
@@ -730,6 +730,7 @@ static const QSSGCustomMaterialVariableSubstitution qssg_var_subst_tab[] = {
{ "DEPTH_TEXTURE", "qt_depthTexture", false },
{ "DEPTH_TEXTURE_ARRAY", "qt_depthTextureArray", false },
{ "AO_TEXTURE", "qt_aoTexture", false },
+ { "AO_TEXTURE", "qt_aoTextureArray", false },
{ "IBL_TEXTURE", "qt_lightProbe", false },
{ "LIGHTMAP", "qt_lightmap", false },
@@ -974,6 +975,8 @@ QSSGShaderCustomMaterialAdapter::prepareCustomShader(QByteArray &dst,
md.flags |= QSSGCustomShaderMetaData::UsesDepthTexture;
else if (trimmedId == QByteArrayLiteral("AO_TEXTURE"))
md.flags |= QSSGCustomShaderMetaData::UsesAoTexture;
+ else if (trimmedId == QByteArrayLiteral("AO_TEXTURE_ARRAY"))
+ md.flags |= QSSGCustomShaderMetaData::UsesAoTextureArray;
else if (trimmedId == QByteArrayLiteral("POSITION"))
md.flags |= QSSGCustomShaderMetaData::OverridesPosition;
else if (trimmedId == QByteArrayLiteral("PROJECTION_MATRIX"))
@@ -1107,8 +1110,12 @@ QSSGShaderCustomMaterialAdapter::prepareCustomShader(QByteArray &dst,
if ((md.flags.testFlag(QSSGCustomShaderMetaData::UsesScreenTextureArray) || md.flags.testFlag(QSSGCustomShaderMetaData::UsesScreenMipTextureArray)) && multiViewCompatible)
allUniforms.append({ "sampler2DArray", "qt_screenTextureArray" });
+ // And for SSAO.
if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesAoTexture))
allUniforms.append({ "sampler2D", "qt_aoTexture" });
+ if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesAoTextureArray))
+ allUniforms.append({ "sampler2DArray", "qt_aoTextureArray" });
+
if (md.flags.testFlag(QSSGCustomShaderMetaData::UsesLightmap))
allUniforms.append({ "sampler2D", "qt_lightmap" });
diff --git a/src/runtimerender/rendererimpl/qssgrendererimplshaders_p.h b/src/runtimerender/rendererimpl/qssgrendererimplshaders_p.h
index 94bcd4ed..300522d1 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimplshaders_p.h
+++ b/src/runtimerender/rendererimpl/qssgrendererimplshaders_p.h
@@ -46,7 +46,7 @@ public:
QSSGRhiShaderPipelinePtr getRhiGridShader(int viewCount);
QSSGRhiShaderPipelinePtr getRhiOrthographicShadowBlurXShader();
QSSGRhiShaderPipelinePtr getRhiOrthographicShadowBlurYShader();
- QSSGRhiShaderPipelinePtr getRhiSsaoShader();
+ QSSGRhiShaderPipelinePtr getRhiSsaoShader(int viewCount);
QSSGRhiShaderPipelinePtr getRhiSkyBoxCubeShader(int viewCount);
QSSGRhiShaderPipelinePtr getRhiSkyBoxShader(QSSGRenderLayer::TonemapMode tonemapMode, bool isRGBE, int viewCount);
QSSGRhiShaderPipelinePtr getRhiSupersampleResolveShader();
diff --git a/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp b/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp
index 653110d9..6624b6e3 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp
+++ b/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp
@@ -64,9 +64,9 @@ QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiOrthographicShadowBlur
return getBuiltinRhiShader(QByteArrayLiteral("orthoshadowblury"), m_cache.orthographicShadowBlurYRhiShader);
}
-QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSsaoShader()
+QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSsaoShader(int viewCount)
{
- return getBuiltinRhiShader(QByteArrayLiteral("ssao"), m_cache.ssaoRhiShader);
+ return getBuiltinRhiShader(QByteArrayLiteral("ssao"), m_cache.ssaoRhiShader, viewCount);
}
QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSkyBoxCubeShader(int viewCount)
diff --git a/src/runtimerender/rendererimpl/qssgrenderhelpers.cpp b/src/runtimerender/rendererimpl/qssgrenderhelpers.cpp
index d074c7cb..9b5077a7 100644
--- a/src/runtimerender/rendererimpl/qssgrenderhelpers.cpp
+++ b/src/runtimerender/rendererimpl/qssgrenderhelpers.cpp
@@ -515,12 +515,22 @@ static inline void addDepthTextureBindings(QSSGRhiContext *rhiCtx,
// SSAO texture
if (shaderPipeline->ssaoTexture()) {
- int binding = shaderPipeline->bindingForTexture("qt_aoTexture", int(QSSGRhiSamplerBindingHints::AoTexture));
- if (binding >= 0) {
+ const int ssaoTextureBinding = shaderPipeline->bindingForTexture("qt_aoTexture", int(QSSGRhiSamplerBindingHints::AoTexture));
+ const int ssaoTextureArrayBinding = shaderPipeline->bindingForTexture("qt_aoTextureArray", int(QSSGRhiSamplerBindingHints::AoTextureArray));
+ if (ssaoTextureBinding >= 0 || ssaoTextureArrayBinding >= 0) {
// linear min/mag, no mipmap
QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
- QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
- bindings.addTexture(binding, QRhiShaderResourceBinding::FragmentStage, shaderPipeline->ssaoTexture(), sampler);
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
+ if (ssaoTextureBinding >= 0) {
+ bindings.addTexture(ssaoTextureBinding,
+ QRhiShaderResourceBinding::FragmentStage,
+ shaderPipeline->ssaoTexture(), sampler);
+ }
+ if (ssaoTextureArrayBinding >= 0) {
+ bindings.addTexture(ssaoTextureArrayBinding,
+ QRhiShaderResourceBinding::FragmentStage,
+ shaderPipeline->ssaoTexture(), sampler);
+ }
} // else ignore, not an error
}
}
@@ -1517,8 +1527,12 @@ bool RenderHelpers::rhiPrepareAoTexture(QSSGRhiContext *rhiCtx, const QSize &siz
bool needsBuild = false;
if (!renderableTex->texture) {
+ QRhiTexture::Flags flags = QRhiTexture::RenderTarget;
// the ambient occlusion texture is always non-msaa, even if multisampling is used in the main pass
- renderableTex->texture = rhiCtx->rhi()->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
+ if (rhiCtx->mainPassViewCount() <= 1)
+ renderableTex->texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, flags);
+ else
+ renderableTex->texture = rhi->newTextureArray(QRhiTexture::RGBA8, rhiCtx->mainPassViewCount(), size, 1, flags);
needsBuild = true;
} else if (renderableTex->texture->pixelSize() != size) {
renderableTex->texture->setPixelSize(size);
@@ -1532,7 +1546,11 @@ bool RenderHelpers::rhiPrepareAoTexture(QSSGRhiContext *rhiCtx, const QSize &siz
return false;
}
renderableTex->resetRenderTarget();
- renderableTex->rt = rhi->newTextureRenderTarget({ renderableTex->texture });
+ QRhiTextureRenderTargetDescription desc;
+ QRhiColorAttachment colorAttachment(renderableTex->texture);
+ colorAttachment.setMultiViewCount(rhiCtx->mainPassViewCount());
+ desc.setColorAttachments({ colorAttachment });
+ renderableTex->rt = rhi->newTextureRenderTarget(desc);
renderableTex->rt->setName(QByteArrayLiteral("Ambient occlusion"));
renderableTex->rpDesc = renderableTex->rt->newCompatibleRenderPassDescriptor();
renderableTex->rt->setRenderPassDescriptor(renderableTex->rpDesc);
@@ -1611,6 +1629,8 @@ void RenderHelpers::rhiRenderAoTexture(QSSGRhiContext *rhiCtx,
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
QSSGRhiShaderResourceBindingList bindings;
bindings.addUniformBuffer(0, RENDERER_VISIBILITY_ALL, dcd.ubuf);
+ // binding 1 is either a sampler2D or sampler2DArray, matching
+ // rhiDepthTexture.texture, no special casing needed here
bindings.addTexture(1, QRhiShaderResourceBinding::FragmentStage, rhiDepthTexture.texture, sampler);
QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
diff --git a/src/runtimerender/rendererimpl/qssgrenderpass.cpp b/src/runtimerender/rendererimpl/qssgrenderpass.cpp
index 8830988e..d10b2eea 100644
--- a/src/runtimerender/rendererimpl/qssgrenderpass.cpp
+++ b/src/runtimerender/rendererimpl/qssgrenderpass.cpp
@@ -297,7 +297,7 @@ void SSAOMapPass::renderPrep(QSSGRenderer &renderer, QSSGLayerRenderData &data)
QSSG_ASSERT_X((rhiDepthTexture && rhiDepthTexture->isValid()), "Preparing AO pass failed, missing equired texture(s)", return);
const auto &shaderCache = renderer.contextInterface()->shaderCache();
- ssaoShaderPipeline = shaderCache->getBuiltInRhiShaders().getRhiSsaoShader();
+ ssaoShaderPipeline = shaderCache->getBuiltInRhiShaders().getRhiSsaoShader(rhiCtx->mainPassViewCount());
aoSettings = { data.layer.aoStrength, data.layer.aoDistance, data.layer.aoSoftness, data.layer.aoBias, data.layer.aoSamplerate, data.layer.aoDither };
ps = data.getPipelineState();
diff --git a/src/runtimerender/res/effectlib/ssao.glsllib b/src/runtimerender/res/effectlib/ssao.glsllib
index 23c4d59a..d393a6b7 100644
--- a/src/runtimerender/res/effectlib/ssao.glsllib
+++ b/src/runtimerender/res/effectlib/ssao.glsllib
@@ -8,7 +8,7 @@
#ifdef QQ3D_SHADER_META
/*{
"uniforms": [
- { "type": "sampler2D", "name": "qt_aoTexture" , "condition": "QSSG_ENABLE_SSAO" }
+ { "type": "sampler2D", "name": "qt_aoTexture" , "condition": "QSSG_ENABLE_SSAO", "multiview_dependent": true }
]
}*/
#endif // QQ3D_SHADER_META
@@ -17,9 +17,15 @@
float qt_screenSpaceAmbientOcclusionFactor()
{
+#if QSHADER_VIEW_COUNT >= 2
+ ivec2 iSize = textureSize(qt_aoTextureArray, 0).xy;
+ vec2 smpUV = (gl_FragCoord.xy) / vec2(iSize);
+ return texture(qt_aoTextureArray, vec3(smpUV, qt_viewIndex)).x;
+#else
ivec2 iSize = textureSize(qt_aoTexture, 0);
vec2 smpUV = (gl_FragCoord.xy) / vec2(iSize);
return texture(qt_aoTexture, smpUV).x;
+#endif
}
#else
diff --git a/src/runtimerender/res/rhishaders/ssao.frag b/src/runtimerender/res/rhishaders/ssao.frag
index d424d6de..af8f39cd 100644
--- a/src/runtimerender/res/rhishaders/ssao.frag
+++ b/src/runtimerender/res/rhishaders/ssao.frag
@@ -2,6 +2,10 @@
layout(location = 0) out vec4 fragOutput;
+#if QSHADER_VIEW_COUNT >= 2
+layout(location = 0) flat in uint v_viewIndex;
+#endif
+
layout(std140, binding = 0) uniform buf {
vec4 aoProperties;
vec4 aoProperties2;
@@ -10,7 +14,11 @@ layout(std140, binding = 0) uniform buf {
vec2 cameraProperties;
} ubuf;
+#if QSHADER_VIEW_COUNT >= 2
+layout(binding = 1) uniform sampler2DArray depthTextureArray;
+#else
layout(binding = 1) uniform sampler2D depthTexture;
+#endif
float calculateVertexDepth( vec2 cameraProperties, vec4 position )
{
@@ -59,9 +67,15 @@ vec3 quatRotate( vec4 q, vec3 v )
return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz );
}
+#if QSHADER_VIEW_COUNT >= 2
+vec3 getViewSpacePos( sampler2DArray depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
+{
+ float sampleDepth = getDepthValue( texture(depthSampler, vec3(UV, v_viewIndex)), camProps );
+#else
vec3 getViewSpacePos( sampler2D depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
{
float sampleDepth = getDepthValue( texture(depthSampler, UV), camProps );
+#endif
sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
vec2 scaledUV = (UV * UvToEye.xy) + UvToEye.zw;
@@ -86,8 +100,13 @@ vec2 offsetDir( vec2 baseDir, int v )
return vec2( dot(baseDir, vX), dot(baseDir, vY) );
}
+#if QSHADER_VIEW_COUNT >= 2
+float calculateAo(int j, vec3 kernel[9], vec4 aoParams, vec4 aoParams2, vec2 camProps, vec2 centerUV, vec4 aoScreen, vec4 UvToEye,
+ vec3 viewPos, vec3 viewNorm, float radStep, sampler2DArray depthSampler)
+#else
float calculateAo(int j, vec3 kernel[9], vec4 aoParams, vec4 aoParams2, vec2 camProps, vec2 centerUV, vec4 aoScreen, vec4 UvToEye,
vec3 viewPos, vec3 viewNorm, float radStep, sampler2D depthSampler)
+#endif
{
float ret = 0.0;
// manually unroll the loop 0..8
@@ -344,7 +363,11 @@ float calculateAo(int j, vec3 kernel[9], vec4 aoParams, vec4 aoParams2, vec2 cam
return ret;
}
+#if QSHADER_VIEW_COUNT >= 2
+float SSambientOcclusion(sampler2DArray depthSampler, vec3 viewNorm, vec4 aoParams, vec4 aoParams2, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+#else
float SSambientOcclusion(sampler2D depthSampler, vec3 viewNorm, vec4 aoParams, vec4 aoParams2, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+#endif
{
vec2 centerUV = gl_FragCoord.xy * aoScreen.zw;
vec3 viewPos = getViewSpacePos( depthSampler, camProps, centerUV, UvToEye );
@@ -399,12 +422,24 @@ float SSambientOcclusion(sampler2D depthSampler, vec3 viewNorm, vec4 aoParams, v
void main()
{
ivec2 iCoords = ivec2(gl_FragCoord.xy);
+#if QSHADER_VIEW_COUNT >= 2
+ float depth = getDepthValue(texelFetch(depthTextureArray, ivec3(iCoords, v_viewIndex), 0), ubuf.cameraProperties);
+#else
float depth = getDepthValue(texelFetch(depthTexture, iCoords, 0), ubuf.cameraProperties);
+#endif
depth = depthValueToLinearDistance( depth, ubuf.cameraProperties );
depth = (depth - ubuf.cameraProperties.x) / (ubuf.cameraProperties.y - ubuf.cameraProperties.x);
+#if QSHADER_VIEW_COUNT >= 2
+ float depth2 = getDepthValue(texelFetch(depthTextureArray, ivec3(iCoords+ivec2(1), v_viewIndex), 0), ubuf.cameraProperties);
+#else
float depth2 = getDepthValue(texelFetch(depthTexture, iCoords+ivec2(1), 0), ubuf.cameraProperties);
+#endif
depth2 = depthValueToLinearDistance( depth, ubuf.cameraProperties );
+#if QSHADER_VIEW_COUNT >= 2
+ float depth3 = getDepthValue(texelFetch(depthTextureArray, ivec3(iCoords-ivec2(1), v_viewIndex), 0), ubuf.cameraProperties);
+#else
float depth3 = getDepthValue(texelFetch(depthTexture, iCoords-ivec2(1), 0), ubuf.cameraProperties);
+#endif
depth3 = depthValueToLinearDistance( depth, ubuf.cameraProperties );
@@ -419,7 +454,12 @@ void main()
screenNorm += normalize(cross(tanU, tanV));
screenNorm = -normalize(screenNorm);
- float aoFactor = SSambientOcclusion( depthTexture, screenNorm, ubuf.aoProperties, ubuf.aoProperties2,
+#if QSHADER_VIEW_COUNT >= 2
+ float aoFactor = SSambientOcclusion( depthTextureArray,
+#else
+ float aoFactor = SSambientOcclusion( depthTexture,
+#endif
+ screenNorm, ubuf.aoProperties, ubuf.aoProperties2,
ubuf.cameraProperties, ubuf.aoScreenConst, ubuf.uvToEyeConst );
fragOutput = vec4(aoFactor, aoFactor, aoFactor, 1.0);
diff --git a/src/runtimerender/res/rhishaders/ssao.vert b/src/runtimerender/res/rhishaders/ssao.vert
index de1f1077..8ef17eb3 100644
--- a/src/runtimerender/res/rhishaders/ssao.vert
+++ b/src/runtimerender/res/rhishaders/ssao.vert
@@ -5,6 +5,10 @@
layout(location = 0) in vec3 attr_pos;
+#if QSHADER_VIEW_COUNT >= 2
+layout(location = 0) flat out uint v_viewIndex;
+#endif
+
layout(std140, binding = 0) uniform buf {
vec4 aoProperties;
vec4 aoProperties2;
@@ -13,9 +17,10 @@ layout(std140, binding = 0) uniform buf {
vec2 cameraProperties;
} ubuf;
-out gl_PerVertex { vec4 gl_Position; };
-
void main()
{
+#if QSHADER_VIEW_COUNT >= 2
+ v_viewIndex = gl_ViewIndex;
+#endif
gl_Position = vec4(attr_pos.xy, 0.5, 1.0 );
}
diff --git a/src/runtimerender/resourcemanager/qssgrendershaderlibrarymanager_p.h b/src/runtimerender/resourcemanager/qssgrendershaderlibrarymanager_p.h
index e32faccd..1a4938b6 100644
--- a/src/runtimerender/resourcemanager/qssgrendershaderlibrarymanager_p.h
+++ b/src/runtimerender/resourcemanager/qssgrendershaderlibrarymanager_p.h
@@ -51,7 +51,8 @@ struct QSSGCustomShaderMetaData
UsesViewIndex = 1 << 13,
UsesDepthTextureArray = 1 << 14,
UsesScreenTextureArray = 1 << 15,
- UsesScreenMipTextureArray = 1 << 16
+ UsesScreenMipTextureArray = 1 << 16,
+ UsesAoTextureArray = 1 << 17
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/tests/manual/qmlxr/testscenes/models/object1.mesh b/tests/manual/qmlxr/testscenes/models/object1.mesh
new file mode 100644
index 00000000..860136b1
--- /dev/null
+++ b/tests/manual/qmlxr/testscenes/models/object1.mesh
Binary files differ
diff --git a/tests/manual/qmlxr/testscenes/ssao.qml b/tests/manual/qmlxr/testscenes/ssao.qml
new file mode 100644
index 00000000..7c705f7c
--- /dev/null
+++ b/tests/manual/qmlxr/testscenes/ssao.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick3D
+
+Node {
+ property vector3d qmlxr_originPosition: Qt.vector3d(0, 200, 300)
+ property vector3d qmlxr_originRotation: Qt.vector3d(-30, 0, 0)
+ property SceneEnvironment qmlxr_environment: SceneEnvironment {
+ aoStrength: 75
+ aoBias: 0.5
+ aoSampleRate: 2
+ NumberAnimation on aoDistance { from: 10; to: 100; duration: 2000; loops: -1 }
+ aoSoftness: 15
+ aoDither: true
+ }
+
+ DirectionalLight {
+ }
+
+ Model {
+ source: "models/object1.mesh"
+ scale: Qt.vector3d(80, 80, 80)
+ materials: PrincipledMaterial { baseColor: "white" }
+ eulerRotation: Qt.vector3d(0, 120, 340)
+ }
+}