Skip to content

Commit

Permalink
Add a better motion blur
Browse files Browse the repository at this point in the history
  • Loading branch information
godlikepanos committed Sep 22, 2024
1 parent 95d96da commit 21d6557
Show file tree
Hide file tree
Showing 80 changed files with 543 additions and 103 deletions.
8 changes: 4 additions & 4 deletions AnKi/Core/CoreTracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ CoreTracer::~CoreTracer()
Error CoreTracer::init(CString directory)
{
Tracer::allocateSingleton();
if(Tracer::getSingleton().getEnabled() != g_tracingEnabledCVar.get())
if(Tracer::getSingleton().getEnabled() != g_tracingEnabledCVar)
{
// Change the value inside the if because setEnabled prints a message
Tracer::getSingleton().setEnabled(g_tracingEnabledCVar.get());
Tracer::getSingleton().setEnabled(g_tracingEnabledCVar);
}
# if ANKI_OS_ANDROID
if(Tracer::getSingleton().getStreamlineEnabled())
Expand Down Expand Up @@ -329,9 +329,9 @@ void CoreTracer::flushFrame(U64 frame)
},
&ctx);

if(Tracer::getSingleton().getEnabled() != g_tracingEnabledCVar.get())
if(Tracer::getSingleton().getEnabled() != g_tracingEnabledCVar)
{
Tracer::getSingleton().setEnabled(g_tracingEnabledCVar.get());
Tracer::getSingleton().setEnabled(g_tracingEnabledCVar);
}

# if ANKI_OS_ANDROID
Expand Down
3 changes: 1 addition & 2 deletions AnKi/Importer/GltfImporterAnimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,8 @@ Error GltfImporter::writeAnimation(const cgltf_animation& anim)
continue;
}

// Only animate cameras for now
const cgltf_node& node = *channel.m_targetNode;
if(node.camera == nullptr || node.name == nullptr)
if(node.name == nullptr)
{
continue;
}
Expand Down
21 changes: 9 additions & 12 deletions AnKi/Renderer/FinalComposite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <AnKi/Renderer/GBuffer.h>
#include <AnKi/Renderer/Dbg.h>
#include <AnKi/Renderer/UiStage.h>
#include <AnKi/Renderer/MotionVectors.h>
#include <AnKi/Renderer/MotionBlur.h>
#include <AnKi/Util/Logger.h>
#include <AnKi/Util/Tracer.h>
#include <AnKi/Util/CVarSet.h>
Expand Down Expand Up @@ -95,10 +95,9 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
pass.newTextureDependency(getRenderer().getDbg().getRt(), TextureUsageBit::kSrvPixel);
}

pass.newTextureDependency(getRenderer().getScale().getTonemappedRt(), TextureUsageBit::kSrvPixel);
pass.newTextureDependency((g_motionBlurSampleCountCVar != 0) ? getRenderer().getMotionBlur().getRt() : getRenderer().getScale().getTonemappedRt(),
TextureUsageBit::kSrvPixel);
pass.newTextureDependency(getRenderer().getBloom().getBloomRt(), TextureUsageBit::kSrvPixel);
pass.newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), TextureUsageBit::kSrvPixel);
pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel);

