Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
CascadedShadowMapsGenerator.cpp
Go to the documentation of this file.
1
2
4
6
9
12
13#include "Core/Headers/Kernel.h"
20
26
27namespace Divide
28{
29
30 namespace
31 {
33
35 {
36 0.025f,
37 1.75f,
38 75.0f,
39 125.0f
40 };
41 }
42
44 : ShadowMapGenerator( context, ShadowType::CSM )
45 {
46 Console::printfn( LOCALE_STR( "LIGHT_CREATE_SHADOW_FB"), "EVCSM" );
47
49
50 g_shadowSettings = context.context().config().rendering.shadowMapping;
51 {
52 ShaderModuleDescriptor vertModule{ ShaderType::VERTEX, "baseVertexShaders.glsl", "FullScreenQuad" };
53 ShaderModuleDescriptor geomModule{ ShaderType::GEOMETRY, "blur.glsl", "GaussBlur" };
54 ShaderModuleDescriptor fragModule{ ShaderType::FRAGMENT, "blur.glsl", "GaussBlur.Layered" };
55
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)" );
60
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)" );
66
67 ShaderProgramDescriptor shaderDescriptor = {};
68 shaderDescriptor._modules.push_back( vertModule );
69 shaderDescriptor._modules.push_back( geomModule );
70 shaderDescriptor._modules.push_back( fragModule );
71 shaderDescriptor._globalDefines.emplace_back( Util::StringFormat( "GS_MAX_INVOCATIONS {}", Config::Lighting::MAX_CSM_SPLITS_PER_LIGHT ) );
72
73 {
74 ResourceDescriptor<ShaderProgram> blurDepthMapShader( Util::StringFormat( "GaussBlur_{}_invocations", Config::Lighting::MAX_CSM_SPLITS_PER_LIGHT ), shaderDescriptor );
75 blurDepthMapShader.waitForReady( true );
76 _blurDepthMapShader = CreateResource( blurDepthMapShader );
77 PipelineDescriptor pipelineDescriptor = {};
78 pipelineDescriptor._stateBlock = _context.get2DStateBlock();
79 pipelineDescriptor._shaderProgramHandle = _blurDepthMapShader;
81
82 _blurPipelineCSM = _context.newPipeline( pipelineDescriptor );
83 }
84 shaderDescriptor._globalDefines[0]._define = "GS_MAX_INVOCATIONS 1u";
85 {
86 ResourceDescriptor<ShaderProgram> blurDepthMapShader( "GaussBlur_1_invocations", shaderDescriptor );
87 blurDepthMapShader.waitForReady( true );
88 _blurAOMapShader = CreateResource( blurDepthMapShader );
89 PipelineDescriptor pipelineDescriptor = {};
90 pipelineDescriptor._stateBlock = _context.get2DStateBlock();
91 pipelineDescriptor._shaderProgramHandle = _blurAOMapShader;
93
94 _blurPipelineAO = _context.newPipeline( pipelineDescriptor );
95 }
96 }
97
99 _shaderConstants.data[0]._vec[1].z = 0.f;
100 _shaderConstants.data[0]._vec[1].w = 0.f;
101
102 std::array<vec2<F32>*, 12> blurSizeConstants = {
115 };
116
117 blurSizeConstants[0]->set( 1.f / g_shadowSettings.csm.shadowMapResolution );
118 for ( size_t i = 1u; i < blurSizeConstants.size(); ++i )
119 {
120 blurSizeConstants[i]->set((*blurSizeConstants[i - 1]) * 0.5f);
121 }
122
123 SamplerDescriptor sampler{};
125 sampler._wrapV = TextureWrap::CLAMP_TO_EDGE;
126 sampler._wrapW = TextureWrap::CLAMP_TO_EDGE;
127 sampler._mipSampling = TextureMipSampling::NONE;
128 sampler._anisotropyLevel = 0u;
129
130 const auto& texDescriptor = Get(rt->getAttachment( RTAttachmentType::COLOUR )->texture())->descriptor();
131 // Draw FBO
132 {
133 // MSAA rendering is supported
134 TextureDescriptor colourDescriptor{};
135 colourDescriptor._texType = TextureType::TEXTURE_2D_ARRAY;
136 colourDescriptor._dataType = texDescriptor._dataType;
137 colourDescriptor._baseFormat = texDescriptor._baseFormat;
138 colourDescriptor._layerCount = Config::Lighting::MAX_CSM_SPLITS_PER_LIGHT;
139 colourDescriptor._mipMappingState = MipMappingState::OFF;
140
141 TextureDescriptor depthDescriptor{};
142 depthDescriptor._texType = TextureType::TEXTURE_2D_ARRAY;
143 depthDescriptor._dataType = GFXDataFormat::UNSIGNED_INT;
144 depthDescriptor._baseFormat = GFXImageFormat::RED;
145 depthDescriptor._packing = GFXImagePacking::DEPTH;
146 depthDescriptor._layerCount = Config::Lighting::MAX_CSM_SPLITS_PER_LIGHT;
147 depthDescriptor._mipMappingState = MipMappingState::OFF;
148
149 RenderTargetDescriptor desc = {};
150 desc._attachments =
151 {
154 };
155
156 desc._resolution = rt->getResolution();
157 desc._name = "CSM_ShadowMap_Draw";
158 desc._msaaSamples = g_shadowSettings.csm.MSAASamples;
159
160 _drawBufferDepth = context.renderTargetPool().allocateRT( desc );
161 }
162
163 //Blur FBO
164 {
165 TextureDescriptor blurMapDescriptor{};
166 blurMapDescriptor._texType = TextureType::TEXTURE_2D_ARRAY;
167 blurMapDescriptor._dataType = texDescriptor._dataType;
168 blurMapDescriptor._baseFormat = texDescriptor._baseFormat;
169 blurMapDescriptor._packing = texDescriptor._packing;
170 blurMapDescriptor._layerCount = Config::Lighting::MAX_CSM_SPLITS_PER_LIGHT;
171 blurMapDescriptor._mipMappingState = MipMappingState::OFF;
172
173 RenderTargetDescriptor desc = {};
174 desc._attachments =
175 {
177 };
178
179 desc._name = "CSM_Blur";
180 desc._resolution = rt->getResolution();
181
183 }
184
186 }
187
189 {
192 {
194 }
195
198 }
199
201 {
202 //Between 0 and 1, change these to check the results
203 constexpr F32 minDistance = 0.0f;
204 constexpr F32 maxDistance = 1.0f;
205
206 SplitDepths depths = {};
207
208 const U8 numSplits = light.csmSplitCount();
209 const F32 nearClip = nearFarPlanes.min;
210 const F32 farClip = nearFarPlanes.max;
211 const F32 clipRange = farClip - nearClip;
212
213 DIVIDE_ASSERT( clipRange > 0.f, "CascadedShadowMapsGenerator::calculateSplitDepths error: invalid clip range specified!" );
214
215 const F32 minZ = nearClip + minDistance * clipRange;
216 const F32 maxZ = nearClip + maxDistance * clipRange;
217
218 const F32 range = maxZ - minZ;
219 const F32 ratio = maxZ / minZ;
220
221 U8 i = 0;
222 for ( ; i < numSplits; ++i )
223 {
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;
227 const F32 d = g_shadowSettings.csm.splitLambda * (log - uniform) + uniform;
228 depths[i] = (d - nearClip) / clipRange;
229 light.setShadowFloatValue( i, d );
230 }
231
233 {
234 depths[i] = F32_MAX;
235 light.setShadowFloatValue( i, -depths[i] );
236 }
237
238 return depths;
239 }
240
241 void CascadedShadowMapsGenerator::applyFrustumSplits( DirectionalLightComponent& light, const Camera& shadowCamera, U8 numSplits ) const
242 {
244
245 const SplitDepths splitDepths = calculateSplitDepths( light, shadowCamera.snapshot()._zPlanes );
246
247 const mat4<F32> invViewProj = GetInverse( shadowCamera.viewProjectionMatrix() );
248
249 F32 appliedDiff = 0.0f;
250 for ( U8 cascadeIterator = 0; cascadeIterator < numSplits; ++cascadeIterator )
251 {
252 Camera* lightCam = ShadowMap::shadowCameras( ShadowType::CSM )[cascadeIterator];
253
254 const F32 prevSplitDistance = cascadeIterator == 0 ? 0.0f : splitDepths[cascadeIterator - 1];
255 const F32 splitDistance = splitDepths[cascadeIterator];
256
257 vec3<F32> frustumCornersWS[8]
258 {
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},
263 {-1.0f, 1.0f, 1.0f},
264 { 1.0f, 1.0f, 1.0f},
265 { 1.0f, -1.0f, 1.0f},
266 {-1.0f, -1.0f, 1.0f},
267 };
268
269 for ( vec3<F32>& corner : frustumCornersWS )
270 {
271 const vec4<F32> inversePoint = invViewProj * vec4<F32>( corner, 1.0f );
272 corner.set( inversePoint / inversePoint.w );
273 }
274
275 for ( U8 i = 0; i < 4; ++i )
276 {
277 const vec3<F32> cornerRay = frustumCornersWS[i + 4] - frustumCornersWS[i];
278 const vec3<F32> nearCornerRay = cornerRay * prevSplitDistance;
279 const vec3<F32> farCornerRay = cornerRay * splitDistance;
280
281 frustumCornersWS[i + 4] = frustumCornersWS[i] + farCornerRay;
282 frustumCornersWS[i] = frustumCornersWS[i] + nearCornerRay;
283 }
284
285 vec3<F32> frustumCenter = VECTOR3_ZERO;
286 for ( const vec3<F32>& corner : frustumCornersWS )
287 {
288 frustumCenter += corner;
289 }
290 frustumCenter /= 8.0f;
291
292 F32 radius = 0.0f;
293 for ( const vec3<F32>& corner : frustumCornersWS )
294 {
295 const F32 distance = (corner - frustumCenter).lengthSquared();
296 radius = std::max( radius, distance );
297 }
298 radius = std::ceil( Sqrt( radius ) * 16.0f ) / 16.0f;
299 radius += appliedDiff;
300
301 vec3<F32> maxExtents( radius, radius, radius );
302 vec3<F32> minExtents = -maxExtents;
303
304 //Position the view matrix looking down the center of the frustum with an arbitrary light direction
305 vec3<F32> lightPosition = frustumCenter - light.directionCache() * (light.csmNearClipOffset() - minExtents.z);
306 mat4<F32> lightViewMatrix = lightCam->lookAt( lightPosition, frustumCenter, WORLD_Y_AXIS );
307
308 if ( cascadeIterator > 0 && light.csmUseSceneAABBFit()[cascadeIterator] )
309 {
310 // Only meshes should be enough
311 bool validResult = false;
312 auto& prevPassResults = light.feedBackContainers()[cascadeIterator];
313 if ( !prevPassResults.empty() )
314 {
315 BoundingBox meshAABB{};
316 for ( auto& node : prevPassResults )
317 {
318 const SceneNode& sNode = node._node->getNode();
319 if ( sNode.type() == SceneNodeType::TYPE_SUBMESH)
320 {
321 meshAABB.add( node._node->get<BoundsComponent>()->getBoundingBox() );
322 validResult = true;
323 }
324 }
325
326 if ( validResult )
327 {
328 meshAABB.transform( lightViewMatrix );
329 appliedDiff = meshAABB.getHalfExtent().y - radius;
330 if ( appliedDiff > 0.5f )
331 {
332 radius += appliedDiff * 0.75f;
333
334 maxExtents.set( radius, radius, radius );
335 minExtents = -maxExtents;
336
337 //Position the view matrix looking down the center of the frustum with an arbitrary light direction
338 lightPosition = frustumCenter - light.directionCache() * (light.csmNearClipOffset() - minExtents.z);
339 lightViewMatrix = lightCam->lookAt( lightPosition, frustumCenter, WORLD_Y_AXIS );
340 }
341 }
342 }
343 }
344
345 const vec2<F32> clip
346 {
347 0.0001f,
348 maxExtents.z - minExtents.z
349 };
350
351 mat4<F32> lightOrthoMatrix = Camera::Ortho( minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, clip.min, clip.max );
352
353 // The rounding matrix that ensures that shadow edges do not shimmer
354 // http://www.gamedev.net/topic/591684-xna-40---shimmering-shadow-maps/
355 {
356 const mat4<F32> shadowMatrix = mat4<F32>::Multiply( lightOrthoMatrix, lightViewMatrix );
357 const vec4<F32> shadowOrigin = shadowMatrix * vec4<F32>{VECTOR3_ZERO, 1.f } * (g_shadowSettings.csm.shadowMapResolution * 0.5f);
358
359 vec4<F32> roundedOrigin = shadowOrigin;
360 roundedOrigin.round();
361
362 lightOrthoMatrix.translate( vec3<F32>
363 {
364 (roundedOrigin.xy - shadowOrigin.xy) * 2.0f / g_shadowSettings.csm.shadowMapResolution, 0.0f
365 } );
366
367 // Use our adjusted matrix for actual rendering
368 lightCam->setProjection( lightOrthoMatrix, clip, true );
369 }
370 lightCam->updateLookAt();
371
372 const mat4<F32> lightVP = mat4<F32>::Multiply( lightOrthoMatrix, lightViewMatrix );
373
374 light.setShadowLightPos( cascadeIterator, lightPosition );
375 light.setShadowVPMatrix( cascadeIterator, mat4<F32>::Multiply( MAT4_BIAS_ZERO_ONE_Z, lightVP ) );
376 }
377 }
378
379 void CascadedShadowMapsGenerator::render( const Camera& playerCamera, Light& light, U16 lightIndex, GFX::CommandBuffer& bufferInOut, GFX::MemoryBarrierCommand& memCmdInOut )
380 {
382
383 auto& dirLight = static_cast<DirectionalLightComponent&>(light);
384
385 const U8 numSplits = dirLight.csmSplitCount();
386 applyFrustumSplits( dirLight, playerCamera, numSplits );
387
388 RenderPassParams params = {};
389 params._sourceNode = light.sgn();
392 params._maxLoD = -1;
393 params._refreshLightData = false;
395
398
400
401 auto cmd = GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>( bufferInOut);
402 Util::StringFormat( cmd->_scopeName, "Cascaded Shadow Pass Light: [ {} ]", lightIndex );
403 cmd->_scopeId = lightIndex;
404
405 RenderPassManager* rpm = _context.context().kernel().renderPassManager().get();
406
407 for ( I8 i = numSplits - 1; i >= 0 && i < numSplits; i-- )
408 {
411
412 Util::StringFormat( params._passName, "CSM_PASS_{}", i );
413 params._stagePass._pass = static_cast<RenderStagePass::PassIndex>(i);
414 params._minExtents.set( g_minExtentsFactors[i] );
415 if ( i > 0 && dirLight.csmUseSceneAABBFit()[i] )
416 {
417 STUBBED( "CascadedShadowMapsGenerator::render: Validate AABBFit for first cascade!" );
418 params._feedBackContainer = &dirLight.feedBackContainers()[i];
419 params._feedBackContainer->resize( 0 );
420 }
421
422 rpm->doCustomPass( ShadowMap::shadowCameras( ShadowType::CSM )[i], params, bufferInOut, memCmdInOut );
423 }
424
425 const U16 layerOffset = dirLight.getShadowArrayOffset();
426 const U8 layerCount = dirLight.csmSplitCount();
427
429
430 GFX::BlitRenderTargetCommand* blitRenderTargetCommand = GFX::EnqueueCommand<GFX::BlitRenderTargetCommand>( bufferInOut );
431 blitRenderTargetCommand->_source = _drawBufferDepth._targetID;
432 blitRenderTargetCommand->_destination = rtHandle._targetID;
433 for ( U8 i = 0u; i < dirLight.csmSplitCount(); ++i )
434 {
435 blitRenderTargetCommand->_params.emplace_back( RTBlitEntry
436 {
437 ._input = {
438 ._layerOffset = i,
439 ._index = 0u
440 },
441 ._output = {
442 ._layerOffset = to_U16( layerOffset + i ),
443 ._index = 0u
444 }
445 } );
446 }
447
448 // Now we can either blur our target or just skip to mipmap computation
449 if ( g_shadowSettings.csm.enableBlurring )
450 {
451 blurTarget( layerOffset, layerCount, bufferInOut );
452 }
453
454 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>( bufferInOut );
455 }
456
458 {
459 //ToDo: compute this:
460 constexpr F32 offset = 500.f;
461
462 // Use a top down camera encompasing most of the scene
463 const vec3<F32> playerCamPos = playerCamera.snapshot()._eye;
464
465 const vec2<F32> maxExtents( offset, offset );
466 const vec2<F32> minExtents = -maxExtents;
467
468 const Rect<I32> orthoRect = { minExtents.x, maxExtents.x, minExtents.y, maxExtents.y };
469 const vec2<F32> zPlanes = { 1.f, offset * 1.5f };
470
471 auto& shadowCameras = ShadowMap::shadowCameras( ShadowType::SINGLE );
472 Camera* shadowCamera = shadowCameras[0];
473 const mat4<F32> viewMatrix = shadowCamera->lookAt( playerCamPos + vec3<F32>( 0.f, offset, 0.f ), playerCamPos, WORLD_Z_NEG_AXIS );
474 const mat4<F32> projMatrix = shadowCamera->setProjection( orthoRect, zPlanes );
475 shadowCamera->updateLookAt();
476
477 // Render large(ish) objects into shadow map
478 RenderPassParams params = {};
479 params._sourceNode = nullptr;
482 params._maxLoD = -1;
483 params._refreshLightData = false;
484 params._passName = "WorldAOPass";
485 params._minExtents.set( g_minExtentsFactors[1] );
489
490 GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>( bufferInOut )->_scopeName = "World AO Render Pass";
491 _context.context().kernel().renderPassManager()->doCustomPass( shadowCamera, params, bufferInOut, memCmdInOut );
492
494
495 GFX::BlitRenderTargetCommand blitRenderTargetCommand = {};
496 blitRenderTargetCommand._source = _drawBufferDepth._targetID;
497 blitRenderTargetCommand._destination = handle._targetID;
498 blitRenderTargetCommand._params.emplace_back( RTBlitEntry
499 {
500 ._input = {
501 ._layerOffset = 0u,
502 ._index = 0u
503 },
504 ._output = {
505 ._layerOffset = ShadowMap::WORLD_AO_LAYER_INDEX,
506 ._index = 0u
507 }
508 } );
509
510 GFX::EnqueueCommand( bufferInOut, blitRenderTargetCommand );
511
512 // Apply a large blur to the map
514 // Used when sampling from sky probes. Us world X/Z to determine if we are in shadow or not. If we are, don't sample sky probe
515 // Can be used for other effects (e.g. rain culling)
516
517 GFX::ComputeMipMapsCommand computeMipMapsCommand = {};
518 computeMipMapsCommand._texture = handle._rt->getAttachment( RTAttachmentType::COLOUR )->texture();
519 computeMipMapsCommand._usage = ImageUsage::SHADER_READ;
520 SubRange& layerRange = computeMipMapsCommand._layerRange;
522 layerRange._count = 1u;
523 GFX::EnqueueCommand( bufferInOut, computeMipMapsCommand );
524
525 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>( bufferInOut );
526
528 }
529
530 void CascadedShadowMapsGenerator::blurTarget( const U16 layerOffset, const U16 layerCount, GFX::CommandBuffer & bufferInOut )
531 {
533 const auto& shadowAtt = rtHandle._rt->getAttachment( RTAttachmentType::COLOUR );
534
535 GFX::BeginRenderPassCommand beginRenderPassCmd{};
536 beginRenderPassCmd._descriptor._layeredRendering = true;
537
538 beginRenderPassCmd._clearDescriptor[to_base( RTColourAttachmentSlot::SLOT_0 )] = { DefaultColours::WHITE, true };
539 beginRenderPassCmd._descriptor._drawMask[to_base( RTColourAttachmentSlot::SLOT_0 )] = true;
540
541 // Blur horizontally
542 beginRenderPassCmd._target = _blurBuffer._targetID;
543 beginRenderPassCmd._name = "DO_CSM_BLUR_PASS_HORIZONTAL";
544 GFX::EnqueueCommand( bufferInOut, beginRenderPassCmd );
545
546 GFX::EnqueueCommand<GFX::BindPipelineCommand>( bufferInOut )->_pipeline = layerCount == 1u ? _blurPipelineAO : _blurPipelineCSM;
547 {
548 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>( bufferInOut );
549 cmd->_usage = DescriptorSetUsage::PER_DRAW;
551 Set( binding._data, shadowAtt->texture(), shadowAtt->_descriptor._sampler );
552 }
553
554 _shaderConstants.data[0]._vec[1].x = 0.f;
555 _shaderConstants.data[0]._vec[1].y = to_F32( layerCount );
556 _shaderConstants.data[0]._vec[1].z = to_F32( layerOffset );
557 _shaderConstants.data[0]._vec[1].w = 0.f;
558
559 GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData = _shaderConstants;
560
561 GFX::EnqueueCommand<GFX::DrawCommand>( bufferInOut )->_drawCommands.emplace_back();
562
563 GFX::EnqueueCommand<GFX::EndRenderPassCommand>( bufferInOut );
564
565 // Blur vertically
566 beginRenderPassCmd._target = rtHandle._targetID;
567 beginRenderPassCmd._name = "DO_CSM_BLUR_PASS_VERTICAL";
568 if ( layerCount == 1u )
569 {
570 beginRenderPassCmd._clearDescriptor[to_base( RTColourAttachmentSlot::SLOT_0 )] = { DefaultColours::WHITE, false };
571 }
572
573 GFX::EnqueueCommand( bufferInOut, beginRenderPassCmd );
574 const auto& blurAtt = _blurBuffer._rt->getAttachment( RTAttachmentType::COLOUR );
575 {
576 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>( bufferInOut );
577 cmd->_usage = DescriptorSetUsage::PER_DRAW;
579 Set( binding._data, blurAtt->texture(), blurAtt->_descriptor._sampler );
580 }
581
582 _shaderConstants.data[0]._vec[1].x = 1.f;
583 _shaderConstants.data[0]._vec[1].y = to_F32( layerCount );
584 _shaderConstants.data[0]._vec[1].z = 0.f;
585 _shaderConstants.data[0]._vec[1].w = to_F32( layerOffset );
586
587 GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData = _shaderConstants;
588
589 GFX::EnqueueCommand<GFX::DrawCommand>( bufferInOut )->_drawCommands.emplace_back();
590
591 GFX::EnqueueCommand<GFX::EndRenderPassCommand>( bufferInOut );
592 }
593
595 {
597 {
599 _drawBufferDepth._rt->updateSampleCount( sampleCount );
600 }
601 }
602}
#define WAIT_FOR_CONDITION(...)
#define LOCALE_STR(X)
Definition: Localization.h:91
#define DIVIDE_ASSERT(...)
#define STUBBED(x)
#define DIVIDE_UNEXPECTED_CALL()
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
static void worldAOViewProjectionMatrix(GFXDevice &device, const mat4< F32 > &vpMatrix) noexcept
Definition: GFXDevice.h:656
const BoundingBox & getBoundingBox() const noexcept
const mat4< F32 > & setProjection(vec2< F32 > zPlanes)
Definition: Camera.cpp:516
const mat4< F32 > & viewProjectionMatrix() const noexcept
Returns the most recent/up-to-date viewProjection matrix.
Definition: Camera.inl:186
const mat4< F32 > & lookAt(const mat4< F32 > &viewMatrix)
Sets the camera's view matrix to specify the specified value by extracting the eye position,...
Definition: Camera.cpp:354
const CameraSnapshot & snapshot() const noexcept
Returns the internal camera snapshot data (eye, orientation, etc)
Definition: Camera.inl:43
bool updateLookAt()
Return true if the cached camera state wasn't up-to-date.
Definition: Camera.cpp:384
static mat4< F32 > Ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar) noexcept
Definition: Camera.inl:219
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
void updateMSAASampleCount(U8 sampleCount) 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.
Definition: GFXDevice.h:215
GFXRTPool & renderTargetPool() noexcept
Definition: GFXDevice.inl:133
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...
Definition: GFXDevice.cpp:3074
const RenderStateBlock & get2DStateBlock() const noexcept
Definition: GFXDevice.inl:123
RenderTargetHandle allocateRT(const RenderTargetDescriptor &descriptor)
Definition: GFXRTPool.cpp:17
bool deallocateRT(RenderTargetHandle &handle)
Definition: GFXRTPool.cpp:33
A light object placed in the scene at a certain position.
Definition: Light.h:58
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
const ShadowType _type
Definition: ShadowMap.h:83
static const RenderTargetHandle & getShadowMap(LightType type)
Definition: ShadowMap.cpp:495
static vector< Camera * > & shadowCameras(const ShadowType type) noexcept
Definition: ShadowMap.h:122
static constexpr U8 WORLD_AO_LAYER_INDEX
Definition: ShadowMap.h:91
vec4< T > _vec[4]
Definition: MathMatrices.h:709
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
Definition: MathVectors.h:335
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:707
vec2< T > xy
Definition: MathVectors.h:1366
void round() noexcept
round all four values
vec2< T > zw
Definition: MathVectors.h:1366
constexpr U8 MAX_CSM_SPLITS_PER_LIGHT
Used for CSM or PSSM to determine the maximum number of frustum splits.
Definition: config.h:159
FColour4 WHITE
Random stuff added for convenience.
Definition: Colours.cpp:8
FORCE_INLINE T * EnqueueCommand(CommandBuffer &buffer)
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
Str StringFormat(const char *fmt, Args &&...args)
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
Definition: RTAttachment.h:71
static const mat4< F32 > MAT4_BIAS_ZERO_ONE_Z
Definition: MathMatrices.h:720
T Sqrt(T input) noexcept
Definition: MathHelper.inl:252
constexpr U16 to_U16(const T value)
uint8_t U8
constexpr F32 to_F32(const T value)
DirectionalLightComponent(SceneGraphNode *sgn, PlatformContext &context)
void GetInverse(const mat4< T > &inM, mat4< T > &r) noexcept
constexpr F32 F32_MAX
uint16_t U16
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
Definition: MathVectors.h:1444
ShadowType
Definition: ShadowMap.h:40
RTClearEntry DEFAULT_CLEAR_ENTRY
static const vec3< F32 > VECTOR3_ZERO
Definition: MathVectors.h:1434
FORCE_INLINE T * Get(const Handle< T > handle)
static const vec3< F32 > WORLD_Y_AXIS
Definition: MathVectors.h:1440
constexpr auto to_base(const Type value) -> Type
U16 _layerOffset
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
U16 _layer
PrimitiveTopology _primitiveTopology
Definition: Pipeline.h:48
Handle< ShaderProgram > _shaderProgramHandle
Definition: Pipeline.h:47
RenderStateBlock _stateBlock
Definition: Pipeline.h:46
vector< ShaderModuleDescriptor > _modules
BlitEntry _input
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
FeedBackContainer * _feedBackContainer
RTClearDescriptor _clearDescriptorMainPass
InternalRTAttachmentDescriptors _attachments
Definition: RenderTarget.h:52
RenderTargetID _targetID
Definition: RenderTarget.h:47
TextureWrap _wrapU
Texture wrap mode (Or S-R-T)