diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 1855eec649..698c139332 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -215,6 +215,7 @@ set(MATERIAL_SRCS src/materials/antiAliasing/fxaa.mat src/materials/antiAliasing/taa.mat src/materials/blitLow.mat + src/materials/blitArray.mat src/materials/bloom/bloomDownsample.mat src/materials/bloom/bloomDownsample2x.mat src/materials/bloom/bloomDownsample9.mat diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index eb4fcf55f8..3a1b2b18a3 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -262,6 +262,7 @@ static const PostProcessManager::MaterialInfo sMaterialListFeatureLevel0[] = { static const PostProcessManager::MaterialInfo sMaterialList[] = { { "bilateralBlur", MATERIAL(BILATERALBLUR) }, { "bilateralBlurBentNormals", MATERIAL(BILATERALBLURBENTNORMALS) }, + { "blitArray", MATERIAL(BLITARRAY) }, { "bloomDownsample", MATERIAL(BLOOMDOWNSAMPLE) }, { "bloomDownsample2x", MATERIAL(BLOOMDOWNSAMPLE2X) }, { "bloomDownsample9", MATERIAL(BLOOMDOWNSAMPLE9) }, @@ -3283,6 +3284,84 @@ FrameGraphId PostProcessManager::debugShadowCascades(FrameGra return debugShadowCascadePass->output; } +FrameGraphId PostProcessManager::debugCombineArrayTexture(FrameGraph& fg, + bool translucent, FrameGraphId input, + filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, + SamplerMagFilter filterMag, + SamplerMinFilter filterMin) noexcept { + + assert_invariant(fg.getDescriptor(input).depth > 1); + assert_invariant(fg.getDescriptor(input).type == SamplerType::SAMPLER_2D_ARRAY); + + // TODO: add support for sub-resources + assert_invariant(fg.getSubResourceDescriptor(input).layer == 0); + assert_invariant(fg.getSubResourceDescriptor(input).level == 0); + + struct QuadBlitData { + FrameGraphId input; + FrameGraphId output; + }; + + auto& ppQuadBlit = fg.addPass("combining array tex", + [&](FrameGraph::Builder& builder, auto& data) { + data.input = builder.sample(input); + data.output = builder.createTexture("upscaled output", outDesc); + data.output = builder.write(data.output, + FrameGraphTexture::Usage::COLOR_ATTACHMENT); + builder.declareRenderPass(builder.getName(data.output), { + .attachments = {.color = { data.output }}, + .clearFlags = TargetBufferFlags::DEPTH }); + }, + [=](FrameGraphResources const& resources, + auto const& data, DriverApi& driver) { + auto color = resources.getTexture(data.input); + auto const& inputDesc = resources.getDescriptor(data.input); + auto out = resources.getRenderPassInfo(); + + // -------------------------------------------------------------------------------- + // set uniforms + + PostProcessMaterial const& material = getPostProcessMaterial("blitArray"); + auto* mi = material.getMaterialInstance(mEngine); + mi->setParameter("color", color, { + .filterMag = filterMag, + .filterMin = filterMin + }); + mi->setParameter("layerIndex", 0); + mi->setParameter("viewport", float4{ + float(vp.left) / inputDesc.width, + float(vp.bottom) / inputDesc.height, + float(vp.width) / inputDesc.width, + float(vp.height) / inputDesc.height + }); + mi->commit(driver); + mi->use(driver); + + auto pipeline = material.getPipelineState(mEngine); + if (translucent) { + pipeline.first.rasterState.blendFunctionSrcRGB = BlendFunction::ONE; + pipeline.first.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE; + pipeline.first.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA; + pipeline.first.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA; + } + + // Blit the scene rendered to the first layer to the left half of the screen. + out.params.viewport.width /= 2; + render(out, pipeline, driver); + + // Blit the scene rendered to the second layer to the right half of the screen. + // Don't clear or discard the target to keep the previously rendered left half image. + mi->setParameter("layerIndex", 1); + mi->commit(driver); + out.params.flags.clear = filament::backend::TargetBufferFlags::NONE; + out.params.flags.discardStart = filament::backend::TargetBufferFlags::NONE; + out.params.viewport.left += out.params.viewport.width; + render(out, pipeline, driver); + }); + + return ppQuadBlit->output; +} + FrameGraphId PostProcessManager::debugDisplayShadowTexture( FrameGraph& fg, FrameGraphId input, diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index badf5b9a8c..432a9e3fff 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -288,6 +288,15 @@ public: FrameGraphId shadowmap, float scale, uint8_t layer, uint8_t level, uint8_t channel, float power) noexcept; + // Combine an array texture pointed to by `input` into a single image, then return it. + // This is only useful to check the multiview rendered scene as a debugging purpose, thus this + // is not expected to be used in normal cases. + FrameGraphId debugCombineArrayTexture(FrameGraph& fg, bool translucent, + FrameGraphId input, + filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, + backend::SamplerMagFilter filterMag, + backend::SamplerMinFilter filterMin) noexcept; + backend::Handle getOneTexture() const; backend::Handle getZeroTexture() const; backend::Handle getOneTextureArray() const; diff --git a/filament/src/materials/blitArray.mat b/filament/src/materials/blitArray.mat new file mode 100644 index 0000000000..2d7cfc4da3 --- /dev/null +++ b/filament/src/materials/blitArray.mat @@ -0,0 +1,38 @@ +material { + name : blitArray, + parameters : [ + { + type : sampler2dArray, + name : color, + precision: medium + }, + { + type : int, + name : layerIndex + }, + { + type : float4, + name : viewport, + precision: high + } + ], + variables : [ + vertex + ], + depthWrite : false, + depthCulling : false, + domain: postprocess +} + +vertex { + void postProcessVertex(inout PostProcessVertexInputs postProcess) { + postProcess.vertex.xy = materialParams.viewport.xy + postProcess.normalizedUV * materialParams.viewport.zw; + postProcess.vertex.xy = uvToRenderTargetUV(postProcess.vertex.xy); + } +} + +fragment { + void postProcess(inout PostProcessInputs postProcess) { + postProcess.color = textureLod(materialParams_color, vec3(variable_vertex.xy, materialParams.layerIndex), 0.0); + } +}