Array<RenderTargetHandle, kMaxDebugRenderTargets> dbgRts;
ShaderProgramPtr debugProgram;
Expand Down Expand Up @@ -141,23 +140,21 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
// Bind stuff
if(!hasDebugRt)
{
cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
cmdb.bindSampler(2, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearRepeat.get());

rgraphCtx.bindSrv(0, 0, getRenderer().getScale().getTonemappedRt());
rgraphCtx.bindSrv(
0, 0, (g_motionBlurSampleCountCVar != 0) ? getRenderer().getMotionBlur().getRt() : getRenderer().getScale().getTonemappedRt());

rgraphCtx.bindSrv(1, 0, getRenderer().getBloom().getBloomRt());
cmdb.bindSrv(2, 0, TextureView(&m_lut->getTexture(), TextureSubresourceDesc::all()));
rgraphCtx.bindSrv(3, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getDepthRt());

if(dbgEnabled)
{
rgraphCtx.bindSrv(5, 0, getRenderer().getDbg().getRt());
rgraphCtx.bindSrv(3, 0, getRenderer().getDbg().getRt());
}

const UVec4 pc(g_motionBlurSamplesCVar, floatBitsToUint(g_filmGrainStrengthCVar), getRenderer().getFrameCount() & kMaxU32, 0);
const UVec4 pc(floatBitsToUint(g_filmGrainStrengthCVar), getRenderer().getFrameCount() & kMaxU32, 0, 0);
cmdb.setFastConstants(&pc, sizeof(pc));
}
else
Expand Down
1 change: 0 additions & 1 deletion AnKi/Renderer/FinalComposite.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace anki {
/// @addtogroup renderer
/// @{

inline NumericCVar<U32> g_motionBlurSamplesCVar("R", "MotionBlurSamples", 32, 0, 2048, "Max motion blur samples");
inline NumericCVar<F32> g_filmGrainStrengthCVar("R", "FilmGrainStrength", 16.0f, 0.0f, 250.0f, "Film grain strength");

/// Post-processing stage.
Expand Down
165 changes: 165 additions & 0 deletions AnKi/Renderer/MotionBlur.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
// All rights reserved.
// Code licensed under the BSD License.
// http://www.anki3d.org/LICENSE

#include <AnKi/Renderer/MotionBlur.h>
#include <AnKi/Renderer/Renderer.h>
#include <AnKi/Renderer/MotionVectors.h>
#include <AnKi/Renderer/TemporalAA.h>
#include <AnKi/Renderer/GBuffer.h>
#include <AnKi/Util/Tracer.h>

namespace anki {

Error MotionBlur::init()
{
ANKI_CHECK(loadShaderProgram("ShaderBinaries/MotionBlur.ankiprogbin",
{{"TILE_SIZE", MutatorValue(g_motionBlurTileSizeCVar)}, {"SAMPLE_COUNT", MutatorValue(g_motionBlurSampleCountCVar)}},
m_prog, m_maxVelocityGrProg, "MaxTileVelocity"));
ANKI_CHECK(loadShaderProgram("ShaderBinaries/MotionBlur.ankiprogbin",
{{"TILE_SIZE", MutatorValue(g_motionBlurTileSizeCVar)}, {"SAMPLE_COUNT", MutatorValue(g_motionBlurSampleCountCVar)}},
m_prog, m_maxNeightbourVelocityGrProg, "MaxNeighbourTileVelocity"));
ANKI_CHECK(loadShaderProgram("ShaderBinaries/MotionBlur.ankiprogbin",
{{"TILE_SIZE", MutatorValue(g_motionBlurTileSizeCVar)}, {"SAMPLE_COUNT", MutatorValue(g_motionBlurSampleCountCVar)}},
m_prog, m_reconstructGrProg, "Reconstruct"));

const UVec2 tiledTexSize = (getRenderer().getPostProcessResolution() + g_motionBlurTileSizeCVar - 1) / g_motionBlurTileSizeCVar;
m_maxVelocityRtDesc =
getRenderer().create2DRenderTargetDescription(tiledTexSize.x(), tiledTexSize.y(), Format::kR16G16_Sfloat, "MaxTileVelocity");
m_maxVelocityRtDesc.bake();

m_maxNeighbourVelocityRtDesc =
getRenderer().create2DRenderTargetDescription(tiledTexSize.x(), tiledTexSize.y(), Format::kR16G16_Sfloat, "MaxNeighbourTileVelocity");
m_maxNeighbourVelocityRtDesc.bake();

m_finalRtDesc = getRenderer().create2DRenderTargetDescription(
getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y(),
(GrManager::getSingleton().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::kR8G8B8_Unorm : Format::kR8G8B8A8_Unorm,
"MotionBlur");
m_finalRtDesc.bake();

return Error::kNone;
}

void MotionBlur::populateRenderGraph(RenderingContext& ctx)
{
ANKI_TRACE_SCOPED_EVENT(MotionBlur);
if(g_motionBlurSampleCountCVar == 0)
{
m_runCtx.m_rt = {};
return;
}

RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;

// MaxTileVelocity
const RenderTargetHandle maxVelRt = rgraph.newRenderTarget(m_maxVelocityRtDesc);
{
NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("Motion blur min velocity");

pass.newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), TextureUsageBit::kSrvCompute);
pass.newTextureDependency(maxVelRt, TextureUsageBit::kUavCompute);

pass.setWork([this, maxVelRt](RenderPassWorkContext& rgraphCtx) {
CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;

cmdb.bindShaderProgram(m_maxVelocityGrProg.get());

rgraphCtx.bindSrv(0, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
rgraphCtx.bindUav(0, 0, maxVelRt);

const UVec2 tiledTexSize = (getRenderer().getPostProcessResolution() + g_motionBlurTileSizeCVar - 1) / g_motionBlurTileSizeCVar;
cmdb.dispatchCompute(tiledTexSize.x(), tiledTexSize.y(), 1);
});
}

// MaxNeighbourTileVelocity
const RenderTargetHandle maxNeighbourVelRt = rgraph.newRenderTarget(m_maxNeighbourVelocityRtDesc);
{
NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("Motion blur min neighbour vel");

pass.newTextureDependency(maxVelRt, TextureUsageBit::kSrvCompute);
pass.newTextureDependency(maxNeighbourVelRt, TextureUsageBit::kUavCompute);

pass.setWork([this, maxVelRt, maxNeighbourVelRt](RenderPassWorkContext& rgraphCtx) {
CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;

cmdb.bindShaderProgram(m_maxNeightbourVelocityGrProg.get());

rgraphCtx.bindSrv(0, 0, maxVelRt);
rgraphCtx.bindUav(0, 0, maxNeighbourVelRt);

const UVec2 tiledTexSize = (getRenderer().getPostProcessResolution() + g_motionBlurTileSizeCVar - 1) / g_motionBlurTileSizeCVar;
cmdb.dispatchCompute(tiledTexSize.x(), tiledTexSize.y(), 1);
});
}

// Recustruct
{
m_runCtx.m_rt = rgraph.newRenderTarget(m_finalRtDesc);

TextureUsageBit readUsage, writeUsage;
RenderPassBase* ppass;
if(g_preferComputeCVar)
{
NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("Motion blur reconstruct");
ppass = &pass;
readUsage = TextureUsageBit::kSrvCompute;
writeUsage = TextureUsageBit::kUavCompute;
}
else
{
GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass("Motion blur reconstruct");
pass.setRenderpassInfo({m_runCtx.m_rt});
ppass = &pass;
readUsage = TextureUsageBit::kSrvPixel;
writeUsage = TextureUsageBit::kRtvDsvWrite;
}

ppass->newTextureDependency(getRenderer().getTemporalAA().getTonemappedRt(), readUsage);
ppass->newTextureDependency(getRenderer().getGBuffer().getDepthRt(), readUsage);
ppass->newTextureDependency(maxNeighbourVelRt, readUsage);
ppass->newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), readUsage);
ppass->newTextureDependency(m_runCtx.m_rt, writeUsage);

ppass->setWork([this, maxNeighbourVelRt, &ctx](RenderPassWorkContext& rgraphCtx) {
CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;

cmdb.bindShaderProgram(m_reconstructGrProg.get());

rgraphCtx.bindSrv(0, 0, getRenderer().getTemporalAA().getTonemappedRt());
rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getDepthRt());
rgraphCtx.bindSrv(2, 0, maxNeighbourVelRt);
rgraphCtx.bindSrv(3, 0, getRenderer().getMotionVectors().getMotionVectorsRt());

cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());

class Constants
{
public:
Vec2 m_depthLinearizationParams;
U32 m_frame;
F32 m_far;
} consts;
consts.m_depthLinearizationParams.x() = (ctx.m_cameraNear - ctx.m_cameraFar) / ctx.m_cameraNear;
consts.m_depthLinearizationParams.y() = ctx.m_cameraFar / ctx.m_cameraNear;
consts.m_frame = getRenderer().getFrameCount() % 32;
consts.m_far = ctx.m_cameraFar;
cmdb.setFastConstants(&consts, sizeof(consts));

if(g_preferComputeCVar)
{
rgraphCtx.bindUav(0, 0, m_runCtx.m_rt);
dispatchPPCompute(cmdb, 8, 8, getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y());
}
else
{
cmdb.setViewport(0, 0, getRenderer().getPostProcessResolution().x(), getRenderer().getPostProcessResolution().y());
drawQuad(cmdb);
}
});
}
}

} // end namespace anki
61 changes: 61 additions & 0 deletions AnKi/Renderer/MotionBlur.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
// All rights reserved.
// Code licensed under the BSD License.
// http://www.anki3d.org/LICENSE

