diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2024-04-30 14:16:46 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2024-05-06 15:51:04 +0200 |
commit | a22a94a3363ce1907fb39c4bd1990b8542da7f61 (patch) | |
tree | fee7bb96423e42802051bb345d77724f7e01e434 | |
parent | b26d2cec2293e6b3efce6b695a58c11df1c78dae (diff) |
Make SSAO multiview-aware
Change-Id: I12ab28dae42de99043415941b463a24c371eae14
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | src/quick3d/qquick3dcustommaterial.cpp | 18 | ||||
-rw-r--r-- | src/runtimerender/graphobjects/qssgrendercustommaterial_p.h | 3 | ||||
-rw-r--r-- | src/runtimerender/qssgrhicontext_p.h | 1 | ||||
-rw-r--r-- | src/runtimerender/qssgrhicustommaterialsystem.cpp | 21 | ||||
-rw-r--r-- | src/runtimerender/qssgshadermaterialadapter.cpp | 7 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrendererimplshaders_p.h | 2 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp | 4 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrenderhelpers.cpp | 32 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrenderpass.cpp | 2 | ||||
-rw-r--r-- | src/runtimerender/res/effectlib/ssao.glsllib | 8 | ||||
-rw-r--r-- | src/runtimerender/res/rhishaders/ssao.frag | 42 | ||||
-rw-r--r-- | src/runtimerender/res/rhishaders/ssao.vert | 9 | ||||
-rw-r--r-- | src/runtimerender/resourcemanager/qssgrendershaderlibrarymanager_p.h | 3 | ||||
-rw-r--r-- | tests/manual/qmlxr/testscenes/models/object1.mesh | bin | 0 -> 184460 bytes | |||
-rw-r--r-- | tests/manual/qmlxr/testscenes/ssao.qml | 28 |
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 Binary files differnew file mode 100644 index 00000000..860136b1 --- /dev/null +++ b/tests/manual/qmlxr/testscenes/models/object1.mesh 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) + } +} |