56 geomModule._defines.emplace_back(
"verticalBlur uint(PushData0[1].x)" );
57 geomModule._defines.emplace_back(
"layerCount int(PushData0[1].y)" );
58 geomModule._defines.emplace_back(
"layerOffsetRead int(PushData0[1].z)" );
59 geomModule._defines.emplace_back(
"layerOffsetWrite int(PushData0[1].w)" );
61 fragModule._defines.emplace_back(
"LAYERED" );
62 fragModule._defines.emplace_back(
"layer uint(PushData0[0].x)" );
63 fragModule._defines.emplace_back(
"size PushData0[0].yz" );
64 fragModule._defines.emplace_back(
"kernelSize int(PushData0[0].w)" );
65 fragModule._defines.emplace_back(
"verticalBlur uint(PushData0[1].x)" );
68 shaderDescriptor.
_modules.push_back( vertModule );
69 shaderDescriptor.
_modules.push_back( geomModule );
70 shaderDescriptor.
_modules.push_back( fragModule );
75 blurDepthMapShader.waitForReady(
true );
84 shaderDescriptor.
_globalDefines[0]._define =
"GS_MAX_INVOCATIONS 1u";
87 blurDepthMapShader.waitForReady(
true );
102 std::array<vec2<F32>*, 12> blurSizeConstants = {
118 for (
size_t i = 1u; i < blurSizeConstants.size(); ++i )
120 blurSizeConstants[i]->set((*blurSizeConstants[i - 1]) * 0.5f);
128 sampler._anisotropyLevel = 0u;
136 colourDescriptor._dataType = texDescriptor._dataType;
137 colourDescriptor._baseFormat = texDescriptor._baseFormat;
157 desc.
_name =
"CSM_ShadowMap_Draw";
167 blurMapDescriptor._dataType = texDescriptor._dataType;
168 blurMapDescriptor._baseFormat = texDescriptor._baseFormat;
169 blurMapDescriptor._packing = texDescriptor._packing;
179 desc.
_name =
"CSM_Blur";
203 constexpr F32 minDistance = 0.0f;
204 constexpr F32 maxDistance = 1.0f;
208 const U8 numSplits = light.csmSplitCount();
209 const F32 nearClip = nearFarPlanes.min;
210 const F32 farClip = nearFarPlanes.max;
211 const F32 clipRange = farClip - nearClip;
213 DIVIDE_ASSERT( clipRange > 0.f,
"CascadedShadowMapsGenerator::calculateSplitDepths error: invalid clip range specified!" );
215 const F32 minZ = nearClip + minDistance * clipRange;
216 const F32 maxZ = nearClip + maxDistance * clipRange;
218 const F32 range = maxZ - minZ;
219 const F32 ratio = maxZ / minZ;
222 for ( ; i < numSplits; ++i )
224 const F32 p =
to_F32( i + 1 ) / numSplits;
225 const F32 log = minZ * std::pow( ratio, p );
226 const F32 uniform = minZ + range * p;
228 depths[i] = (d - nearClip) / clipRange;
229 light.setShadowFloatValue( i, d );
235 light.setShadowFloatValue( i, -depths[i] );
249 F32 appliedDiff = 0.0f;
250 for (
U8 cascadeIterator = 0; cascadeIterator < numSplits; ++cascadeIterator )
254 const F32 prevSplitDistance = cascadeIterator == 0 ? 0.0f : splitDepths[cascadeIterator - 1];
255 const F32 splitDistance = splitDepths[cascadeIterator];
259 {-1.0f, 1.0f, -1.0f},
260 { 1.0f, 1.0f, -1.0f},
261 { 1.0f, -1.0f, -1.0f},
262 {-1.0f, -1.0f, -1.0f},
265 { 1.0f, -1.0f, 1.0f},
266 {-1.0f, -1.0f, 1.0f},
269 for (
vec3<F32>& corner : frustumCornersWS )
272 corner.set( inversePoint / inversePoint.
w );
275 for (
U8 i = 0; i < 4; ++i )
277 const vec3<F32> cornerRay = frustumCornersWS[i + 4] - frustumCornersWS[i];
278 const vec3<F32> nearCornerRay = cornerRay * prevSplitDistance;
279 const vec3<F32> farCornerRay = cornerRay * splitDistance;
281 frustumCornersWS[i + 4] = frustumCornersWS[i] + farCornerRay;
282 frustumCornersWS[i] = frustumCornersWS[i] + nearCornerRay;
286 for (
const vec3<F32>& corner : frustumCornersWS )
288 frustumCenter += corner;
290 frustumCenter /= 8.0f;
293 for (
const vec3<F32>& corner : frustumCornersWS )
295 const F32 distance = (corner - frustumCenter).lengthSquared();
296 radius = std::max( radius, distance );
298 radius = std::ceil(
Sqrt( radius ) * 16.0f ) / 16.0f;
299 radius += appliedDiff;
301 vec3<F32> maxExtents( radius, radius, radius );
305 vec3<F32> lightPosition = frustumCenter - light.directionCache() * (light.csmNearClipOffset() - minExtents.
z);
308 if ( cascadeIterator > 0 && light.csmUseSceneAABBFit()[cascadeIterator] )
311 bool validResult =
false;
312 auto& prevPassResults = light.feedBackContainers()[cascadeIterator];
313 if ( !prevPassResults.empty() )
316 for (
auto& node : prevPassResults )
318 const SceneNode& sNode = node._node->getNode();
328 meshAABB.transform( lightViewMatrix );
329 appliedDiff = meshAABB.getHalfExtent().y - radius;
330 if ( appliedDiff > 0.5f )
332 radius += appliedDiff * 0.75f;
334 maxExtents.
set( radius, radius, radius );
335 minExtents = -maxExtents;
338 lightPosition = frustumCenter - light.directionCache() * (light.csmNearClipOffset() - minExtents.
z);
348 maxExtents.
z - minExtents.
z
360 roundedOrigin.
round();
374 light.setShadowLightPos( cascadeIterator, lightPosition );
385 const U8 numSplits = dirLight.csmSplitCount();
401 auto cmd = GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>( bufferInOut);
402 Util::StringFormat( cmd->_scopeName,
"Cascaded Shadow Pass Light: [ {} ]", lightIndex );
403 cmd->_scopeId = lightIndex;
407 for (
I8 i = numSplits - 1; i >= 0 && i < numSplits; i-- )
415 if ( i > 0 && dirLight.csmUseSceneAABBFit()[i] )
417 STUBBED(
"CascadedShadowMapsGenerator::render: Validate AABBFit for first cascade!" );
425 const U16 layerOffset = dirLight.getShadowArrayOffset();
426 const U8 layerCount = dirLight.csmSplitCount();
433 for (
U8 i = 0u; i < dirLight.csmSplitCount(); ++i )
442 ._layerOffset =
to_U16( layerOffset + i ),
451 blurTarget( layerOffset, layerCount, bufferInOut );
454 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>( bufferInOut );
460 constexpr F32 offset = 500.f;
465 const vec2<F32> maxExtents( offset, offset );
466 const vec2<F32> minExtents = -maxExtents;
468 const Rect<I32> orthoRect = { minExtents.
x, maxExtents.
x, minExtents.
y, maxExtents.
y };
469 const vec2<F32> zPlanes = { 1.f, offset * 1.5f };
472 Camera* shadowCamera = shadowCameras[0];
490 GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>( bufferInOut )->_scopeName =
"World AO Render Pass";
491 _context.
context().
kernel().renderPassManager()->doCustomPass( shadowCamera, params, bufferInOut, memCmdInOut );
525 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>( bufferInOut );
543 beginRenderPassCmd._name =
"DO_CSM_BLUR_PASS_HORIZONTAL";
548 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>( bufferInOut );
551 Set( binding.
_data, shadowAtt->texture(), shadowAtt->_descriptor._sampler );
559 GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData =
_shaderConstants;
561 GFX::EnqueueCommand<GFX::DrawCommand>( bufferInOut )->_drawCommands.emplace_back();
563 GFX::EnqueueCommand<GFX::EndRenderPassCommand>( bufferInOut );
566 beginRenderPassCmd._target = rtHandle.
_targetID;
567 beginRenderPassCmd._name =
"DO_CSM_BLUR_PASS_VERTICAL";
568 if ( layerCount == 1u )
576 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>( bufferInOut );
579 Set( binding.
_data, blurAtt->texture(), blurAtt->_descriptor._sampler );
587 GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData =
_shaderConstants;
589 GFX::EnqueueCommand<GFX::DrawCommand>( bufferInOut )->_drawCommands.emplace_back();
591 GFX::EnqueueCommand<GFX::EndRenderPassCommand>( bufferInOut );
#define WAIT_FOR_CONDITION(...)
#define PROFILE_SCOPE_AUTO(CATEGORY)
static void worldAOViewProjectionMatrix(GFXDevice &device, const mat4< F32 > &vpMatrix) noexcept
const BoundingBox & getBoundingBox() const noexcept
const mat4< F32 > & setProjection(vec2< F32 > zPlanes)
const mat4< F32 > & viewProjectionMatrix() const noexcept
Returns the most recent/up-to-date viewProjection matrix.
const mat4< F32 > & lookAt(const mat4< F32 > &viewMatrix)
Sets the camera's view matrix to specify the specified value by extracting the eye position,...
const CameraSnapshot & snapshot() const noexcept
Returns the internal camera snapshot data (eye, orientation, etc)
bool updateLookAt()
Return true if the cached camera state wasn't up-to-date.
static mat4< F32 > Ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar) noexcept
void render(const Camera &playerCamera, Light &light, U16 lightIndex, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut) override
void generateWorldAO(const Camera &playerCamera, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut)
void applyFrustumSplits(DirectionalLightComponent &light, const Camera &shadowCamera, U8 numSplits) const
void blurTarget(U16 layerOffset, U16 layerCount, GFX::CommandBuffer &bufferInOut)
std::array< F32, Config::Lighting::MAX_CSM_SPLITS_PER_LIGHT > SplitDepths
PushConstantsStruct _shaderConstants
RenderTargetHandle _blurBuffer
Pipeline * _blurPipelineAO
Pipeline * _blurPipelineCSM
Handle< ShaderProgram > _blurAOMapShader
Handle< ShaderProgram > _blurDepthMapShader
CascadedShadowMapsGenerator(GFXDevice &context)
RenderTargetHandle _drawBufferDepth
void updateMSAASampleCount(U8 sampleCount) override
~CascadedShadowMapsGenerator() override
SplitDepths calculateSplitDepths(DirectionalLightComponent &light, const vec2< F32 > nearFarPlanes) const noexcept
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
GFXRTPool & renderTargetPool() noexcept
Pipeline * newPipeline(const PipelineDescriptor &descriptor)
Create and return a new graphics pipeline. This is only used for caching and doesn't use the object a...
const RenderStateBlock & get2DStateBlock() const noexcept
RenderTargetHandle allocateRT(const RenderTargetDescriptor &descriptor)
bool deallocateRT(RenderTargetHandle &handle)
A light object placed in the scene at a certain position.
PlatformContext & context() noexcept
Kernel & kernel() noexcept
Configuration & config() noexcept
Handle< Texture > texture() const
void doCustomPass(Camera *const camera, RenderPassParams params, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut)
RTAttachment * getAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
bool updateSampleCount(U8 newSampleCount)
Change msaa sampel count for all attachments.
vec2< U16 > getResolution() const noexcept
static const RenderTargetHandle & getShadowMap(LightType type)
static vector< Camera * > & shadowCameras(const ShadowType type) noexcept
static constexpr U8 WORLD_AO_LAYER_INDEX
static mat4< T > Multiply(const mat4< T > &matrixA, const mat4< T > &matrixB) noexcept
ret = A * B
void translate(const vec3< U > &v) noexcept
void set(const T *v) noexcept
set the 2 components of the vector manually using a source pointer to a (large enough) array
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
void round() noexcept
round all four values
constexpr U8 MAX_CSM_SPLITS_PER_LIGHT
Used for CSM or PSSM to determine the maximum number of frustum splits.
FColour4 WHITE
Random stuff added for convenience.
FORCE_INLINE T * EnqueueCommand(CommandBuffer &buffer)
constexpr Optick::Category::Type Graphics
Str StringFormat(const char *fmt, Args &&...args)
Configuration::Rendering::ShadowMapping g_shadowSettings
constexpr F32 g_minExtentsFactors[]
Handle console commands that start with a forward slash.
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
static const mat4< F32 > MAT4_BIAS_ZERO_ONE_Z
constexpr U16 to_U16(const T value)
constexpr F32 to_F32(const T value)
DirectionalLightComponent(SceneGraphNode *sgn, PlatformContext &context)
void GetInverse(const mat4< T > &inM, mat4< T > &r) noexcept
void Set(DescriptorSetBindingData &dataInOut, ShaderBuffer *buffer, const BufferRange range) noexcept
DescriptorSetBinding & AddBinding(DescriptorSet &setInOut, U8 slot, U16 stageVisibilityMask)
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
static const vec3< F32 > WORLD_Z_NEG_AXIS
RTClearEntry DEFAULT_CLEAR_ENTRY
static const vec3< F32 > VECTOR3_ZERO
FORCE_INLINE T * Get(const Handle< T > handle)
static const vec3< F32 > WORLD_Y_AXIS
constexpr auto to_base(const Type value) -> Type
Divide::Configuration::Rendering::ShadowMapping::CSMSettings csm
struct Divide::Configuration::Rendering::ShadowMapping shadowMapping
struct Divide::Configuration::Rendering rendering
static NO_INLINE void printfn(const char *format, T &&... args)
DescriptorSetBindingData _data
RTDrawDescriptor _descriptor
RenderTargetID _destination
Handle< Texture > _texture
PrimitiveTopology _primitiveTopology
Handle< ShaderProgram > _shaderProgramHandle
RenderStateBlock _stateBlock
vector< ShaderModuleDescriptor > _modules
ModuleDefines _globalDefines
DrawLayerEntry _writeLayers[RT_MAX_ATTACHMENT_COUNT]
bool _layeredRendering
Set to true to bind all image layers to the render target (e.g. for Geometry Shader layered rendering...
const SceneGraphNode * _sourceNode
RTDrawDescriptor _targetDescriptorMainPass
RenderStagePass _stagePass
FeedBackContainer * _feedBackContainer
RTClearDescriptor _clearDescriptorMainPass
InternalRTAttachmentDescriptors _attachments
TextureWrap _wrapU
Texture wrap mode (Or S-R-T)