#pragma once

#include <AnKi/Renderer/RendererObject.h>

namespace anki {

/// @addtogroup renderer
/// @{

inline NumericCVar<U32> g_motionBlurTileSizeCVar("R", "MotionBlurTileSize", 32, 8, 64, "Motion blur tile size");
inline NumericCVar<U32> g_motionBlurSampleCountCVar("R", "MotionBlurSampleCount", 16, 0, 64, "Motion blur sample count");

/// Motion blur.
class MotionBlur : public RendererObject
{
public:
MotionBlur()
{
registerDebugRenderTarget("MotionBlur");
}

Error init();

void populateRenderGraph(RenderingContext& ctx);

void getDebugRenderTarget([[maybe_unused]] CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
[[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const override
{
ANKI_ASSERT(rtName == "MotionBlur");
handles[0] = m_runCtx.m_rt;
}

RenderTargetHandle getRt() const
{
return m_runCtx.m_rt;
}

private:
ShaderProgramResourcePtr m_prog;
ShaderProgramPtr m_maxVelocityGrProg;
ShaderProgramPtr m_maxNeightbourVelocityGrProg;
ShaderProgramPtr m_reconstructGrProg;

RenderTargetDesc m_maxVelocityRtDesc;
RenderTargetDesc m_maxNeighbourVelocityRtDesc;
RenderTargetDesc m_finalRtDesc;

class
{
public:
RenderTargetHandle m_rt;
} m_runCtx;
};
/// @}

} // end namespace anki
2 changes: 2 additions & 0 deletions AnKi/Renderer/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <AnKi/Renderer/Ssao.h>
#include <AnKi/Renderer/Ssr.h>
#include <AnKi/Renderer/Sky.h>
#include <AnKi/Renderer/MotionBlur.h>
#include <AnKi/Renderer/Utils/Drawer.h>
#include <AnKi/Renderer/Utils/GpuVisibility.h>
#include <AnKi/Renderer/Utils/MipmapGenerator.h>
Expand Down Expand Up @@ -294,6 +295,7 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
}
m_vrsSriGeneration->populateRenderGraph(ctx);
m_scale->populateRenderGraph(ctx);
m_motionBlur->populateRenderGraph(ctx);
m_bloom2->populateRenderGraph(ctx);
m_tonemapping->populateRenderGraph(ctx);
m_dbg->populateRenderGraph(ctx);
Expand Down
1 change: 1 addition & 0 deletions AnKi/Renderer/RendererObject.def.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ANKI_RENDERER_OBJECT_DEF(ClusterBinning, clusterBinning2, 1)
ANKI_RENDERER_OBJECT_DEF(Ssao, ssao, 1)
ANKI_RENDERER_OBJECT_DEF(Ssr, ssr, 1)
ANKI_RENDERER_OBJECT_DEF(Sky, sky, 1)
ANKI_RENDERER_OBJECT_DEF(MotionBlur, motionBlur, 1)

// Util objects
ANKI_RENDERER_OBJECT_DEF(RenderableDrawer, drawer, 1)
Expand Down
3 changes: 1 addition & 2 deletions AnKi/Resource/AnimationResource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Error AnimationResource::load(const ResourceFilename& filename, [[maybe_unused]]
}

// <scalingKeys>
ANKI_CHECK(chEl.getChildElementOptional("scalingKeys", keysEl));
ANKI_CHECK(chEl.getChildElementOptional("scaleKeys", keysEl));
if(keysEl)
{
ANKI_CHECK(keysEl.getChildElement("key", keyEl));
Expand All @@ -147,7 +147,6 @@ Error AnimationResource::load(const ResourceFilename& filename, [[maybe_unused]]
maxTime = std::max(maxTime, key.m_time);

// value
ANKI_CHECK(keyEl.getChildElement("value", el));
ANKI_CHECK(keyEl.getNumber(key.m_value));

// Check ident
Expand Down
Loading

0 comments on commit 21d6557

Please sign in to comment.