From 9d0ad3586dbe2b3aa79d1d30b96e7b4159fff46a Mon Sep 17 00:00:00 2001 From: Ben Doherty Date: Fri, 6 Sep 2019 15:04:52 -0700 Subject: [PATCH] Update tonemapping to use new post-process material domain (#1428) --- filament/CMakeLists.txt | 1 + filament/src/PostProcessManager.cpp | 40 ++++++++++-------- filament/src/PostProcessManager.h | 1 + filament/src/materials/tonemapping.mat | 57 ++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 filament/src/materials/tonemapping.mat diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index 58247cc190..f8fc7ba185 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -142,6 +142,7 @@ set(MATERIAL_SRCS src/materials/skybox.mat src/materials/sao.mat src/materials/ssao.mat + src/materials/tonemapping.mat ) # Embed the binary resource blob for materials. diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index cebbb7fdee..5a90bffefd 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -46,6 +46,8 @@ PostProcessManager::PostProcessMaterial::PostProcessMaterial(FEngine& engine, uint8_t const* data, size_t size) noexcept { mMaterial = upcast(Material::Builder().package(data, size).build(engine)); mMaterialInstance = mMaterial->getDefaultInstance(); + // TODO: After all materials using this class have been converted to the post-process material + // domain, load both OPAQUE and TRANSPARENt variants here. mProgram = mMaterial->getProgram(0); } @@ -89,6 +91,7 @@ void PostProcessManager::init() noexcept { mSSAO = PostProcessMaterial(mEngine, MATERIALS_SAO_DATA, MATERIALS_SAO_SIZE); mMipmapDepth = PostProcessMaterial(mEngine, MATERIALS_MIPMAPDEPTH_DATA, MATERIALS_MIPMAPDEPTH_SIZE); mBlur = PostProcessMaterial(mEngine, MATERIALS_BLUR_DATA, MATERIALS_BLUR_SIZE); + mTonemapping = PostProcessMaterial(mEngine, MATERIALS_TONEMAPPING_DATA, MATERIALS_TONEMAPPING_SIZE); // create sampler for post-process FBO DriverApi& driver = mEngine.getDriverApi(); @@ -159,9 +162,6 @@ FrameGraphId PostProcessManager::toneMapping(FrameGraph& fg, FrameGraphId output; FrameGraphRenderTargetHandle rt; }; - backend::Handle toneMappingProgram = engine.getPostProcessProgram( - translucent ? PostProcessStage::TONE_MAPPING_TRANSLUCENT - : PostProcessStage::TONE_MAPPING_OPAQUE); auto& ppToneMapping = fg.addPass("tonemapping", [&](FrameGraph::Builder& builder, PostProcessToneMapping& data) { @@ -174,24 +174,28 @@ FrameGraphId PostProcessManager::toneMapping(FrameGraph& fg, }); data.rt = builder.createRenderTarget(data.output); }, - [=](FrameGraphPassResources const& resources, + [=, engine = &engine](FrameGraphPassResources const& resources, PostProcessToneMapping const& data, DriverApi& driver) { - PipelineState pipeline; - pipeline.rasterState.culling = RasterState::CullingMode::NONE; - pipeline.rasterState.colorWrite = true; - pipeline.rasterState.depthFunc = RasterState::DepthFunc::A; - pipeline.program = toneMappingProgram; - - auto const& textureDesc = resources.getDescriptor(data.input); auto const& color = resources.getTexture(data.input); - // TODO: the first parameters below are the *actual viewport* size - // (as opposed to the size of the source texture). Currently we don't allow - // the texture to be resized, so they match. We'll need something more - // sophisticated in the future. - mPostProcessUb.setUniform(offsetof(PostProcessingUib, dithering), dithering); - setSource(textureDesc.width, textureDesc.height, - color, {}, textureDesc.width, textureDesc.height); + FMaterialInstance* pInstance = mTonemapping.getMaterialInstance(); + pInstance->setParameter("dithering", dithering); + SamplerParams params; + pInstance->setParameter("colorBuffer", color, params); + + auto duration = engine->getEngineTime(); + float fraction = (duration.count() % 1000000000) / 1000000000.0f; + mPostProcessUb.setUniform(offsetof(PostProcessingUib, time), fraction); + + pInstance->commit(driver); + pInstance->use(driver); + + PipelineState pipeline; + pipeline.rasterState = mTonemapping.getMaterial()->getRasterState(); + const uint8_t variant = static_cast ( + translucent ? + PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE ); + pipeline.program = mTonemapping.getMaterial()->getProgram(variant); auto const& target = resources.getRenderTarget(data.rt); driver.beginRenderPass(target.target, target.params); diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 65a194e5bc..5c1046040e 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -118,6 +118,7 @@ private: PostProcessMaterial mSSAO; PostProcessMaterial mMipmapDepth; PostProcessMaterial mBlur; + PostProcessMaterial mTonemapping; backend::Handle mNoSSAOTexture; }; diff --git a/filament/src/materials/tonemapping.mat b/filament/src/materials/tonemapping.mat new file mode 100644 index 0000000000..04b371ef00 --- /dev/null +++ b/filament/src/materials/tonemapping.mat @@ -0,0 +1,57 @@ +material { + name : tonemap, + parameters : [ + { + type : sampler2d, + name : colorBuffer, + precision: high + }, + { + type : int, + name : dithering + } + ], + depthWrite : false, + depthCulling : false, + culling: none, + domain: postprocess +} + +fragment { + +#include "../../../shaders/src/tone_mapping.fs" +#include "../../../shaders/src/conversion_functions.fs" +#include "../../../shaders/src/dithering.fs" + + vec3 resolveFragment(const ivec2 uv) { + return texelFetch(materialParams_colorBuffer, uv, 0).rgb; + } + + vec4 resolveAlphaFragment(const ivec2 uv) { + return texelFetch(materialParams_colorBuffer, uv, 0); + } + + vec4 resolve() { +#if POST_PROCESS_OPAQUE + vec4 color = vec4(resolveFragment(ivec2(getUV())), 1.0); + color.rgb = tonemap(color.rgb); + color.rgb = OECF(color.rgb); + color.a = luminance(color.rgb); +#else + vec4 color = resolveAlphaFragment(ivec2(getUV())); + color.rgb /= color.a + FLT_EPS; + color.rgb = tonemap(color.rgb); + color.rgb = OECF(color.rgb); + color.rgb *= color.a + FLT_EPS; +#endif + return color; + } + + void postProcess(inout PostProcessInputs postProcess) { + postProcess.color = resolve(); + if (materialParams.dithering > 0) { + postProcess.color = dither(postProcess.color); + } + } + +}