Refactor rendering frame execution contracts
This commit is contained in:
310
docs/plan/Renderer_C++层第一阶段收口计划_2026-04-13_晚间.md
Normal file
310
docs/plan/Renderer_C++层第一阶段收口计划_2026-04-13_晚间.md
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
# Renderer C++层第一阶段收口计划
|
||||||
|
|
||||||
|
日期: `2026-04-13`
|
||||||
|
|
||||||
|
## 1. 文档定位
|
||||||
|
|
||||||
|
这份文档是 `Render Graph` 之前的最后一轮 `native render kernel v1` 收口计划。
|
||||||
|
|
||||||
|
目标不是继续往当前 `Rendering` 层里塞新功能,而是先把下面几件事彻底做清楚:
|
||||||
|
|
||||||
|
- `request -> frame plan -> execution` 三层语义分开。
|
||||||
|
- `RenderSceneExtractor -> CullingResults -> RendererList -> DrawSettings` 这条数据组织链正式化。
|
||||||
|
- `BuiltinForwardPipeline` 从“大杂烩渲染器”收成“协调器 + 子能力”。
|
||||||
|
- `Editor` 注入点、阴影、主场景、后处理之间的边界说清楚。
|
||||||
|
- 给下一步 `C++ Render Graph` 留出稳定输入,而不是把当前混乱直接 graph 化。
|
||||||
|
|
||||||
|
结论先写在前面:
|
||||||
|
|
||||||
|
- `Render Graph` 应该做在 `C++ native` 层。
|
||||||
|
- 现在还不应该直接开做 `Render Graph` 或 `Deferred Renderer`。
|
||||||
|
- 当前更优先的是把现有渲染层整理干净,再往 SRP/URP 方向演进。
|
||||||
|
|
||||||
|
## 2. 当前阶段已经完成的收口
|
||||||
|
|
||||||
|
截至 `2026-04-13` 晚间,已经落地的内容:
|
||||||
|
|
||||||
|
- `CameraRenderRequest -> CameraFramePlan` 已经分层,`CameraRenderer` 开始正式消费 plan。
|
||||||
|
- `CullingResults / RendererList` contract 已经进入 `RenderSceneData`。
|
||||||
|
- `Forward / Depth / ObjectId` 已经优先走 `RendererList`,旧 `visibleItems` 只保留过渡 fallback。
|
||||||
|
- `RendererListUtils` 已经把可见项遍历规则收口成公共工具。
|
||||||
|
- `Gaussian / Volumetric` 已经从 `BuiltinForwardPipeline` 中抽成统一 `SceneRenderFeaturePass`。
|
||||||
|
- `FrameExecutionContext / ScenePhase / DrawSettings` 已经引入。
|
||||||
|
- `RenderPipeline` 已经支持新的 `FrameExecutionContext` 入口,旧三参数入口保留为兼容适配层。
|
||||||
|
- `BuiltinForwardPipeline` 已经开始按 scene phase 组织主场景执行。
|
||||||
|
- `CameraRenderer` 主场景阶段已经走新的 execution context,而不是继续只传三参数。
|
||||||
|
|
||||||
|
本轮验证结果:
|
||||||
|
|
||||||
|
- `XCEditor` 已重新编译通过。
|
||||||
|
- `rendering_unit_tests` 已重新编译通过。
|
||||||
|
- `editor_tests` 已重新编译通过。
|
||||||
|
- `editor_tests --gtest_filter=*ViewportRenderFlow*:*SceneViewportRenderPassBundle* --gtest_brief=1` 通过 `14/14`。
|
||||||
|
- `rendering_unit_tests --gtest_filter=*BuiltinForwardPipeline*:*RenderPass*:*CameraSceneRenderer*:*Shadow*:*ObjectId* --gtest_brief=1` 通过 `67/68`。
|
||||||
|
- 唯一失败仍然是既有老问题:
|
||||||
|
`BuiltinForwardPipeline_Test.OpenGLRuntimeTranspilesForwardShadowVariantToLegacyClipConventions`
|
||||||
|
|
||||||
|
## 3. 为什么现在还不能直接上 Render Graph
|
||||||
|
|
||||||
|
现在直接上 `Render Graph`,本质上是在 graph 里继续承接当前的隐式耦合,问题只会换个位置存在。
|
||||||
|
|
||||||
|
当前还没完全收口的核心问题不是“没有 graph”,而是下面这些边界还不够正式:
|
||||||
|
|
||||||
|
- `CameraRenderer` 和各类 scene pass 之间,谁负责组织阶段,谁负责执行,还没有完全模块化。
|
||||||
|
- `Shadow` 相关逻辑仍然分散在 planner、camera execution、pipeline、surface cache 几处。
|
||||||
|
- `BuiltinForwardPipeline` 虽然已经开始瘦身,但还没有彻底收成一个明确的 coordinator。
|
||||||
|
- `Editor` 的扩展点虽然已可用,但 contract 还偏“约定式”,还不够像以后给 `C# SRP` 暴露的正式接口。
|
||||||
|
- 目录结构仍然在暴露旧历史:一些“子系统”目前还是文件堆,不是真正的模块。
|
||||||
|
|
||||||
|
如果这些问题不先解决,`Render Graph` 只会变成一个新的承压层,后面再拆更贵。
|
||||||
|
|
||||||
|
## 4. Render Graph 和未来 SRP/URP 的边界
|
||||||
|
|
||||||
|
未来的推荐结构仍然是这条线:
|
||||||
|
|
||||||
|
`RHI -> Native Render Kernel -> Render Graph -> SRP-like Contract -> Universal Renderer -> C# Custom Pipeline`
|
||||||
|
|
||||||
|
其中边界应当明确成这样:
|
||||||
|
|
||||||
|
- `C++ native` 保留:
|
||||||
|
- `Render Graph`
|
||||||
|
- `CullingResults / RendererList`
|
||||||
|
- draw / dispatch context
|
||||||
|
- GPU resource cache
|
||||||
|
- shadow map / atlas 执行能力
|
||||||
|
- Gaussian 排序与 working set
|
||||||
|
- Volume 资源上传与底层执行
|
||||||
|
- `URP-like` 包层保留:
|
||||||
|
- feature 编排
|
||||||
|
- pass 注入顺序
|
||||||
|
- renderer feature 配置
|
||||||
|
- 用户级 pipeline 组合
|
||||||
|
- 未来的 `C#` 自定义渲染管线 API
|
||||||
|
|
||||||
|
这意味着:
|
||||||
|
|
||||||
|
- 阴影、Gaussian、Volumetric 不是整块搬去包层。
|
||||||
|
- 包层更像 Unity 的 `URP renderer` 和 `renderer feature`。
|
||||||
|
- native 层更像 Unity 没公开给用户、但真正负责执行和图资源生命周期的内核。
|
||||||
|
|
||||||
|
## 5. 第一阶段还差哪些工作才能收口
|
||||||
|
|
||||||
|
### 5.1 Shadow 子系统正式化
|
||||||
|
|
||||||
|
这是当前最值得先做的一块。
|
||||||
|
|
||||||
|
现状问题:
|
||||||
|
|
||||||
|
- 阴影规划在 `Planning`。
|
||||||
|
- 阴影 surface/cache 在 `Execution/Caches`。
|
||||||
|
- 阴影执行又是 standalone pass。
|
||||||
|
- 主场景采样阴影的状态切换仍在 `BuiltinForwardPipeline`。
|
||||||
|
|
||||||
|
这说明阴影现在“能跑”,但还不是一个正式子系统。
|
||||||
|
|
||||||
|
收口目标:
|
||||||
|
|
||||||
|
- 明确 `shadow planning / shadow resources / shadow execution / shadow sampling contract` 四层边界。
|
||||||
|
- 把方向光阴影相关共享数据收成一组正式类型,而不是散落在多个调用点上。
|
||||||
|
- 为以后扩展 `cascades / shadow atlas / additional light shadows / baked shadowmask` 留出位置。
|
||||||
|
|
||||||
|
### 5.2 Editor 注入点正式化
|
||||||
|
|
||||||
|
现状问题:
|
||||||
|
|
||||||
|
- 当前有 `pre scene / post scene / overlay / object id / outline / grid` 多种 editor 路径。
|
||||||
|
- 这些能力已经能工作,但还没有统一成“正式 stage 注入 contract”。
|
||||||
|
|
||||||
|
收口目标:
|
||||||
|
|
||||||
|
- 明确哪些注入点属于 runtime 正式阶段,哪些属于 editor-only extension。
|
||||||
|
- 让 `CameraFramePlan` 对这些阶段的描述更加稳定。
|
||||||
|
- 给以后 `C# renderer feature` 的注入点设计提供 native 对照物。
|
||||||
|
|
||||||
|
### 5.3 BuiltinForwardPipeline 继续瘦身
|
||||||
|
|
||||||
|
本轮已经完成第一刀,但还没收完。
|
||||||
|
|
||||||
|
还需要继续做的事情:
|
||||||
|
|
||||||
|
- 把 forward scene phase 执行和底层 draw/resource 逻辑彻底分开。
|
||||||
|
- 把 forward renderer 自己的内部资源、skybox、feature 协调代码进一步收拢。
|
||||||
|
- 保证 `BuiltinForwardPipeline` 自己只表达“阶段顺序和协调”,不再继续膨胀。
|
||||||
|
|
||||||
|
### 5.4 旧 fallback 的裁边
|
||||||
|
|
||||||
|
当前有一些过渡兼容层是故意保留的:
|
||||||
|
|
||||||
|
- `RenderPipeline::Render(context, surface, sceneData)` 旧入口
|
||||||
|
- `visibleItems` fallback
|
||||||
|
- `BuildRenderRequests` 旧习惯入口
|
||||||
|
|
||||||
|
这些现在不该硬删,因为会影响现有 tests 和 editor 链路。
|
||||||
|
|
||||||
|
但第一阶段收口前,至少要做到:
|
||||||
|
|
||||||
|
- 新主链默认只走正式 contract。
|
||||||
|
- 旧入口只作为 adapter,不再新增依赖。
|
||||||
|
- 每个 fallback 都有明确退出条件。
|
||||||
|
|
||||||
|
### 5.5 测试和文档补齐
|
||||||
|
|
||||||
|
当前已有回归还不够系统。
|
||||||
|
|
||||||
|
还需要补的重点测试:
|
||||||
|
|
||||||
|
- `FrameExecutionContext` 是否完整透传 source surface / source color view / state。
|
||||||
|
- `BuiltinForwardPipeline` scene phase 顺序是否稳定。
|
||||||
|
- feature pass 的 `Prepare -> Execute` 顺序是否稳定。
|
||||||
|
- editor 注入点在有后处理和无后处理两种情况下是否仍能保持正确 source/destination surface。
|
||||||
|
- shadow planning 和 main scene shadow sampling 之间的契约测试。
|
||||||
|
|
||||||
|
## 6. 下一步最优先该做什么
|
||||||
|
|
||||||
|
下一步最优先建议做:
|
||||||
|
|
||||||
|
`Shadow 子系统收口`
|
||||||
|
|
||||||
|
原因很直接:
|
||||||
|
|
||||||
|
- 它横跨 `Planning / Execution / Pipeline / Resources / Sampling`。
|
||||||
|
- 它是以后 `Deferred / Light Baking / ShadowMask / Additional Light Shadows` 的共同基础。
|
||||||
|
- 它也是未来 `Render Graph` 最敏感的一类资源依赖链。
|
||||||
|
- 如果阴影先不收,后面 graph 化时 barrier、resource lifetime、pass dependency 都会更乱。
|
||||||
|
|
||||||
|
建议顺序:
|
||||||
|
|
||||||
|
1. 先把方向光阴影的 plan/data/resource/execute contract 固化。
|
||||||
|
2. 再把 editor 注入 contract 固化。
|
||||||
|
3. 然后做第一轮目录收拢。
|
||||||
|
4. 最后判断这一阶段是否可以正式收口,进入 `Render Graph` 设计。
|
||||||
|
|
||||||
|
## 7. 当前 Rendering 目录结构存在的问题
|
||||||
|
|
||||||
|
### 7.1 `FrameData` 目录太杂
|
||||||
|
|
||||||
|
现在 `FrameData` 里同时混着:
|
||||||
|
|
||||||
|
- camera/environment 数据
|
||||||
|
- scene snapshot
|
||||||
|
- visible item
|
||||||
|
- culling results
|
||||||
|
- renderer list utils
|
||||||
|
|
||||||
|
这说明它不是一个明确模块,而是“跟帧有关的先放这”。
|
||||||
|
|
||||||
|
建议方向:
|
||||||
|
|
||||||
|
- `FrameData` 保留纯只读帧快照类型。
|
||||||
|
- 把 `CullingResults / RendererList / Filtering / Sorting / DrawSettings` 逐步收进更明确的 `Execution` 或 `Culling` 子域。
|
||||||
|
- `RendererListUtils` 这种执行辅助逻辑,不适合长期留在 `FrameData`。
|
||||||
|
|
||||||
|
### 7.2 `Passes` 目录混合了三类东西
|
||||||
|
|
||||||
|
现在 `Passes` 里同时有:
|
||||||
|
|
||||||
|
- 主场景 pass
|
||||||
|
- fullscreen/post-process pass
|
||||||
|
- editor pass
|
||||||
|
|
||||||
|
这会让“runtime 正式渲染能力”和“editor 辅助渲染能力”继续混在一起。
|
||||||
|
|
||||||
|
建议方向:
|
||||||
|
|
||||||
|
- `Passes/Scene`
|
||||||
|
- `Passes/Fullscreen`
|
||||||
|
- `Passes/Editor`
|
||||||
|
- `Passes/Shadow`
|
||||||
|
|
||||||
|
不一定要一次性全搬,但后面新增文件不应继续平铺。
|
||||||
|
|
||||||
|
### 7.3 `BuiltinForwardPipeline` 还没形成真正子模块
|
||||||
|
|
||||||
|
当前 forward 相关代码已经分散在:
|
||||||
|
|
||||||
|
- `BuiltinForwardPipeline.h/.cpp`
|
||||||
|
- `BuiltinForwardPipelineSkybox.cpp`
|
||||||
|
- `Internal/BuiltinForwardPipelineResources.cpp`
|
||||||
|
|
||||||
|
这已经具备“应该单独成目录”的条件。
|
||||||
|
|
||||||
|
建议方向:
|
||||||
|
|
||||||
|
- `Rendering/Pipelines/BuiltinForward/`
|
||||||
|
- `BuiltinForwardPipeline.h`
|
||||||
|
- `BuiltinForwardPipeline.cpp`
|
||||||
|
- `BuiltinForwardPipelineScene.cpp`
|
||||||
|
- `BuiltinForwardPipelineResources.cpp`
|
||||||
|
- `BuiltinForwardPipelineSkybox.cpp`
|
||||||
|
|
||||||
|
这样后面 forward / deferred / universal renderer 才能并列演进。
|
||||||
|
|
||||||
|
### 7.4 `Shadow` 目录还不算真正的 shadow 子系统
|
||||||
|
|
||||||
|
目前虽然已经有 `Rendering/Shadow`,但从全链路看,阴影的责任仍然散在其他目录。
|
||||||
|
|
||||||
|
建议方向:
|
||||||
|
|
||||||
|
- `Shadow` 目录最终至少容纳:
|
||||||
|
- planning types
|
||||||
|
- shared frame data
|
||||||
|
- runtime resources / caches
|
||||||
|
- shadow executor or shadow renderer
|
||||||
|
|
||||||
|
### 7.5 `Internal` 边界不稳定
|
||||||
|
|
||||||
|
现在 `src/Rendering/Internal` 更像历史遗留缓冲区。
|
||||||
|
|
||||||
|
长期风险:
|
||||||
|
|
||||||
|
- 真正属于 forward 的内部实现放在全局 `Internal`
|
||||||
|
- 真正属于 volume / splat / shadow 的内部实现也可能继续堆进去
|
||||||
|
|
||||||
|
建议方向:
|
||||||
|
|
||||||
|
- 全局 `Internal` 只保留跨模块公共 helper。
|
||||||
|
- 各子系统自己的内部文件放回各自目录。
|
||||||
|
|
||||||
|
## 8. 建议的第一轮目录收拢动作
|
||||||
|
|
||||||
|
这一轮只做低风险收拢,不做大搬家。
|
||||||
|
|
||||||
|
建议动作:
|
||||||
|
|
||||||
|
- 把 `BuiltinForwardPipeline*` 相关实现收成 `Pipelines/BuiltinForward/` 子目录。
|
||||||
|
- 给 `Passes` 至少先分出 `Editor` 和 `Fullscreen` 两个子目录。
|
||||||
|
- 给 `Shadow` 补一组正式 shared types,再决定是否移动更多实现文件。
|
||||||
|
- 暂时不大动 `include` 层 public 路径,先保证编译和引用稳定。
|
||||||
|
|
||||||
|
原则:
|
||||||
|
|
||||||
|
- 先按职责拆,再按目录搬。
|
||||||
|
- 不为了“好看”做纯目录手术。
|
||||||
|
- 每次收拢都必须带编译和回归。
|
||||||
|
|
||||||
|
## 9. 第一阶段收口完成的判定标准
|
||||||
|
|
||||||
|
满足下面这些条件,就可以认为 `Render Graph` 之前这一阶段基本收口:
|
||||||
|
|
||||||
|
- `CameraFramePlan` 成为主执行入口,旧 request 入口只保留兼容壳。
|
||||||
|
- `FrameExecutionContext / ScenePhase / DrawSettings` 成为主场景执行正式 contract。
|
||||||
|
- `CullingResults / RendererList` 成为主要 draw organization contract。
|
||||||
|
- `BuiltinForwardPipeline` 被收成 coordinator,而不是继续长成总垃圾堆。
|
||||||
|
- `Shadow` 成为清晰子系统,而不是散点逻辑。
|
||||||
|
- `Editor` 注入点形成稳定 contract。
|
||||||
|
- 目录结构不再继续鼓励“新逻辑直接往老文件里塞”。
|
||||||
|
- 相关 tests 和编译链稳定。
|
||||||
|
|
||||||
|
到这一步,再开始 `C++ Render Graph`,代价才是可控的。
|
||||||
|
|
||||||
|
## 10. 当前建议
|
||||||
|
|
||||||
|
当前最佳路线不变:
|
||||||
|
|
||||||
|
- 短期:继续按 Unity 的 `SRP + URP` 方向做 native 基座。
|
||||||
|
- 中期:先在 `C++` 做出稳定的 `Render Graph + RendererList + Feature Injection` 内核。
|
||||||
|
- 中长期:再暴露 `C#` 自定义渲染管线接口,做你自己的 `URP-like` 包层。
|
||||||
|
|
||||||
|
眼下最正确的动作不是“赶紧补 deferred”,也不是“先把所有特效搬去包层”,而是:
|
||||||
|
|
||||||
|
`先把当前 native rendering layer 整理成一个真正可扩展的内核。`
|
||||||
179
engine/include/XCEngine/Rendering/Execution/CameraFramePlan.h
Normal file
179
engine/include/XCEngine/Rendering/Execution/CameraFramePlan.h
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Planning/CameraRenderRequest.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
struct CameraFramePlan {
|
||||||
|
CameraRenderRequest request = {};
|
||||||
|
ShadowCasterRenderRequest shadowCaster = {};
|
||||||
|
DirectionalShadowRenderPlan directionalShadow = {};
|
||||||
|
PostProcessRenderRequest postProcess = {};
|
||||||
|
FinalOutputRenderRequest finalOutput = {};
|
||||||
|
ResolvedFinalColorPolicy finalColorPolicy = {};
|
||||||
|
RenderPassSequence* preScenePasses = nullptr;
|
||||||
|
RenderPassSequence* postScenePasses = nullptr;
|
||||||
|
RenderPassSequence* overlayPasses = nullptr;
|
||||||
|
|
||||||
|
static CameraFramePlan FromRequest(const CameraRenderRequest& request) {
|
||||||
|
CameraFramePlan plan = {};
|
||||||
|
plan.request = request;
|
||||||
|
plan.shadowCaster = request.shadowCaster;
|
||||||
|
plan.directionalShadow = request.directionalShadow;
|
||||||
|
plan.postProcess = request.postProcess;
|
||||||
|
plan.finalOutput = request.finalOutput;
|
||||||
|
plan.finalColorPolicy = request.finalColorPolicy;
|
||||||
|
plan.preScenePasses = request.preScenePasses;
|
||||||
|
plan.postScenePasses = request.postScenePasses;
|
||||||
|
plan.overlayPasses = request.overlayPasses;
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() const {
|
||||||
|
return request.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasFrameStage(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PreScenePasses:
|
||||||
|
return preScenePasses != nullptr;
|
||||||
|
case CameraFrameStage::ShadowCaster:
|
||||||
|
return shadowCaster.IsRequested() || directionalShadow.IsValid();
|
||||||
|
case CameraFrameStage::DepthOnly:
|
||||||
|
return request.depthOnly.IsRequested();
|
||||||
|
case CameraFrameStage::MainScene:
|
||||||
|
return true;
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.IsRequested();
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.IsRequested();
|
||||||
|
case CameraFrameStage::ObjectId:
|
||||||
|
return request.objectId.IsRequested();
|
||||||
|
case CameraFrameStage::PostScenePasses:
|
||||||
|
return postScenePasses != nullptr;
|
||||||
|
case CameraFrameStage::OverlayPasses:
|
||||||
|
return overlayPasses != nullptr;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderPassSequence* GetPassSequence(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PreScenePasses:
|
||||||
|
return preScenePasses;
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.passes;
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.passes;
|
||||||
|
case CameraFrameStage::PostScenePasses:
|
||||||
|
return postScenePasses;
|
||||||
|
case CameraFrameStage::OverlayPasses:
|
||||||
|
return overlayPasses;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RenderSurface& GetMainSceneSurface() const {
|
||||||
|
if (postProcess.IsRequested()) {
|
||||||
|
return postProcess.sourceSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalOutput.IsRequested()) {
|
||||||
|
return finalOutput.sourceSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RenderSurface& GetFinalCompositedSurface() const {
|
||||||
|
if (finalOutput.IsRequested()) {
|
||||||
|
return finalOutput.destinationSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postProcess.IsRequested()) {
|
||||||
|
return postProcess.destinationSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RenderSurface* GetOutputSurface(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PreScenePasses:
|
||||||
|
case CameraFrameStage::MainScene:
|
||||||
|
return &GetMainSceneSurface();
|
||||||
|
case CameraFrameStage::ShadowCaster:
|
||||||
|
return shadowCaster.IsRequested() ? &shadowCaster.surface : nullptr;
|
||||||
|
case CameraFrameStage::DepthOnly:
|
||||||
|
return request.depthOnly.IsRequested() ? &request.depthOnly.surface : nullptr;
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.IsRequested() ? &postProcess.destinationSurface : nullptr;
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.IsRequested() ? &finalOutput.destinationSurface : nullptr;
|
||||||
|
case CameraFrameStage::ObjectId:
|
||||||
|
return request.objectId.IsRequested() ? &request.objectId.surface : nullptr;
|
||||||
|
case CameraFrameStage::PostScenePasses:
|
||||||
|
case CameraFrameStage::OverlayPasses:
|
||||||
|
return &GetFinalCompositedSurface();
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RenderSurface* GetSourceSurface(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.IsRequested() ? &postProcess.sourceSurface : nullptr;
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.IsRequested() ? &finalOutput.sourceSurface : nullptr;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RHI::RHIResourceView* GetSourceColorView(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.IsRequested() ? postProcess.sourceColorView : nullptr;
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.IsRequested() ? finalOutput.sourceColorView : nullptr;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RHI::ResourceStates GetSourceColorState(CameraFrameStage stage) const {
|
||||||
|
switch (stage) {
|
||||||
|
case CameraFrameStage::PostProcess:
|
||||||
|
return postProcess.IsRequested() ? postProcess.sourceColorState : RHI::ResourceStates::Common;
|
||||||
|
case CameraFrameStage::FinalOutput:
|
||||||
|
return finalOutput.IsRequested() ? finalOutput.sourceColorState : RHI::ResourceStates::Common;
|
||||||
|
default:
|
||||||
|
return RHI::ResourceStates::Common;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RequiresIntermediateSceneColor() const {
|
||||||
|
return postProcess.IsRequested() || finalOutput.IsRequested();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline CameraRenderRequest BuildLegacyCameraRenderRequest(
|
||||||
|
const CameraFramePlan& plan) {
|
||||||
|
CameraRenderRequest request = plan.request;
|
||||||
|
request.shadowCaster = plan.shadowCaster;
|
||||||
|
request.directionalShadow = plan.directionalShadow;
|
||||||
|
request.postProcess = plan.postProcess;
|
||||||
|
request.finalOutput = plan.finalOutput;
|
||||||
|
request.finalColorPolicy = plan.finalColorPolicy;
|
||||||
|
request.preScenePasses = plan.preScenePasses;
|
||||||
|
request.postScenePasses = plan.postScenePasses;
|
||||||
|
request.overlayPasses = plan.overlayPasses;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/CameraFramePlan.h>
|
||||||
#include <XCEngine/Rendering/Extraction/RenderSceneExtractor.h>
|
#include <XCEngine/Rendering/Extraction/RenderSceneExtractor.h>
|
||||||
#include <XCEngine/Rendering/Planning/CameraRenderRequest.h>
|
#include <XCEngine/Rendering/Planning/CameraRenderRequest.h>
|
||||||
#include <XCEngine/Rendering/RenderPass.h>
|
#include <XCEngine/Rendering/RenderPass.h>
|
||||||
@@ -49,19 +50,20 @@ public:
|
|||||||
RenderPass* GetShadowCasterPass() const { return m_shadowCasterPass.get(); }
|
RenderPass* GetShadowCasterPass() const { return m_shadowCasterPass.get(); }
|
||||||
|
|
||||||
bool Render(const CameraRenderRequest& request);
|
bool Render(const CameraRenderRequest& request);
|
||||||
|
bool Render(const CameraFramePlan& plan);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ResetPipeline(std::unique_ptr<RenderPipeline> pipeline);
|
void ResetPipeline(std::unique_ptr<RenderPipeline> pipeline);
|
||||||
bool ResolveShadowCasterRequest(
|
bool ResolveShadowCasterRequest(
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
ShadowCasterRenderRequest& outResolvedShadowCaster,
|
ShadowCasterRenderRequest& outResolvedShadowCaster,
|
||||||
RHI::RHIResourceView*& outShadowMapView);
|
RHI::RHIResourceView*& outShadowMapView);
|
||||||
bool BuildSceneDataForRequest(
|
bool BuildSceneDataForPlan(
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
RHI::RHIResourceView* shadowMapView,
|
RHI::RHIResourceView* shadowMapView,
|
||||||
RenderSceneData& outSceneData);
|
RenderSceneData& outSceneData);
|
||||||
bool ExecuteRenderPlan(
|
bool ExecuteRenderPlan(
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
||||||
const RenderSceneData& sceneData);
|
const RenderSceneData& sceneData);
|
||||||
|
|
||||||
|
|||||||
15
engine/include/XCEngine/Rendering/Execution/DrawSettings.h
Normal file
15
engine/include/XCEngine/Rendering/Execution/DrawSettings.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/ScenePhase.h>
|
||||||
|
#include <XCEngine/Rendering/FrameData/CullingResults.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
struct DrawSettings {
|
||||||
|
ScenePhase scenePhase = ScenePhase::Opaque;
|
||||||
|
RendererListType rendererListType = RendererListType::AllVisible;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/ScenePhase.h>
|
||||||
|
#include <XCEngine/Rendering/RenderContext.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace RHI {
|
||||||
|
class RHIResourceView;
|
||||||
|
} // namespace RHI
|
||||||
|
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
struct RenderSceneData;
|
||||||
|
class RenderSurface;
|
||||||
|
|
||||||
|
struct FrameExecutionContext {
|
||||||
|
FrameExecutionContext(
|
||||||
|
const RenderContext& inRenderContext,
|
||||||
|
const RenderSurface& inSurface,
|
||||||
|
const RenderSceneData& inSceneData,
|
||||||
|
const RenderSurface* inSourceSurface = nullptr,
|
||||||
|
RHI::RHIResourceView* inSourceColorView = nullptr,
|
||||||
|
RHI::ResourceStates inSourceColorState = RHI::ResourceStates::Common)
|
||||||
|
: renderContext(inRenderContext)
|
||||||
|
, surface(inSurface)
|
||||||
|
, sceneData(inSceneData)
|
||||||
|
, sourceSurface(inSourceSurface)
|
||||||
|
, sourceColorView(inSourceColorView)
|
||||||
|
, sourceColorState(inSourceColorState) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const RenderContext& renderContext;
|
||||||
|
const RenderSurface& surface;
|
||||||
|
const RenderSceneData& sceneData;
|
||||||
|
const RenderSurface* sourceSurface = nullptr;
|
||||||
|
RHI::RHIResourceView* sourceColorView = nullptr;
|
||||||
|
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScenePhaseExecutionContext {
|
||||||
|
ScenePhaseExecutionContext(
|
||||||
|
const FrameExecutionContext& inFrameContext,
|
||||||
|
ScenePhase inScenePhase,
|
||||||
|
bool inSampledDirectionalShadow = false)
|
||||||
|
: frameContext(inFrameContext)
|
||||||
|
, scenePhase(inScenePhase)
|
||||||
|
, sampledDirectionalShadow(inSampledDirectionalShadow) {
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameExecutionContext frameContext;
|
||||||
|
ScenePhase scenePhase = ScenePhase::Opaque;
|
||||||
|
bool sampledDirectionalShadow = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
40
engine/include/XCEngine/Rendering/Execution/ScenePhase.h
Normal file
40
engine/include/XCEngine/Rendering/Execution/ScenePhase.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Core/Types.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
enum class ScenePhase : Core::uint32 {
|
||||||
|
Opaque = 0,
|
||||||
|
Skybox = 1,
|
||||||
|
Feature = 2,
|
||||||
|
Transparent = 3,
|
||||||
|
EditorExtension = 4,
|
||||||
|
PostProcess = 5,
|
||||||
|
FinalOutput = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* ToString(ScenePhase scenePhase) {
|
||||||
|
switch (scenePhase) {
|
||||||
|
case ScenePhase::Opaque:
|
||||||
|
return "Opaque";
|
||||||
|
case ScenePhase::Skybox:
|
||||||
|
return "Skybox";
|
||||||
|
case ScenePhase::Feature:
|
||||||
|
return "Feature";
|
||||||
|
case ScenePhase::Transparent:
|
||||||
|
return "Transparent";
|
||||||
|
case ScenePhase::EditorExtension:
|
||||||
|
return "EditorExtension";
|
||||||
|
case ScenePhase::PostProcess:
|
||||||
|
return "PostProcess";
|
||||||
|
case ScenePhase::FinalOutput:
|
||||||
|
return "FinalOutput";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/CameraFramePlan.h>
|
||||||
#include <XCEngine/Rendering/Execution/CameraRenderer.h>
|
#include <XCEngine/Rendering/Execution/CameraRenderer.h>
|
||||||
#include <XCEngine/Rendering/Planning/CameraRenderRequest.h>
|
#include <XCEngine/Rendering/Planning/CameraRenderRequest.h>
|
||||||
#include <XCEngine/Rendering/Planning/SceneRenderRequestPlanner.h>
|
#include <XCEngine/Rendering/Planning/SceneRenderRequestPlanner.h>
|
||||||
@@ -35,9 +36,16 @@ public:
|
|||||||
Components::CameraComponent* overrideCamera,
|
Components::CameraComponent* overrideCamera,
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSurface& surface);
|
const RenderSurface& surface);
|
||||||
|
std::vector<CameraFramePlan> BuildFramePlans(
|
||||||
|
const Components::Scene& scene,
|
||||||
|
Components::CameraComponent* overrideCamera,
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSurface& surface);
|
||||||
|
|
||||||
bool Render(const CameraRenderRequest& request);
|
bool Render(const CameraRenderRequest& request);
|
||||||
bool Render(const std::vector<CameraRenderRequest>& requests);
|
bool Render(const std::vector<CameraRenderRequest>& requests);
|
||||||
|
bool Render(const CameraFramePlan& plan);
|
||||||
|
bool Render(const std::vector<CameraFramePlan>& plans);
|
||||||
bool Render(
|
bool Render(
|
||||||
const Components::Scene& scene,
|
const Components::Scene& scene,
|
||||||
Components::CameraComponent* overrideCamera,
|
Components::CameraComponent* overrideCamera,
|
||||||
@@ -45,12 +53,14 @@ public:
|
|||||||
const RenderSurface& surface);
|
const RenderSurface& surface);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::vector<CameraFramePlan> CreateFramePlansFromRequests(
|
||||||
|
const std::vector<CameraRenderRequest>& requests) const;
|
||||||
void PrepareOwnedFullscreenStageState(size_t requestCount);
|
void PrepareOwnedFullscreenStageState(size_t requestCount);
|
||||||
void ResolveCameraFinalColorPolicies(
|
void ResolveCameraFinalColorPolicies(
|
||||||
std::vector<CameraRenderRequest>& requests) const;
|
std::vector<CameraFramePlan>& plans) const;
|
||||||
void AttachFullscreenStageRequests(
|
void AttachFullscreenStageRequests(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
std::vector<CameraRenderRequest>& requests);
|
std::vector<CameraFramePlan>& plans);
|
||||||
|
|
||||||
SceneRenderRequestPlanner m_requestPlanner;
|
SceneRenderRequestPlanner m_requestPlanner;
|
||||||
CameraRenderer m_cameraRenderer;
|
CameraRenderer m_cameraRenderer;
|
||||||
|
|||||||
85
engine/include/XCEngine/Rendering/FrameData/CullingResults.h
Normal file
85
engine/include/XCEngine/Rendering/FrameData/CullingResults.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Core/Types.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
enum class RendererListType : Core::uint32 {
|
||||||
|
AllVisible = 0,
|
||||||
|
Opaque = 1,
|
||||||
|
Transparent = 2,
|
||||||
|
ShadowCaster = 3,
|
||||||
|
ObjectId = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class RendererSortMode : Core::uint32 {
|
||||||
|
None = 0,
|
||||||
|
FrontToBack = 1,
|
||||||
|
BackToFront = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FilteringSettings {
|
||||||
|
Core::int32 renderQueueMin = std::numeric_limits<Core::int32>::lowest();
|
||||||
|
Core::int32 renderQueueMax = std::numeric_limits<Core::int32>::max();
|
||||||
|
bool requireShadowCasting = false;
|
||||||
|
bool requireRenderObjectId = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SortingSettings {
|
||||||
|
RendererSortMode sortMode = RendererSortMode::None;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RendererListDesc {
|
||||||
|
RendererListType type = RendererListType::AllVisible;
|
||||||
|
FilteringSettings filtering = {};
|
||||||
|
SortingSettings sorting = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RendererList {
|
||||||
|
RendererListDesc desc = {};
|
||||||
|
std::vector<Core::uint32> visibleRenderItemIndices;
|
||||||
|
|
||||||
|
bool Empty() const {
|
||||||
|
return visibleRenderItemIndices.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Size() const {
|
||||||
|
return visibleRenderItemIndices.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CullingResults {
|
||||||
|
std::vector<RendererList> rendererLists;
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
rendererLists.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
RendererList* FindRendererList(RendererListType type) {
|
||||||
|
for (RendererList& rendererList : rendererLists) {
|
||||||
|
if (rendererList.desc.type == type) {
|
||||||
|
return &rendererList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RendererList* FindRendererList(RendererListType type) const {
|
||||||
|
for (const RendererList& rendererList : rendererLists) {
|
||||||
|
if (rendererList.desc.type == type) {
|
||||||
|
return &rendererList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <XCEngine/Core/Math/Vector2.h>
|
#include <XCEngine/Core/Math/Vector2.h>
|
||||||
#include <XCEngine/Core/Math/Vector3.h>
|
#include <XCEngine/Core/Math/Vector3.h>
|
||||||
#include <XCEngine/Core/Math/Vector4.h>
|
#include <XCEngine/Core/Math/Vector4.h>
|
||||||
|
#include <XCEngine/Rendering/FrameData/CullingResults.h>
|
||||||
#include <XCEngine/Rendering/FrameData/RenderCameraData.h>
|
#include <XCEngine/Rendering/FrameData/RenderCameraData.h>
|
||||||
#include <XCEngine/Rendering/FrameData/RenderEnvironmentData.h>
|
#include <XCEngine/Rendering/FrameData/RenderEnvironmentData.h>
|
||||||
#include <XCEngine/Rendering/Shadow/DirectionalShadowSettings.h>
|
#include <XCEngine/Rendering/Shadow/DirectionalShadowSettings.h>
|
||||||
@@ -115,6 +116,7 @@ struct RenderSceneData {
|
|||||||
RenderEnvironmentData environment;
|
RenderEnvironmentData environment;
|
||||||
RenderLightingData lighting;
|
RenderLightingData lighting;
|
||||||
Resources::ShaderKeywordSet globalShaderKeywords;
|
Resources::ShaderKeywordSet globalShaderKeywords;
|
||||||
|
CullingResults cullingResults;
|
||||||
std::vector<VisibleRenderItem> visibleItems;
|
std::vector<VisibleRenderItem> visibleItems;
|
||||||
std::vector<VisibleGaussianSplatItem> visibleGaussianSplats;
|
std::vector<VisibleGaussianSplatItem> visibleGaussianSplats;
|
||||||
std::vector<VisibleVolumeItem> visibleVolumes;
|
std::vector<VisibleVolumeItem> visibleVolumes;
|
||||||
@@ -122,6 +124,22 @@ struct RenderSceneData {
|
|||||||
bool HasCamera() const {
|
bool HasCamera() const {
|
||||||
return camera != nullptr;
|
return camera != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RendererList* FindRendererList(RendererListType type) {
|
||||||
|
return cullingResults.FindRendererList(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const RendererList* FindRendererList(RendererListType type) const {
|
||||||
|
return cullingResults.FindRendererList(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const VisibleRenderItem* TryGetVisibleRenderItem(Core::uint32 index) const {
|
||||||
|
if (index >= visibleItems.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &visibleItems[index];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Rendering
|
} // namespace Rendering
|
||||||
|
|||||||
145
engine/include/XCEngine/Rendering/FrameData/RendererListUtils.h
Normal file
145
engine/include/XCEngine/Rendering/FrameData/RendererListUtils.h
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Components/MeshRendererComponent.h>
|
||||||
|
#include <XCEngine/Rendering/FrameData/RenderSceneData.h>
|
||||||
|
#include <XCEngine/Resources/Material/Material.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
inline FilteringSettings BuildDefaultFilteringSettings(RendererListType type) {
|
||||||
|
FilteringSettings filtering = {};
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RendererListType::AllVisible:
|
||||||
|
break;
|
||||||
|
case RendererListType::Opaque:
|
||||||
|
filtering.renderQueueMax =
|
||||||
|
static_cast<Core::int32>(Resources::MaterialRenderQueue::Transparent) - 1;
|
||||||
|
break;
|
||||||
|
case RendererListType::Transparent:
|
||||||
|
filtering.renderQueueMin =
|
||||||
|
static_cast<Core::int32>(Resources::MaterialRenderQueue::Transparent);
|
||||||
|
break;
|
||||||
|
case RendererListType::ShadowCaster:
|
||||||
|
filtering.requireShadowCasting = true;
|
||||||
|
break;
|
||||||
|
case RendererListType::ObjectId:
|
||||||
|
filtering.requireRenderObjectId = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtering;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SortingSettings BuildDefaultSortingSettings(RendererListType type) {
|
||||||
|
SortingSettings sorting = {};
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RendererListType::Opaque:
|
||||||
|
case RendererListType::ShadowCaster:
|
||||||
|
case RendererListType::ObjectId:
|
||||||
|
sorting.sortMode = RendererSortMode::FrontToBack;
|
||||||
|
break;
|
||||||
|
case RendererListType::Transparent:
|
||||||
|
sorting.sortMode = RendererSortMode::BackToFront;
|
||||||
|
break;
|
||||||
|
case RendererListType::AllVisible:
|
||||||
|
sorting.sortMode = RendererSortMode::None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorting;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RendererListDesc BuildDefaultRendererListDesc(RendererListType type) {
|
||||||
|
RendererListDesc desc = {};
|
||||||
|
desc.type = type;
|
||||||
|
desc.filtering = BuildDefaultFilteringSettings(type);
|
||||||
|
desc.sorting = BuildDefaultSortingSettings(type);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool MatchesFilteringSettings(
|
||||||
|
const VisibleRenderItem& visibleItem,
|
||||||
|
const FilteringSettings& filtering) {
|
||||||
|
if (visibleItem.renderQueue < filtering.renderQueueMin ||
|
||||||
|
visibleItem.renderQueue > filtering.renderQueueMax) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filtering.requireShadowCasting &&
|
||||||
|
visibleItem.meshRenderer != nullptr &&
|
||||||
|
!visibleItem.meshRenderer->GetCastShadows()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filtering.requireRenderObjectId &&
|
||||||
|
!IsValidRenderObjectId(visibleItem.renderObjectId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool MatchesRendererListDesc(
|
||||||
|
const VisibleRenderItem& visibleItem,
|
||||||
|
const RendererListDesc& desc) {
|
||||||
|
return MatchesFilteringSettings(visibleItem, desc.filtering);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RendererList BuildRendererList(
|
||||||
|
RendererListType type,
|
||||||
|
const std::vector<VisibleRenderItem>& visibleItems) {
|
||||||
|
RendererList rendererList = {};
|
||||||
|
rendererList.desc = BuildDefaultRendererListDesc(type);
|
||||||
|
rendererList.visibleRenderItemIndices.reserve(visibleItems.size());
|
||||||
|
|
||||||
|
for (Core::uint32 visibleItemIndex = 0;
|
||||||
|
visibleItemIndex < static_cast<Core::uint32>(visibleItems.size());
|
||||||
|
++visibleItemIndex) {
|
||||||
|
if (!MatchesRendererListDesc(
|
||||||
|
visibleItems[visibleItemIndex],
|
||||||
|
rendererList.desc)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rendererList.visibleRenderItemIndices.push_back(visibleItemIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rendererList;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
inline void VisitRendererListVisibleItems(
|
||||||
|
const RenderSceneData& sceneData,
|
||||||
|
RendererListType rendererListType,
|
||||||
|
Visitor&& visitor) {
|
||||||
|
const RendererList* rendererList = sceneData.FindRendererList(rendererListType);
|
||||||
|
if (rendererList != nullptr) {
|
||||||
|
for (Core::uint32 visibleItemIndex : rendererList->visibleRenderItemIndices) {
|
||||||
|
const VisibleRenderItem* visibleItem =
|
||||||
|
sceneData.TryGetVisibleRenderItem(visibleItemIndex);
|
||||||
|
if (visibleItem == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitor(*visibleItem);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RendererListDesc fallbackDesc = BuildDefaultRendererListDesc(rendererListType);
|
||||||
|
for (const VisibleRenderItem& visibleItem : sceneData.visibleItems) {
|
||||||
|
if (!MatchesRendererListDesc(visibleItem, fallbackDesc)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitor(visibleItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <XCEngine/Core/Asset/ResourceHandle.h>
|
#include <XCEngine/Core/Asset/ResourceHandle.h>
|
||||||
#include <XCEngine/Core/Math/Matrix4.h>
|
#include <XCEngine/Core/Math/Matrix4.h>
|
||||||
#include <XCEngine/Rendering/Builtin/BuiltinPassTypes.h>
|
#include <XCEngine/Rendering/Builtin/BuiltinPassTypes.h>
|
||||||
|
#include <XCEngine/Rendering/FrameData/CullingResults.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
||||||
#include <XCEngine/Rendering/RenderPass.h>
|
#include <XCEngine/Rendering/RenderPass.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
||||||
@@ -46,6 +47,7 @@ protected:
|
|||||||
BuiltinMaterialPass passType,
|
BuiltinMaterialPass passType,
|
||||||
Containers::String builtinShaderPath);
|
Containers::String builtinShaderPath);
|
||||||
|
|
||||||
|
virtual RendererListType GetRendererListType() const;
|
||||||
virtual bool ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const;
|
virtual bool ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <XCEngine/Rendering/Caches/RenderResourceCache.h>
|
#include <XCEngine/Rendering/Caches/RenderResourceCache.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
||||||
#include <XCEngine/Rendering/RenderPass.h>
|
#include <XCEngine/Rendering/SceneRenderFeaturePass.h>
|
||||||
#include <XCEngine/RHI/RHIDescriptorPool.h>
|
#include <XCEngine/RHI/RHIDescriptorPool.h>
|
||||||
#include <XCEngine/RHI/RHIDescriptorSet.h>
|
#include <XCEngine/RHI/RHIDescriptorSet.h>
|
||||||
#include <XCEngine/RHI/RHIPipelineLayout.h>
|
#include <XCEngine/RHI/RHIPipelineLayout.h>
|
||||||
@@ -40,12 +40,16 @@ class BuiltinGaussianSplatPassResources;
|
|||||||
|
|
||||||
namespace Passes {
|
namespace Passes {
|
||||||
|
|
||||||
class BuiltinGaussianSplatPass final : public RenderPass {
|
class BuiltinGaussianSplatPass final : public SceneRenderFeaturePass {
|
||||||
public:
|
public:
|
||||||
~BuiltinGaussianSplatPass() override;
|
~BuiltinGaussianSplatPass() override;
|
||||||
|
|
||||||
const char* GetName() const override;
|
const char* GetName() const override;
|
||||||
bool Initialize(const RenderContext& context) override;
|
bool Initialize(const RenderContext& context) override;
|
||||||
|
bool IsActive(const RenderSceneData& sceneData) const override;
|
||||||
|
bool Prepare(
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSceneData& sceneData) override;
|
||||||
bool PrepareGaussianSplatResources(
|
bool PrepareGaussianSplatResources(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSceneData& sceneData);
|
const RenderSceneData& sceneData);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public:
|
|||||||
const char* GetName() const override;
|
const char* GetName() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
RendererListType GetRendererListType() const override;
|
||||||
bool ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const override;
|
bool ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <XCEngine/Rendering/Caches/RenderResourceCache.h>
|
#include <XCEngine/Rendering/Caches/RenderResourceCache.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
||||||
#include <XCEngine/Rendering/RenderPass.h>
|
#include <XCEngine/Rendering/SceneRenderFeaturePass.h>
|
||||||
#include <XCEngine/RHI/RHIDescriptorPool.h>
|
#include <XCEngine/RHI/RHIDescriptorPool.h>
|
||||||
#include <XCEngine/RHI/RHIDescriptorSet.h>
|
#include <XCEngine/RHI/RHIDescriptorSet.h>
|
||||||
#include <XCEngine/RHI/RHIPipelineLayout.h>
|
#include <XCEngine/RHI/RHIPipelineLayout.h>
|
||||||
@@ -33,7 +33,7 @@ struct RenderLightingData;
|
|||||||
|
|
||||||
namespace Passes {
|
namespace Passes {
|
||||||
|
|
||||||
class BuiltinVolumetricPass final : public RenderPass {
|
class BuiltinVolumetricPass final : public SceneRenderFeaturePass {
|
||||||
public:
|
public:
|
||||||
~BuiltinVolumetricPass() override;
|
~BuiltinVolumetricPass() override;
|
||||||
|
|
||||||
@@ -41,6 +41,10 @@ public:
|
|||||||
|
|
||||||
const char* GetName() const override;
|
const char* GetName() const override;
|
||||||
bool Initialize(const RenderContext& context) override;
|
bool Initialize(const RenderContext& context) override;
|
||||||
|
bool IsActive(const RenderSceneData& sceneData) const override;
|
||||||
|
bool Prepare(
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSceneData& sceneData) override;
|
||||||
bool PrepareVolumeResources(
|
bool PrepareVolumeResources(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSceneData& sceneData);
|
const RenderSceneData& sceneData);
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/DrawSettings.h>
|
||||||
|
#include <XCEngine/Rendering/Execution/FrameExecutionContext.h>
|
||||||
#include <XCEngine/Rendering/Builtin/BuiltinPassTypes.h>
|
#include <XCEngine/Rendering/Builtin/BuiltinPassTypes.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialResolve.h>
|
||||||
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
#include <XCEngine/Rendering/Materials/RenderMaterialStateUtils.h>
|
||||||
#include <XCEngine/Rendering/RenderPass.h>
|
#include <XCEngine/Rendering/RenderPass.h>
|
||||||
#include <XCEngine/Rendering/RenderPipeline.h>
|
#include <XCEngine/Rendering/RenderPipeline.h>
|
||||||
#include <XCEngine/Rendering/RenderPipelineAsset.h>
|
#include <XCEngine/Rendering/RenderPipelineAsset.h>
|
||||||
|
#include <XCEngine/Rendering/SceneRenderFeaturePass.h>
|
||||||
#include <XCEngine/Rendering/Caches/RenderResourceCache.h>
|
#include <XCEngine/Rendering/Caches/RenderResourceCache.h>
|
||||||
|
|
||||||
#include <XCEngine/RHI/RHIDescriptorPool.h>
|
#include <XCEngine/RHI/RHIDescriptorPool.h>
|
||||||
@@ -50,16 +53,21 @@ public:
|
|||||||
BuiltinForwardPipeline();
|
BuiltinForwardPipeline();
|
||||||
~BuiltinForwardPipeline() override;
|
~BuiltinForwardPipeline() override;
|
||||||
|
|
||||||
|
using RenderPipeline::Render;
|
||||||
|
|
||||||
static RHI::InputLayoutDesc BuildInputLayout();
|
static RHI::InputLayoutDesc BuildInputLayout();
|
||||||
|
|
||||||
bool Initialize(const RenderContext& context) override;
|
bool Initialize(const RenderContext& context) override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
bool Render(const FrameExecutionContext& executionContext) override;
|
||||||
bool Render(
|
bool Render(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSurface& surface,
|
const RenderSurface& surface,
|
||||||
const RenderSceneData& sceneData) override;
|
const RenderSceneData& sceneData) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using ForwardSceneFeaturePassArray = std::array<SceneRenderFeaturePass*, 2>;
|
||||||
|
|
||||||
struct OwnedDescriptorSet {
|
struct OwnedDescriptorSet {
|
||||||
RHI::RHIDescriptorPool* pool = nullptr;
|
RHI::RHIDescriptorPool* pool = nullptr;
|
||||||
RHI::RHIDescriptorSet* set = nullptr;
|
RHI::RHIDescriptorSet* set = nullptr;
|
||||||
@@ -263,6 +271,19 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool EnsureInitialized(const RenderContext& context);
|
bool EnsureInitialized(const RenderContext& context);
|
||||||
|
ForwardSceneFeaturePassArray CollectForwardSceneFeaturePasses() const;
|
||||||
|
bool InitializeForwardSceneFeaturePasses(const RenderContext& context);
|
||||||
|
void ShutdownForwardSceneFeaturePasses();
|
||||||
|
bool PrepareForwardSceneFeaturePasses(
|
||||||
|
const FrameExecutionContext& executionContext) const;
|
||||||
|
bool ExecuteForwardSceneFeaturePasses(
|
||||||
|
const ScenePhaseExecutionContext& executionContext) const;
|
||||||
|
ScenePhaseExecutionContext BuildScenePhaseExecutionContext(
|
||||||
|
const FrameExecutionContext& executionContext,
|
||||||
|
ScenePhase scenePhase) const;
|
||||||
|
DrawSettings BuildDrawSettings(ScenePhase scenePhase) const;
|
||||||
|
bool ExecuteForwardScene(const FrameExecutionContext& executionContext);
|
||||||
|
bool ExecuteScenePhase(const ScenePhaseExecutionContext& executionContext);
|
||||||
bool CreatePipelineResources(const RenderContext& context);
|
bool CreatePipelineResources(const RenderContext& context);
|
||||||
void DestroyPipelineResources();
|
void DestroyPipelineResources();
|
||||||
static bool TryResolveSurfacePassType(
|
static bool TryResolveSurfacePassType(
|
||||||
@@ -315,18 +336,14 @@ private:
|
|||||||
bool HasProceduralSkybox(const RenderSceneData& sceneData) const;
|
bool HasProceduralSkybox(const RenderSceneData& sceneData) const;
|
||||||
bool BeginForwardScenePass(const RenderPassContext& context);
|
bool BeginForwardScenePass(const RenderPassContext& context);
|
||||||
void EndForwardScenePass(const RenderPassContext& context);
|
void EndForwardScenePass(const RenderPassContext& context);
|
||||||
bool ExecuteForwardOpaquePass(const RenderPassContext& context);
|
bool ExecuteForwardOpaquePass(const ScenePhaseExecutionContext& context);
|
||||||
bool ExecuteForwardSkyboxPass(const RenderPassContext& context);
|
bool ExecuteForwardSkyboxPass(const RenderPassContext& context);
|
||||||
bool ExecuteForwardTransparentPass(const RenderPassContext& context);
|
bool ExecuteForwardTransparentPass(const ScenePhaseExecutionContext& context);
|
||||||
bool DrawVisibleItems(
|
bool DrawVisibleItems(
|
||||||
const RenderContext& context,
|
const FrameExecutionContext& executionContext,
|
||||||
const RenderSurface& surface,
|
const DrawSettings& drawSettings);
|
||||||
const RenderSceneData& sceneData,
|
|
||||||
bool drawTransparentItems);
|
|
||||||
bool DrawVisibleItem(
|
bool DrawVisibleItem(
|
||||||
const RenderContext& context,
|
const FrameExecutionContext& executionContext,
|
||||||
const RenderSurface& surface,
|
|
||||||
const RenderSceneData& sceneData,
|
|
||||||
const VisibleRenderItem& visibleItem);
|
const VisibleRenderItem& visibleItem);
|
||||||
bool EnsureSkyboxResources(const RenderContext& context);
|
bool EnsureSkyboxResources(const RenderContext& context);
|
||||||
bool CreateSkyboxResources(const RenderContext& context);
|
bool CreateSkyboxResources(const RenderContext& context);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct DirectionalShadowPlanningSettings {
|
|||||||
float perspectiveFocusFactor = 1.0f;
|
float perspectiveFocusFactor = 1.0f;
|
||||||
float orthographicFocusFactor = 2.0f;
|
float orthographicFocusFactor = 2.0f;
|
||||||
float minDepthRange = 20.0f;
|
float minDepthRange = 20.0f;
|
||||||
float boundsPadding = 1.0f;
|
float boundsPadding = 0.5f;
|
||||||
float minDepthPadding = 2.0f;
|
float minDepthPadding = 2.0f;
|
||||||
DirectionalShadowSamplingSettings sampling = {};
|
DirectionalShadowSamplingSettings sampling = {};
|
||||||
DirectionalShadowCasterBiasSettings casterBias = {};
|
DirectionalShadowCasterBiasSettings casterBias = {};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/FrameExecutionContext.h>
|
||||||
#include <XCEngine/Rendering/RenderContext.h>
|
#include <XCEngine/Rendering/RenderContext.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@@ -25,6 +26,23 @@ struct RenderPassContext {
|
|||||||
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
|
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline RenderPassContext BuildRenderPassContext(
|
||||||
|
const FrameExecutionContext& executionContext) {
|
||||||
|
return {
|
||||||
|
executionContext.renderContext,
|
||||||
|
executionContext.surface,
|
||||||
|
executionContext.sceneData,
|
||||||
|
executionContext.sourceSurface,
|
||||||
|
executionContext.sourceColorView,
|
||||||
|
executionContext.sourceColorState
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RenderPassContext BuildRenderPassContext(
|
||||||
|
const ScenePhaseExecutionContext& executionContext) {
|
||||||
|
return BuildRenderPassContext(executionContext.frameContext);
|
||||||
|
}
|
||||||
|
|
||||||
class RenderPass {
|
class RenderPass {
|
||||||
public:
|
public:
|
||||||
virtual ~RenderPass() = default;
|
virtual ~RenderPass() = default;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/Execution/FrameExecutionContext.h>
|
||||||
#include <XCEngine/Rendering/FrameData/RenderSceneData.h>
|
#include <XCEngine/Rendering/FrameData/RenderSceneData.h>
|
||||||
#include <XCEngine/Rendering/RenderContext.h>
|
#include <XCEngine/Rendering/RenderContext.h>
|
||||||
|
|
||||||
@@ -14,6 +15,12 @@ public:
|
|||||||
|
|
||||||
virtual bool Initialize(const RenderContext& context) = 0;
|
virtual bool Initialize(const RenderContext& context) = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
virtual bool Render(const FrameExecutionContext& executionContext) {
|
||||||
|
return Render(
|
||||||
|
executionContext.renderContext,
|
||||||
|
executionContext.surface,
|
||||||
|
executionContext.sceneData);
|
||||||
|
}
|
||||||
virtual bool Render(
|
virtual bool Render(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSurface& surface,
|
const RenderSurface& surface,
|
||||||
|
|||||||
24
engine/include/XCEngine/Rendering/SceneRenderFeaturePass.h
Normal file
24
engine/include/XCEngine/Rendering/SceneRenderFeaturePass.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <XCEngine/Rendering/RenderPass.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Rendering {
|
||||||
|
|
||||||
|
class SceneRenderFeaturePass : public RenderPass {
|
||||||
|
public:
|
||||||
|
~SceneRenderFeaturePass() override = default;
|
||||||
|
|
||||||
|
virtual bool IsActive(const RenderSceneData& sceneData) const = 0;
|
||||||
|
|
||||||
|
virtual bool Prepare(
|
||||||
|
const RenderContext& renderContext,
|
||||||
|
const RenderSceneData& sceneData) {
|
||||||
|
(void)renderContext;
|
||||||
|
(void)sceneData;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Rendering
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -289,81 +289,88 @@ bool ExecuteFullscreenPassSequenceStage(
|
|||||||
|
|
||||||
RenderPassContext BuildFrameStagePassContext(
|
RenderPassContext BuildFrameStagePassContext(
|
||||||
CameraFrameStage stage,
|
CameraFrameStage stage,
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
const RenderSceneData& sceneData) {
|
const RenderSceneData& sceneData) {
|
||||||
const RenderSurface* outputSurface = request.GetOutputSurface(stage);
|
const RenderSurface* outputSurface = plan.GetOutputSurface(stage);
|
||||||
return {
|
return {
|
||||||
request.context,
|
plan.request.context,
|
||||||
outputSurface != nullptr ? *outputSurface : request.surface,
|
outputSurface != nullptr ? *outputSurface : plan.request.surface,
|
||||||
sceneData,
|
sceneData,
|
||||||
request.GetSourceSurface(stage),
|
plan.GetSourceSurface(stage),
|
||||||
request.GetSourceColorView(stage),
|
plan.GetSourceColorView(stage),
|
||||||
request.GetSourceColorState(stage)
|
plan.GetSourceColorState(stage)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExecuteFrameStage(
|
bool ExecuteFrameStage(
|
||||||
CameraFrameStage stage,
|
CameraFrameStage stage,
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
||||||
const RenderSceneData& sceneData,
|
const RenderSceneData& sceneData,
|
||||||
CameraFrameExecutionState& executionState) {
|
CameraFrameExecutionState& executionState) {
|
||||||
const RenderPassContext passContext = BuildFrameStagePassContext(stage, request, sceneData);
|
const RenderPassContext passContext = BuildFrameStagePassContext(stage, plan, sceneData);
|
||||||
|
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case CameraFrameStage::PreScenePasses:
|
case CameraFrameStage::PreScenePasses:
|
||||||
return ExecutePassSequenceStage(
|
return ExecutePassSequenceStage(
|
||||||
executionState.preScenePasses,
|
executionState.preScenePasses,
|
||||||
request.GetPassSequence(stage),
|
plan.GetPassSequence(stage),
|
||||||
request.context,
|
plan.request.context,
|
||||||
passContext);
|
passContext);
|
||||||
case CameraFrameStage::ShadowCaster:
|
case CameraFrameStage::ShadowCaster:
|
||||||
return ExecuteScenePassRequest(
|
return ExecuteScenePassRequest(
|
||||||
executionState.shadowCasterPass,
|
executionState.shadowCasterPass,
|
||||||
resolvedShadowCaster,
|
resolvedShadowCaster,
|
||||||
request.context,
|
plan.request.context,
|
||||||
sceneData);
|
sceneData);
|
||||||
case CameraFrameStage::DepthOnly:
|
case CameraFrameStage::DepthOnly:
|
||||||
return ExecuteScenePassRequest(
|
return ExecuteScenePassRequest(
|
||||||
executionState.depthOnlyPass,
|
executionState.depthOnlyPass,
|
||||||
request.depthOnly,
|
plan.request.depthOnly,
|
||||||
request.context,
|
plan.request.context,
|
||||||
sceneData);
|
sceneData);
|
||||||
case CameraFrameStage::MainScene:
|
case CameraFrameStage::MainScene:
|
||||||
return executionState.pipeline != nullptr &&
|
return executionState.pipeline != nullptr &&
|
||||||
executionState.pipeline->Render(request.context, passContext.surface, sceneData);
|
executionState.pipeline->Render(
|
||||||
|
FrameExecutionContext(
|
||||||
|
plan.request.context,
|
||||||
|
passContext.surface,
|
||||||
|
sceneData,
|
||||||
|
passContext.sourceSurface,
|
||||||
|
passContext.sourceColorView,
|
||||||
|
passContext.sourceColorState));
|
||||||
case CameraFrameStage::PostProcess:
|
case CameraFrameStage::PostProcess:
|
||||||
return ExecuteFullscreenPassSequenceStage(
|
return ExecuteFullscreenPassSequenceStage(
|
||||||
executionState.postProcessPasses,
|
executionState.postProcessPasses,
|
||||||
request.GetPassSequence(stage),
|
plan.GetPassSequence(stage),
|
||||||
request.context,
|
plan.request.context,
|
||||||
passContext,
|
passContext,
|
||||||
executionState.postProcessSurfaceCache);
|
executionState.postProcessSurfaceCache);
|
||||||
case CameraFrameStage::FinalOutput:
|
case CameraFrameStage::FinalOutput:
|
||||||
return ExecuteFullscreenPassSequenceStage(
|
return ExecuteFullscreenPassSequenceStage(
|
||||||
executionState.finalOutputPasses,
|
executionState.finalOutputPasses,
|
||||||
request.GetPassSequence(stage),
|
plan.GetPassSequence(stage),
|
||||||
request.context,
|
plan.request.context,
|
||||||
passContext,
|
passContext,
|
||||||
executionState.finalOutputSurfaceCache);
|
executionState.finalOutputSurfaceCache);
|
||||||
case CameraFrameStage::ObjectId:
|
case CameraFrameStage::ObjectId:
|
||||||
return !request.objectId.IsRequested() ||
|
return !plan.request.objectId.IsRequested() ||
|
||||||
ExecuteStandalonePass(
|
ExecuteStandalonePass(
|
||||||
executionState.objectIdPass,
|
executionState.objectIdPass,
|
||||||
request.context,
|
plan.request.context,
|
||||||
request.objectId.surface,
|
plan.request.objectId.surface,
|
||||||
sceneData);
|
sceneData);
|
||||||
case CameraFrameStage::PostScenePasses:
|
case CameraFrameStage::PostScenePasses:
|
||||||
return ExecutePassSequenceStage(
|
return ExecutePassSequenceStage(
|
||||||
executionState.postScenePasses,
|
executionState.postScenePasses,
|
||||||
request.GetPassSequence(stage),
|
plan.GetPassSequence(stage),
|
||||||
request.context,
|
plan.request.context,
|
||||||
passContext);
|
passContext);
|
||||||
case CameraFrameStage::OverlayPasses:
|
case CameraFrameStage::OverlayPasses:
|
||||||
return ExecutePassSequenceStage(
|
return ExecutePassSequenceStage(
|
||||||
executionState.overlayPasses,
|
executionState.overlayPasses,
|
||||||
request.GetPassSequence(stage),
|
plan.GetPassSequence(stage),
|
||||||
request.context,
|
plan.request.context,
|
||||||
passContext);
|
passContext);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -396,27 +403,27 @@ RenderDirectionalShadowData BuildDirectionalShadowData(
|
|||||||
return shadowData;
|
return shadowData;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderEnvironmentData BuildEnvironmentData(const CameraRenderRequest& request) {
|
RenderEnvironmentData BuildEnvironmentData(const CameraFramePlan& plan) {
|
||||||
RenderEnvironmentData environment = {};
|
RenderEnvironmentData environment = {};
|
||||||
const RenderSurface& mainSceneSurface = request.GetMainSceneSurface();
|
const RenderSurface& mainSceneSurface = plan.GetMainSceneSurface();
|
||||||
if (request.camera == nullptr ||
|
if (plan.request.camera == nullptr ||
|
||||||
mainSceneSurface.GetDepthAttachment() == nullptr ||
|
mainSceneSurface.GetDepthAttachment() == nullptr ||
|
||||||
!HasRenderClearFlag(request.clearFlags, RenderClearFlags::Color) ||
|
!HasRenderClearFlag(plan.request.clearFlags, RenderClearFlags::Color) ||
|
||||||
!request.camera->IsSkyboxEnabled() ||
|
!plan.request.camera->IsSkyboxEnabled() ||
|
||||||
request.camera->GetProjectionType() != Components::CameraProjectionType::Perspective) {
|
plan.request.camera->GetProjectionType() != Components::CameraProjectionType::Perspective) {
|
||||||
return environment;
|
return environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const Resources::Material* skyboxMaterial = request.camera->GetSkyboxMaterial()) {
|
if (const Resources::Material* skyboxMaterial = plan.request.camera->GetSkyboxMaterial()) {
|
||||||
environment.mode = RenderEnvironmentMode::MaterialSkybox;
|
environment.mode = RenderEnvironmentMode::MaterialSkybox;
|
||||||
environment.materialSkybox.material = skyboxMaterial;
|
environment.materialSkybox.material = skyboxMaterial;
|
||||||
return environment;
|
return environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
environment.mode = RenderEnvironmentMode::ProceduralSkybox;
|
environment.mode = RenderEnvironmentMode::ProceduralSkybox;
|
||||||
environment.skybox.topColor = request.camera->GetSkyboxTopColor();
|
environment.skybox.topColor = plan.request.camera->GetSkyboxTopColor();
|
||||||
environment.skybox.horizonColor = request.camera->GetSkyboxHorizonColor();
|
environment.skybox.horizonColor = plan.request.camera->GetSkyboxHorizonColor();
|
||||||
environment.skybox.bottomColor = request.camera->GetSkyboxBottomColor();
|
environment.skybox.bottomColor = plan.request.camera->GetSkyboxBottomColor();
|
||||||
return environment;
|
return environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,17 +545,17 @@ void CameraRenderer::ResetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CameraRenderer::ResolveShadowCasterRequest(
|
bool CameraRenderer::ResolveShadowCasterRequest(
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
ShadowCasterRenderRequest& outResolvedShadowCaster,
|
ShadowCasterRenderRequest& outResolvedShadowCaster,
|
||||||
RHI::RHIResourceView*& outShadowMapView) {
|
RHI::RHIResourceView*& outShadowMapView) {
|
||||||
outResolvedShadowCaster = request.shadowCaster;
|
outResolvedShadowCaster = plan.shadowCaster;
|
||||||
outShadowMapView = nullptr;
|
outShadowMapView = nullptr;
|
||||||
|
|
||||||
if (outResolvedShadowCaster.IsRequested()) {
|
if (outResolvedShadowCaster.IsRequested()) {
|
||||||
return outResolvedShadowCaster.IsValid();
|
return outResolvedShadowCaster.IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request.directionalShadow.IsValid()) {
|
if (!plan.directionalShadow.IsValid()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +563,7 @@ bool CameraRenderer::ResolveShadowCasterRequest(
|
|||||||
m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceCache>();
|
m_directionalShadowSurface = std::make_unique<DirectionalShadowSurfaceCache>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_directionalShadowSurface->EnsureSurface(request.context, request.directionalShadow)) {
|
if (!m_directionalShadowSurface->EnsureSurface(plan.request.context, plan.directionalShadow)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,44 +571,44 @@ bool CameraRenderer::ResolveShadowCasterRequest(
|
|||||||
outResolvedShadowCaster.clearFlags = RenderClearFlags::Depth;
|
outResolvedShadowCaster.clearFlags = RenderClearFlags::Depth;
|
||||||
if (!outResolvedShadowCaster.hasCameraDataOverride) {
|
if (!outResolvedShadowCaster.hasCameraDataOverride) {
|
||||||
outResolvedShadowCaster.hasCameraDataOverride = true;
|
outResolvedShadowCaster.hasCameraDataOverride = true;
|
||||||
outResolvedShadowCaster.cameraDataOverride = request.directionalShadow.cameraData;
|
outResolvedShadowCaster.cameraDataOverride = plan.directionalShadow.cameraData;
|
||||||
}
|
}
|
||||||
|
|
||||||
outShadowMapView = m_directionalShadowSurface->GetDepthShaderView();
|
outShadowMapView = m_directionalShadowSurface->GetDepthShaderView();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CameraRenderer::BuildSceneDataForRequest(
|
bool CameraRenderer::BuildSceneDataForPlan(
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
RHI::RHIResourceView* shadowMapView,
|
RHI::RHIResourceView* shadowMapView,
|
||||||
RenderSceneData& outSceneData) {
|
RenderSceneData& outSceneData) {
|
||||||
const RenderSurface& mainSceneSurface = request.GetMainSceneSurface();
|
const RenderSurface& mainSceneSurface = plan.GetMainSceneSurface();
|
||||||
outSceneData = m_sceneExtractor.ExtractForCamera(
|
outSceneData = m_sceneExtractor.ExtractForCamera(
|
||||||
*request.scene,
|
*plan.request.scene,
|
||||||
*request.camera,
|
*plan.request.camera,
|
||||||
mainSceneSurface.GetRenderAreaWidth(),
|
mainSceneSurface.GetRenderAreaWidth(),
|
||||||
mainSceneSurface.GetRenderAreaHeight());
|
mainSceneSurface.GetRenderAreaHeight());
|
||||||
if (!outSceneData.HasCamera()) {
|
if (!outSceneData.HasCamera()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.directionalShadow.IsValid()) {
|
if (plan.directionalShadow.IsValid()) {
|
||||||
outSceneData.lighting.mainDirectionalShadow =
|
outSceneData.lighting.mainDirectionalShadow =
|
||||||
BuildDirectionalShadowData(request.directionalShadow, shadowMapView);
|
BuildDirectionalShadowData(plan.directionalShadow, shadowMapView);
|
||||||
}
|
}
|
||||||
outSceneData.globalShaderKeywords = BuildSceneGlobalShaderKeywords(outSceneData);
|
outSceneData.globalShaderKeywords = BuildSceneGlobalShaderKeywords(outSceneData);
|
||||||
|
|
||||||
outSceneData.cameraData.clearFlags = request.clearFlags;
|
outSceneData.cameraData.clearFlags = plan.request.clearFlags;
|
||||||
outSceneData.environment = BuildEnvironmentData(request);
|
outSceneData.environment = BuildEnvironmentData(plan);
|
||||||
if (request.hasClearColorOverride) {
|
if (plan.request.hasClearColorOverride) {
|
||||||
outSceneData.cameraData.clearColor = request.clearColorOverride;
|
outSceneData.cameraData.clearColor = plan.request.clearColorOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CameraRenderer::ExecuteRenderPlan(
|
bool CameraRenderer::ExecuteRenderPlan(
|
||||||
const CameraRenderRequest& request,
|
const CameraFramePlan& plan,
|
||||||
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
const ShadowCasterRenderRequest& resolvedShadowCaster,
|
||||||
const RenderSceneData& sceneData) {
|
const RenderSceneData& sceneData) {
|
||||||
CameraFrameExecutionState executionState = {};
|
CameraFrameExecutionState executionState = {};
|
||||||
@@ -613,14 +620,14 @@ bool CameraRenderer::ExecuteRenderPlan(
|
|||||||
executionState.finalOutputSurfaceCache = m_finalOutputSurfaceCache.get();
|
executionState.finalOutputSurfaceCache = m_finalOutputSurfaceCache.get();
|
||||||
|
|
||||||
for (const CameraFrameStageInfo& stageInfo : kOrderedCameraFrameStages) {
|
for (const CameraFrameStageInfo& stageInfo : kOrderedCameraFrameStages) {
|
||||||
if (!request.HasFrameStage(stageInfo.stage) &&
|
if (!plan.HasFrameStage(stageInfo.stage) &&
|
||||||
stageInfo.stage != CameraFrameStage::MainScene) {
|
stageInfo.stage != CameraFrameStage::MainScene) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExecuteFrameStage(
|
if (!ExecuteFrameStage(
|
||||||
stageInfo.stage,
|
stageInfo.stage,
|
||||||
request,
|
plan,
|
||||||
resolvedShadowCaster,
|
resolvedShadowCaster,
|
||||||
sceneData,
|
sceneData,
|
||||||
executionState)) {
|
executionState)) {
|
||||||
@@ -633,14 +640,19 @@ bool CameraRenderer::ExecuteRenderPlan(
|
|||||||
|
|
||||||
bool CameraRenderer::Render(
|
bool CameraRenderer::Render(
|
||||||
const CameraRenderRequest& request) {
|
const CameraRenderRequest& request) {
|
||||||
if (!request.IsValid() || m_pipeline == nullptr) {
|
return Render(CameraFramePlan::FromRequest(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CameraRenderer::Render(
|
||||||
|
const CameraFramePlan& plan) {
|
||||||
|
if (!plan.IsValid() || m_pipeline == nullptr) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: request invalid or pipeline missing");
|
"CameraRenderer::Render failed: plan invalid or pipeline missing");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderSurface& mainSceneSurface = request.GetMainSceneSurface();
|
const RenderSurface& mainSceneSurface = plan.GetMainSceneSurface();
|
||||||
if (mainSceneSurface.GetRenderAreaWidth() == 0 ||
|
if (mainSceneSurface.GetRenderAreaWidth() == 0 ||
|
||||||
mainSceneSurface.GetRenderAreaHeight() == 0) {
|
mainSceneSurface.GetRenderAreaHeight() == 0) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
@@ -648,29 +660,29 @@ bool CameraRenderer::Render(
|
|||||||
"CameraRenderer::Render failed: main scene surface render area is empty");
|
"CameraRenderer::Render failed: main scene surface render area is empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (request.depthOnly.IsRequested() &&
|
if (plan.request.depthOnly.IsRequested() &&
|
||||||
!request.depthOnly.IsValid()) {
|
!plan.request.depthOnly.IsValid()) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: depth-only request invalid");
|
"CameraRenderer::Render failed: depth-only request invalid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (request.postProcess.IsRequested() &&
|
if (plan.postProcess.IsRequested() &&
|
||||||
!request.postProcess.IsValid()) {
|
!plan.postProcess.IsValid()) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: post-process request invalid");
|
"CameraRenderer::Render failed: post-process request invalid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (request.finalOutput.IsRequested() &&
|
if (plan.finalOutput.IsRequested() &&
|
||||||
!request.finalOutput.IsValid()) {
|
!plan.finalOutput.IsValid()) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: final-output request invalid");
|
"CameraRenderer::Render failed: final-output request invalid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (request.objectId.IsRequested() &&
|
if (plan.request.objectId.IsRequested() &&
|
||||||
!request.objectId.IsValid()) {
|
!plan.request.objectId.IsValid()) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: object-id request invalid");
|
"CameraRenderer::Render failed: object-id request invalid");
|
||||||
@@ -679,7 +691,7 @@ bool CameraRenderer::Render(
|
|||||||
|
|
||||||
ShadowCasterRenderRequest resolvedShadowCaster = {};
|
ShadowCasterRenderRequest resolvedShadowCaster = {};
|
||||||
RHI::RHIResourceView* shadowMapView = nullptr;
|
RHI::RHIResourceView* shadowMapView = nullptr;
|
||||||
if (!ResolveShadowCasterRequest(request, resolvedShadowCaster, shadowMapView)) {
|
if (!ResolveShadowCasterRequest(plan, resolvedShadowCaster, shadowMapView)) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: ResolveShadowCasterRequest returned false");
|
"CameraRenderer::Render failed: ResolveShadowCasterRequest returned false");
|
||||||
@@ -687,14 +699,14 @@ bool CameraRenderer::Render(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderSceneData sceneData = {};
|
RenderSceneData sceneData = {};
|
||||||
if (!BuildSceneDataForRequest(request, shadowMapView, sceneData)) {
|
if (!BuildSceneDataForPlan(plan, shadowMapView, sceneData)) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: BuildSceneDataForRequest returned false");
|
"CameraRenderer::Render failed: BuildSceneDataForPlan returned false");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExecuteRenderPlan(request, resolvedShadowCaster, sceneData)) {
|
if (!ExecuteRenderPlan(plan, resolvedShadowCaster, sceneData)) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"CameraRenderer::Render failed: ExecuteRenderPlan returned false");
|
"CameraRenderer::Render failed: ExecuteRenderPlan returned false");
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ namespace Rendering {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
bool CompareCameraFramePlans(
|
||||||
|
const CameraFramePlan& lhs,
|
||||||
|
const CameraFramePlan& rhs) {
|
||||||
|
return SceneRenderRequestUtils::CompareCameraRenderRequests(
|
||||||
|
lhs.request,
|
||||||
|
rhs.request);
|
||||||
|
}
|
||||||
|
|
||||||
RenderSurface ConfigureFullscreenStageSurface(
|
RenderSurface ConfigureFullscreenStageSurface(
|
||||||
const FullscreenPassSurfaceCache::SurfaceEntry& entry,
|
const FullscreenPassSurfaceCache::SurfaceEntry& entry,
|
||||||
const RenderSurface& templateSurface,
|
const RenderSurface& templateSurface,
|
||||||
@@ -94,44 +102,72 @@ std::vector<CameraRenderRequest> SceneRenderer::BuildRenderRequests(
|
|||||||
Components::CameraComponent* overrideCamera,
|
Components::CameraComponent* overrideCamera,
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSurface& surface) {
|
const RenderSurface& surface) {
|
||||||
std::vector<CameraRenderRequest> requests =
|
const std::vector<CameraFramePlan> plans =
|
||||||
m_requestPlanner.BuildRequests(scene, overrideCamera, context, surface);
|
BuildFramePlans(scene, overrideCamera, context, surface);
|
||||||
ResolveCameraFinalColorPolicies(requests);
|
std::vector<CameraRenderRequest> requests = {};
|
||||||
AttachFullscreenStageRequests(context, requests);
|
requests.reserve(plans.size());
|
||||||
|
for (const CameraFramePlan& plan : plans) {
|
||||||
|
requests.push_back(BuildLegacyCameraRenderRequest(plan));
|
||||||
|
}
|
||||||
return requests;
|
return requests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<CameraFramePlan> SceneRenderer::BuildFramePlans(
|
||||||
|
const Components::Scene& scene,
|
||||||
|
Components::CameraComponent* overrideCamera,
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSurface& surface) {
|
||||||
|
const std::vector<CameraRenderRequest> requests =
|
||||||
|
m_requestPlanner.BuildRequests(scene, overrideCamera, context, surface);
|
||||||
|
std::vector<CameraFramePlan> plans = CreateFramePlansFromRequests(requests);
|
||||||
|
ResolveCameraFinalColorPolicies(plans);
|
||||||
|
AttachFullscreenStageRequests(context, plans);
|
||||||
|
return plans;
|
||||||
|
}
|
||||||
|
|
||||||
bool SceneRenderer::Render(const CameraRenderRequest& request) {
|
bool SceneRenderer::Render(const CameraRenderRequest& request) {
|
||||||
return m_cameraRenderer.Render(request);
|
return Render(CameraFramePlan::FromRequest(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SceneRenderer::Render(const std::vector<CameraRenderRequest>& requests) {
|
bool SceneRenderer::Render(const std::vector<CameraRenderRequest>& requests) {
|
||||||
if (requests.empty()) {
|
std::vector<CameraFramePlan> plans = CreateFramePlansFromRequests(requests);
|
||||||
|
return Render(plans);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneRenderer::Render(const CameraFramePlan& plan) {
|
||||||
|
return m_cameraRenderer.Render(plan);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneRenderer::Render(const std::vector<CameraFramePlan>& plans) {
|
||||||
|
if (plans.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const CameraRenderRequest& request : requests) {
|
for (const CameraFramePlan& plan : plans) {
|
||||||
if (!request.IsValid()) {
|
if (!plan.IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CameraRenderRequest> sortedRequests = requests;
|
std::vector<CameraFramePlan> sortedPlans = plans;
|
||||||
SceneRenderRequestUtils::SortCameraRenderRequests(sortedRequests);
|
std::stable_sort(
|
||||||
|
sortedPlans.begin(),
|
||||||
|
sortedPlans.end(),
|
||||||
|
CompareCameraFramePlans);
|
||||||
|
|
||||||
bool rendered = false;
|
bool rendered = false;
|
||||||
for (const CameraRenderRequest& request : sortedRequests) {
|
for (const CameraFramePlan& plan : sortedPlans) {
|
||||||
if (!m_cameraRenderer.Render(request)) {
|
if (!m_cameraRenderer.Render(plan)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTrackedFullscreenSurfaceState(
|
UpdateTrackedFullscreenSurfaceState(
|
||||||
m_ownedFullscreenStageSurfaces,
|
m_ownedFullscreenStageSurfaces,
|
||||||
&request.GetMainSceneSurface());
|
&plan.GetMainSceneSurface());
|
||||||
if (request.postProcess.IsRequested()) {
|
if (plan.postProcess.IsRequested()) {
|
||||||
UpdateTrackedFullscreenSurfaceState(
|
UpdateTrackedFullscreenSurfaceState(
|
||||||
m_ownedFullscreenStageSurfaces,
|
m_ownedFullscreenStageSurfaces,
|
||||||
&request.postProcess.destinationSurface);
|
&plan.postProcess.destinationSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
rendered = true;
|
rendered = true;
|
||||||
@@ -145,7 +181,18 @@ bool SceneRenderer::Render(
|
|||||||
Components::CameraComponent* overrideCamera,
|
Components::CameraComponent* overrideCamera,
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSurface& surface) {
|
const RenderSurface& surface) {
|
||||||
return Render(BuildRenderRequests(scene, overrideCamera, context, surface));
|
return Render(BuildFramePlans(scene, overrideCamera, context, surface));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CameraFramePlan> SceneRenderer::CreateFramePlansFromRequests(
|
||||||
|
const std::vector<CameraRenderRequest>& requests) const {
|
||||||
|
std::vector<CameraFramePlan> plans = {};
|
||||||
|
plans.reserve(requests.size());
|
||||||
|
for (const CameraRenderRequest& request : requests) {
|
||||||
|
plans.push_back(CameraFramePlan::FromRequest(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
return plans;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::PrepareOwnedFullscreenStageState(size_t requestCount) {
|
void SceneRenderer::PrepareOwnedFullscreenStageState(size_t requestCount) {
|
||||||
@@ -166,39 +213,39 @@ void SceneRenderer::PrepareOwnedFullscreenStageState(size_t requestCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::ResolveCameraFinalColorPolicies(
|
void SceneRenderer::ResolveCameraFinalColorPolicies(
|
||||||
std::vector<CameraRenderRequest>& requests) const {
|
std::vector<CameraFramePlan>& plans) const {
|
||||||
const RenderPipelineAsset* pipelineAsset = GetPipelineAsset();
|
const RenderPipelineAsset* pipelineAsset = GetPipelineAsset();
|
||||||
const FinalColorSettings pipelineDefaults =
|
const FinalColorSettings pipelineDefaults =
|
||||||
pipelineAsset != nullptr ? pipelineAsset->GetDefaultFinalColorSettings() : FinalColorSettings();
|
pipelineAsset != nullptr ? pipelineAsset->GetDefaultFinalColorSettings() : FinalColorSettings();
|
||||||
|
|
||||||
for (CameraRenderRequest& request : requests) {
|
for (CameraFramePlan& plan : plans) {
|
||||||
if (request.camera == nullptr) {
|
if (plan.request.camera == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.finalColorPolicy = ResolveFinalColorPolicy(
|
plan.finalColorPolicy = ResolveFinalColorPolicy(
|
||||||
pipelineDefaults,
|
pipelineDefaults,
|
||||||
&request.camera->GetFinalColorOverrides());
|
&plan.request.camera->GetFinalColorOverrides());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneRenderer::AttachFullscreenStageRequests(
|
void SceneRenderer::AttachFullscreenStageRequests(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
std::vector<CameraRenderRequest>& requests) {
|
std::vector<CameraFramePlan>& plans) {
|
||||||
PrepareOwnedFullscreenStageState(requests.size());
|
PrepareOwnedFullscreenStageState(plans.size());
|
||||||
|
|
||||||
for (size_t index = 0; index < requests.size(); ++index) {
|
for (size_t index = 0; index < plans.size(); ++index) {
|
||||||
CameraRenderRequest& request = requests[index];
|
CameraFramePlan& plan = plans[index];
|
||||||
if (request.camera == nullptr ||
|
if (plan.request.camera == nullptr ||
|
||||||
request.context.device == nullptr ||
|
plan.request.context.device == nullptr ||
|
||||||
!HasValidColorTarget(request.surface)) {
|
!HasValidColorTarget(plan.request.surface)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<RenderPassSequence> postProcessSequence =
|
std::unique_ptr<RenderPassSequence> postProcessSequence =
|
||||||
BuildCameraPostProcessPassSequence(request.camera->GetPostProcessPasses());
|
BuildCameraPostProcessPassSequence(plan.request.camera->GetPostProcessPasses());
|
||||||
std::unique_ptr<RenderPassSequence> finalOutputSequence =
|
std::unique_ptr<RenderPassSequence> finalOutputSequence =
|
||||||
BuildFinalColorPassSequence(request.finalColorPolicy);
|
BuildFinalColorPassSequence(plan.finalColorPolicy);
|
||||||
|
|
||||||
const bool hasPostProcess =
|
const bool hasPostProcess =
|
||||||
postProcessSequence != nullptr && postProcessSequence->GetPassCount() > 0u;
|
postProcessSequence != nullptr && postProcessSequence->GetPassCount() > 0u;
|
||||||
@@ -208,14 +255,14 @@ void SceneRenderer::AttachFullscreenStageRequests(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.surface.GetSampleCount() > 1u) {
|
if (plan.request.surface.GetSampleCount() > 1u) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"SceneRenderer fullscreen post-process/final-output chain currently requires a single-sample main scene surface");
|
"SceneRenderer fullscreen post-process/final-output chain currently requires a single-sample main scene surface");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<RHI::RHIResourceView*>& colorAttachments = request.surface.GetColorAttachments();
|
const std::vector<RHI::RHIResourceView*>& colorAttachments = plan.request.surface.GetColorAttachments();
|
||||||
const RHI::Format colorFormat = colorAttachments[0]->GetFormat();
|
const RHI::Format colorFormat = colorAttachments[0]->GetFormat();
|
||||||
if (colorFormat == RHI::Format::Unknown) {
|
if (colorFormat == RHI::Format::Unknown) {
|
||||||
continue;
|
continue;
|
||||||
@@ -226,8 +273,8 @@ void SceneRenderer::AttachFullscreenStageRequests(
|
|||||||
if (surfaceCache == nullptr ||
|
if (surfaceCache == nullptr ||
|
||||||
!surfaceCache->EnsureSurfaces(
|
!surfaceCache->EnsureSurfaces(
|
||||||
context,
|
context,
|
||||||
request.surface.GetWidth(),
|
plan.request.surface.GetWidth(),
|
||||||
request.surface.GetHeight(),
|
plan.request.surface.GetHeight(),
|
||||||
colorFormat,
|
colorFormat,
|
||||||
fullscreenSurfaceCount)) {
|
fullscreenSurfaceCount)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -246,30 +293,30 @@ void SceneRenderer::AttachFullscreenStageRequests(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasPostProcess) {
|
if (hasPostProcess) {
|
||||||
request.postProcess.sourceSurface =
|
plan.postProcess.sourceSurface =
|
||||||
ConfigureFullscreenStageSurface(*sceneColorEntry, request.surface, true);
|
ConfigureFullscreenStageSurface(*sceneColorEntry, plan.request.surface, true);
|
||||||
request.postProcess.sourceColorView = sceneColorEntry->shaderResourceView;
|
plan.postProcess.sourceColorView = sceneColorEntry->shaderResourceView;
|
||||||
request.postProcess.sourceColorState = request.postProcess.sourceSurface.GetColorStateAfter();
|
plan.postProcess.sourceColorState = plan.postProcess.sourceSurface.GetColorStateAfter();
|
||||||
request.postProcess.destinationSurface =
|
plan.postProcess.destinationSurface =
|
||||||
hasFinalOutput
|
hasFinalOutput
|
||||||
? ConfigureFullscreenStageSurface(*postProcessOutputEntry, request.surface, false)
|
? ConfigureFullscreenStageSurface(*postProcessOutputEntry, plan.request.surface, false)
|
||||||
: request.surface;
|
: plan.request.surface;
|
||||||
m_ownedPostProcessSequences[index] = std::move(postProcessSequence);
|
m_ownedPostProcessSequences[index] = std::move(postProcessSequence);
|
||||||
request.postProcess.passes = m_ownedPostProcessSequences[index].get();
|
plan.postProcess.passes = m_ownedPostProcessSequences[index].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFinalOutput) {
|
if (hasFinalOutput) {
|
||||||
const FullscreenPassSurfaceCache::SurfaceEntry* finalOutputSourceEntry =
|
const FullscreenPassSurfaceCache::SurfaceEntry* finalOutputSourceEntry =
|
||||||
hasPostProcess ? postProcessOutputEntry : sceneColorEntry;
|
hasPostProcess ? postProcessOutputEntry : sceneColorEntry;
|
||||||
request.finalOutput.sourceSurface =
|
plan.finalOutput.sourceSurface =
|
||||||
hasPostProcess
|
hasPostProcess
|
||||||
? request.postProcess.destinationSurface
|
? plan.postProcess.destinationSurface
|
||||||
: ConfigureFullscreenStageSurface(*sceneColorEntry, request.surface, true);
|
: ConfigureFullscreenStageSurface(*sceneColorEntry, plan.request.surface, true);
|
||||||
request.finalOutput.sourceColorView = finalOutputSourceEntry->shaderResourceView;
|
plan.finalOutput.sourceColorView = finalOutputSourceEntry->shaderResourceView;
|
||||||
request.finalOutput.sourceColorState = request.finalOutput.sourceSurface.GetColorStateAfter();
|
plan.finalOutput.sourceColorState = plan.finalOutput.sourceSurface.GetColorStateAfter();
|
||||||
request.finalOutput.destinationSurface = request.surface;
|
plan.finalOutput.destinationSurface = plan.request.surface;
|
||||||
m_ownedFinalOutputSequences[index] = std::move(finalOutputSequence);
|
m_ownedFinalOutputSequences[index] = std::move(finalOutputSequence);
|
||||||
request.finalOutput.passes = m_ownedFinalOutputSequences[index].get();
|
plan.finalOutput.passes = m_ownedFinalOutputSequences[index].get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "Components/CameraComponent.h"
|
#include "Components/CameraComponent.h"
|
||||||
#include "Components/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
#include "Components/LightComponent.h"
|
#include "Components/LightComponent.h"
|
||||||
|
#include "Rendering/FrameData/RendererListUtils.h"
|
||||||
#include "Rendering/Extraction/RenderSceneUtility.h"
|
#include "Rendering/Extraction/RenderSceneUtility.h"
|
||||||
#include "Scene/Scene.h"
|
#include "Scene/Scene.h"
|
||||||
|
|
||||||
@@ -125,6 +126,21 @@ bool CompareVisibleGaussianSplats(
|
|||||||
return CompareVisibleGaussianSplatsStable(lhs, rhs);
|
return CompareVisibleGaussianSplatsStable(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BuildRendererLists(RenderSceneData& sceneData) {
|
||||||
|
sceneData.cullingResults.Clear();
|
||||||
|
sceneData.cullingResults.rendererLists.reserve(5u);
|
||||||
|
sceneData.cullingResults.rendererLists.push_back(
|
||||||
|
BuildRendererList(RendererListType::AllVisible, sceneData.visibleItems));
|
||||||
|
sceneData.cullingResults.rendererLists.push_back(
|
||||||
|
BuildRendererList(RendererListType::Opaque, sceneData.visibleItems));
|
||||||
|
sceneData.cullingResults.rendererLists.push_back(
|
||||||
|
BuildRendererList(RendererListType::Transparent, sceneData.visibleItems));
|
||||||
|
sceneData.cullingResults.rendererLists.push_back(
|
||||||
|
BuildRendererList(RendererListType::ShadowCaster, sceneData.visibleItems));
|
||||||
|
sceneData.cullingResults.rendererLists.push_back(
|
||||||
|
BuildRendererList(RendererListType::ObjectId, sceneData.visibleItems));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
RenderSceneData RenderSceneExtractor::Extract(
|
RenderSceneData RenderSceneExtractor::Extract(
|
||||||
@@ -165,6 +181,7 @@ RenderSceneData RenderSceneExtractor::Extract(
|
|||||||
sceneData.visibleVolumes.begin(),
|
sceneData.visibleVolumes.begin(),
|
||||||
sceneData.visibleVolumes.end(),
|
sceneData.visibleVolumes.end(),
|
||||||
CompareVisibleVolumes);
|
CompareVisibleVolumes);
|
||||||
|
BuildRendererLists(sceneData);
|
||||||
ExtractLighting(scene, cameraPosition, cullingMask, sceneData.lighting);
|
ExtractLighting(scene, cameraPosition, cullingMask, sceneData.lighting);
|
||||||
|
|
||||||
return sceneData;
|
return sceneData;
|
||||||
@@ -208,6 +225,7 @@ RenderSceneData RenderSceneExtractor::ExtractForCamera(
|
|||||||
sceneData.visibleVolumes.begin(),
|
sceneData.visibleVolumes.begin(),
|
||||||
sceneData.visibleVolumes.end(),
|
sceneData.visibleVolumes.end(),
|
||||||
CompareVisibleVolumes);
|
CompareVisibleVolumes);
|
||||||
|
BuildRendererLists(sceneData);
|
||||||
ExtractLighting(scene, cameraPosition, cullingMask, sceneData.lighting);
|
ExtractLighting(scene, cameraPosition, cullingMask, sceneData.lighting);
|
||||||
|
|
||||||
return sceneData;
|
return sceneData;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "RHI/RHICommandList.h"
|
#include "RHI/RHICommandList.h"
|
||||||
#include "Rendering/Extraction/RenderSceneExtractor.h"
|
#include "Rendering/Extraction/RenderSceneExtractor.h"
|
||||||
|
#include "Rendering/FrameData/RendererListUtils.h"
|
||||||
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
||||||
#include "Rendering/RenderSurface.h"
|
#include "Rendering/RenderSurface.h"
|
||||||
#include "Resources/Mesh/Mesh.h"
|
#include "Resources/Mesh/Mesh.h"
|
||||||
@@ -139,13 +140,16 @@ bool BuiltinDepthStylePassBase::Execute(const RenderPassContext& context) {
|
|||||||
|
|
||||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||||
|
|
||||||
for (const VisibleRenderItem& visibleItem : context.sceneData.visibleItems) {
|
VisitRendererListVisibleItems(
|
||||||
|
context.sceneData,
|
||||||
|
GetRendererListType(),
|
||||||
|
[&](const VisibleRenderItem& visibleItem) {
|
||||||
if (!ShouldRenderVisibleItem(visibleItem)) {
|
if (!ShouldRenderVisibleItem(visibleItem)) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawVisibleItem(context.renderContext, context.surface, context.sceneData, visibleItem);
|
DrawVisibleItem(context.renderContext, context.surface, context.sceneData, visibleItem);
|
||||||
}
|
});
|
||||||
|
|
||||||
commandList->EndRenderPass();
|
commandList->EndRenderPass();
|
||||||
|
|
||||||
@@ -165,6 +169,10 @@ bool BuiltinDepthStylePassBase::Execute(const RenderPassContext& context) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RendererListType BuiltinDepthStylePassBase::GetRendererListType() const {
|
||||||
|
return RendererListType::AllVisible;
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinDepthStylePassBase::ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const {
|
bool BuiltinDepthStylePassBase::ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const {
|
||||||
(void)visibleItem;
|
(void)visibleItem;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -222,6 +222,16 @@ bool BuiltinGaussianSplatPass::Initialize(const RenderContext& context) {
|
|||||||
return EnsureInitialized(context);
|
return EnsureInitialized(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BuiltinGaussianSplatPass::IsActive(const RenderSceneData& sceneData) const {
|
||||||
|
return !sceneData.visibleGaussianSplats.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinGaussianSplatPass::Prepare(
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSceneData& sceneData) {
|
||||||
|
return PrepareGaussianSplatResources(context, sceneData);
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
|
bool BuiltinGaussianSplatPass::PrepareGaussianSplatResources(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSceneData& sceneData) {
|
const RenderSceneData& sceneData) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Core/Asset/ResourceManager.h"
|
#include "Core/Asset/ResourceManager.h"
|
||||||
#include "RHI/RHICommandList.h"
|
#include "RHI/RHICommandList.h"
|
||||||
|
#include "Rendering/FrameData/RendererListUtils.h"
|
||||||
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
||||||
#include "Rendering/Extraction/RenderSceneExtractor.h"
|
#include "Rendering/Extraction/RenderSceneExtractor.h"
|
||||||
#include "Rendering/RenderSurface.h"
|
#include "Rendering/RenderSurface.h"
|
||||||
@@ -119,9 +120,12 @@ bool BuiltinObjectIdPass::Execute(const RenderPassContext& context) {
|
|||||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||||
commandList->SetPipelineState(m_pipelineState);
|
commandList->SetPipelineState(m_pipelineState);
|
||||||
|
|
||||||
for (const VisibleRenderItem& visibleItem : context.sceneData.visibleItems) {
|
VisitRendererListVisibleItems(
|
||||||
|
context.sceneData,
|
||||||
|
RendererListType::ObjectId,
|
||||||
|
[&](const VisibleRenderItem& visibleItem) {
|
||||||
DrawVisibleItem(context.renderContext, context.sceneData, visibleItem);
|
DrawVisibleItem(context.renderContext, context.sceneData, visibleItem);
|
||||||
}
|
});
|
||||||
|
|
||||||
commandList->EndRenderPass();
|
commandList->EndRenderPass();
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ const char* BuiltinShadowCasterPass::GetName() const {
|
|||||||
return "BuiltinShadowCasterPass";
|
return "BuiltinShadowCasterPass";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RendererListType BuiltinShadowCasterPass::GetRendererListType() const {
|
||||||
|
return RendererListType::ShadowCaster;
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinShadowCasterPass::ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const {
|
bool BuiltinShadowCasterPass::ShouldRenderVisibleItem(const VisibleRenderItem& visibleItem) const {
|
||||||
return visibleItem.meshRenderer == nullptr || visibleItem.meshRenderer->GetCastShadows();
|
return visibleItem.meshRenderer == nullptr || visibleItem.meshRenderer->GetCastShadows();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,6 +210,16 @@ bool BuiltinVolumetricPass::Initialize(const RenderContext& context) {
|
|||||||
return EnsureInitialized(context);
|
return EnsureInitialized(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BuiltinVolumetricPass::IsActive(const RenderSceneData& sceneData) const {
|
||||||
|
return !sceneData.visibleVolumes.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinVolumetricPass::Prepare(
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSceneData& sceneData) {
|
||||||
|
return PrepareVolumeResources(context, sceneData);
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinVolumetricPass::PrepareVolumeResources(
|
bool BuiltinVolumetricPass::PrepareVolumeResources(
|
||||||
const RenderContext& context,
|
const RenderContext& context,
|
||||||
const RenderSceneData& sceneData) {
|
const RenderSceneData& sceneData) {
|
||||||
|
|||||||
@@ -143,58 +143,31 @@ RHI::InputLayoutDesc BuiltinForwardPipeline::BuildInputLayout() {
|
|||||||
|
|
||||||
bool BuiltinForwardPipeline::Initialize(const RenderContext& context) {
|
bool BuiltinForwardPipeline::Initialize(const RenderContext& context) {
|
||||||
return EnsureInitialized(context) &&
|
return EnsureInitialized(context) &&
|
||||||
m_gaussianSplatPass != nullptr &&
|
InitializeForwardSceneFeaturePasses(context);
|
||||||
m_gaussianSplatPass->Initialize(context) &&
|
|
||||||
m_volumetricPass != nullptr &&
|
|
||||||
m_volumetricPass->Initialize(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuiltinForwardPipeline::Shutdown() {
|
void BuiltinForwardPipeline::Shutdown() {
|
||||||
if (m_gaussianSplatPass != nullptr) {
|
ShutdownForwardSceneFeaturePasses();
|
||||||
m_gaussianSplatPass->Shutdown();
|
|
||||||
}
|
|
||||||
if (m_volumetricPass != nullptr) {
|
|
||||||
m_volumetricPass->Shutdown();
|
|
||||||
}
|
|
||||||
DestroyPipelineResources();
|
DestroyPipelineResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::Render(
|
bool BuiltinForwardPipeline::Render(
|
||||||
const RenderContext& context,
|
const FrameExecutionContext& executionContext) {
|
||||||
const RenderSurface& surface,
|
if (!Initialize(executionContext.renderContext)) {
|
||||||
const RenderSceneData& sceneData) {
|
|
||||||
if (!Initialize(context)) {
|
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"BuiltinForwardPipeline::Render failed: Initialize returned false");
|
"BuiltinForwardPipeline::Render failed: Initialize returned false");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_volumetricPass != nullptr &&
|
if (!PrepareForwardSceneFeaturePasses(executionContext)) {
|
||||||
!sceneData.visibleVolumes.empty() &&
|
|
||||||
!m_volumetricPass->PrepareVolumeResources(context, sceneData)) {
|
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
Debug::LogCategory::Rendering,
|
Debug::LogCategory::Rendering,
|
||||||
"BuiltinForwardPipeline::Render failed: PrepareVolumeResources returned false");
|
"BuiltinForwardPipeline::Render failed: PrepareForwardSceneFeaturePasses returned false");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (m_gaussianSplatPass != nullptr &&
|
|
||||||
!sceneData.visibleGaussianSplats.empty() &&
|
|
||||||
!m_gaussianSplatPass->PrepareGaussianSplatResources(context, sceneData)) {
|
|
||||||
Debug::Logger::Get().Error(
|
|
||||||
Debug::LogCategory::Rendering,
|
|
||||||
"BuiltinForwardPipeline::Render failed: PrepareGaussianSplatResources returned false");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RenderPassContext passContext = {
|
const RenderPassContext passContext = BuildRenderPassContext(executionContext);
|
||||||
context,
|
|
||||||
surface,
|
|
||||||
sceneData,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
RHI::ResourceStates::Common
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!BeginForwardScenePass(passContext)) {
|
if (!BeginForwardScenePass(passContext)) {
|
||||||
Debug::Logger::Get().Error(
|
Debug::Logger::Get().Error(
|
||||||
@@ -203,53 +176,33 @@ bool BuiltinForwardPipeline::Render(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool sampledDirectionalShadow = ShouldSampleMainDirectionalShadowMap(sceneData);
|
const bool sampledDirectionalShadow =
|
||||||
|
ShouldSampleMainDirectionalShadowMap(executionContext.sceneData);
|
||||||
if (sampledDirectionalShadow) {
|
if (sampledDirectionalShadow) {
|
||||||
TransitionMainDirectionalShadowForSampling(context, sceneData);
|
TransitionMainDirectionalShadowForSampling(
|
||||||
|
executionContext.renderContext,
|
||||||
|
executionContext.sceneData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool renderResult = ExecuteForwardOpaquePass(passContext);
|
const bool renderResult = ExecuteForwardScene(executionContext);
|
||||||
if (renderResult) {
|
|
||||||
renderResult = ExecuteForwardSkyboxPass(passContext);
|
|
||||||
if (!renderResult) {
|
|
||||||
Debug::Logger::Get().Error(
|
|
||||||
Debug::LogCategory::Rendering,
|
|
||||||
"BuiltinForwardPipeline::Render failed: ExecuteForwardSkyboxPass returned false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (renderResult && m_gaussianSplatPass != nullptr) {
|
|
||||||
renderResult = m_gaussianSplatPass->Execute(passContext);
|
|
||||||
if (!renderResult) {
|
|
||||||
Debug::Logger::Get().Error(
|
|
||||||
Debug::LogCategory::Rendering,
|
|
||||||
"BuiltinForwardPipeline::Render failed: BuiltinGaussianSplatPass::Execute returned false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (renderResult && m_volumetricPass != nullptr) {
|
|
||||||
renderResult = m_volumetricPass->Execute(passContext);
|
|
||||||
if (!renderResult) {
|
|
||||||
Debug::Logger::Get().Error(
|
|
||||||
Debug::LogCategory::Rendering,
|
|
||||||
"BuiltinForwardPipeline::Render failed: BuiltinVolumetricPass::Execute returned false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (renderResult) {
|
|
||||||
renderResult = ExecuteForwardTransparentPass(passContext);
|
|
||||||
if (!renderResult) {
|
|
||||||
Debug::Logger::Get().Error(
|
|
||||||
Debug::LogCategory::Rendering,
|
|
||||||
"BuiltinForwardPipeline::Render failed: ExecuteForwardTransparentPass returned false");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sampledDirectionalShadow) {
|
if (sampledDirectionalShadow) {
|
||||||
RestoreMainDirectionalShadowAfterSampling(context, sceneData);
|
RestoreMainDirectionalShadowAfterSampling(
|
||||||
|
executionContext.renderContext,
|
||||||
|
executionContext.sceneData);
|
||||||
}
|
}
|
||||||
EndForwardScenePass(passContext);
|
EndForwardScenePass(passContext);
|
||||||
|
|
||||||
return renderResult;
|
return renderResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BuiltinForwardPipeline::Render(
|
||||||
|
const RenderContext& context,
|
||||||
|
const RenderSurface& surface,
|
||||||
|
const RenderSceneData& sceneData) {
|
||||||
|
return Render(FrameExecutionContext(context, surface, sceneData));
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::BeginForwardScenePass(const RenderPassContext& passContext) {
|
bool BuiltinForwardPipeline::BeginForwardScenePass(const RenderPassContext& passContext) {
|
||||||
const RenderContext& context = passContext.renderContext;
|
const RenderContext& context = passContext.renderContext;
|
||||||
const RenderSurface& surface = passContext.surface;
|
const RenderSurface& surface = passContext.surface;
|
||||||
@@ -358,20 +311,18 @@ void BuiltinForwardPipeline::EndForwardScenePass(const RenderPassContext& passCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(const RenderPassContext& passContext) {
|
bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(
|
||||||
const RenderContext& context = passContext.renderContext;
|
const ScenePhaseExecutionContext& executionContext) {
|
||||||
const RenderSurface& surface = passContext.surface;
|
return DrawVisibleItems(
|
||||||
const RenderSceneData& sceneData = passContext.sceneData;
|
executionContext.frameContext,
|
||||||
|
BuildDrawSettings(executionContext.scenePhase));
|
||||||
return DrawVisibleItems(context, surface, sceneData, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::ExecuteForwardTransparentPass(const RenderPassContext& passContext) {
|
bool BuiltinForwardPipeline::ExecuteForwardTransparentPass(
|
||||||
const RenderContext& context = passContext.renderContext;
|
const ScenePhaseExecutionContext& executionContext) {
|
||||||
const RenderSurface& surface = passContext.surface;
|
return DrawVisibleItems(
|
||||||
const RenderSceneData& sceneData = passContext.sceneData;
|
executionContext.frameContext,
|
||||||
|
BuildDrawSettings(executionContext.scenePhase));
|
||||||
return DrawVisibleItems(context, surface, sceneData, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::EnsureInitialized(const RenderContext& context) {
|
bool BuiltinForwardPipeline::EnsureInitialized(const RenderContext& context) {
|
||||||
@@ -392,6 +343,146 @@ bool BuiltinForwardPipeline::EnsureInitialized(const RenderContext& context) {
|
|||||||
return m_initialized;
|
return m_initialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BuiltinForwardPipeline::ForwardSceneFeaturePassArray
|
||||||
|
BuiltinForwardPipeline::CollectForwardSceneFeaturePasses() const {
|
||||||
|
return {
|
||||||
|
m_gaussianSplatPass.get(),
|
||||||
|
m_volumetricPass.get()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinForwardPipeline::InitializeForwardSceneFeaturePasses(const RenderContext& context) {
|
||||||
|
for (SceneRenderFeaturePass* featurePass : CollectForwardSceneFeaturePasses()) {
|
||||||
|
if (featurePass == nullptr || !featurePass->Initialize(context)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltinForwardPipeline::ShutdownForwardSceneFeaturePasses() {
|
||||||
|
for (SceneRenderFeaturePass* featurePass : CollectForwardSceneFeaturePasses()) {
|
||||||
|
if (featurePass != nullptr) {
|
||||||
|
featurePass->Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinForwardPipeline::PrepareForwardSceneFeaturePasses(
|
||||||
|
const FrameExecutionContext& executionContext) const {
|
||||||
|
for (SceneRenderFeaturePass* featurePass : CollectForwardSceneFeaturePasses()) {
|
||||||
|
if (featurePass == nullptr || !featurePass->IsActive(executionContext.sceneData)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!featurePass->Prepare(
|
||||||
|
executionContext.renderContext,
|
||||||
|
executionContext.sceneData)) {
|
||||||
|
Debug::Logger::Get().Error(
|
||||||
|
Debug::LogCategory::Rendering,
|
||||||
|
(Containers::String("BuiltinForwardPipeline feature prepare failed: ") +
|
||||||
|
featurePass->GetName()).CStr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinForwardPipeline::ExecuteForwardSceneFeaturePasses(
|
||||||
|
const ScenePhaseExecutionContext& executionContext) const {
|
||||||
|
const RenderPassContext passContext = BuildRenderPassContext(executionContext);
|
||||||
|
|
||||||
|
for (SceneRenderFeaturePass* featurePass : CollectForwardSceneFeaturePasses()) {
|
||||||
|
if (featurePass == nullptr ||
|
||||||
|
!featurePass->IsActive(executionContext.frameContext.sceneData)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!featurePass->Execute(passContext)) {
|
||||||
|
Debug::Logger::Get().Error(
|
||||||
|
Debug::LogCategory::Rendering,
|
||||||
|
(Containers::String("BuiltinForwardPipeline feature execute failed: ") +
|
||||||
|
featurePass->GetName()).CStr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScenePhaseExecutionContext BuiltinForwardPipeline::BuildScenePhaseExecutionContext(
|
||||||
|
const FrameExecutionContext& executionContext,
|
||||||
|
ScenePhase scenePhase) const {
|
||||||
|
return ScenePhaseExecutionContext(
|
||||||
|
executionContext,
|
||||||
|
scenePhase,
|
||||||
|
ShouldSampleMainDirectionalShadowMap(executionContext.sceneData));
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSettings BuiltinForwardPipeline::BuildDrawSettings(ScenePhase scenePhase) const {
|
||||||
|
DrawSettings drawSettings = {};
|
||||||
|
drawSettings.scenePhase = scenePhase;
|
||||||
|
switch (scenePhase) {
|
||||||
|
case ScenePhase::Opaque:
|
||||||
|
drawSettings.rendererListType = RendererListType::Opaque;
|
||||||
|
break;
|
||||||
|
case ScenePhase::Transparent:
|
||||||
|
drawSettings.rendererListType = RendererListType::Transparent;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
drawSettings.rendererListType = RendererListType::AllVisible;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return drawSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinForwardPipeline::ExecuteScenePhase(
|
||||||
|
const ScenePhaseExecutionContext& executionContext) {
|
||||||
|
switch (executionContext.scenePhase) {
|
||||||
|
case ScenePhase::Opaque:
|
||||||
|
return ExecuteForwardOpaquePass(executionContext);
|
||||||
|
case ScenePhase::Skybox:
|
||||||
|
return ExecuteForwardSkyboxPass(BuildRenderPassContext(executionContext));
|
||||||
|
case ScenePhase::Feature:
|
||||||
|
return ExecuteForwardSceneFeaturePasses(executionContext);
|
||||||
|
case ScenePhase::Transparent:
|
||||||
|
return ExecuteForwardTransparentPass(executionContext);
|
||||||
|
default:
|
||||||
|
Debug::Logger::Get().Error(
|
||||||
|
Debug::LogCategory::Rendering,
|
||||||
|
(Containers::String("BuiltinForwardPipeline::ExecuteScenePhase does not support scene phase: ") +
|
||||||
|
ToString(executionContext.scenePhase)).CStr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltinForwardPipeline::ExecuteForwardScene(
|
||||||
|
const FrameExecutionContext& executionContext) {
|
||||||
|
static constexpr ScenePhase kForwardScenePhases[] = {
|
||||||
|
ScenePhase::Opaque,
|
||||||
|
ScenePhase::Skybox,
|
||||||
|
ScenePhase::Feature,
|
||||||
|
ScenePhase::Transparent
|
||||||
|
};
|
||||||
|
|
||||||
|
for (ScenePhase scenePhase : kForwardScenePhases) {
|
||||||
|
const ScenePhaseExecutionContext scenePhaseExecutionContext =
|
||||||
|
BuildScenePhaseExecutionContext(executionContext, scenePhase);
|
||||||
|
if (!ExecuteScenePhase(scenePhaseExecutionContext)) {
|
||||||
|
Debug::Logger::Get().Error(
|
||||||
|
Debug::LogCategory::Rendering,
|
||||||
|
(Containers::String("BuiltinForwardPipeline::ExecuteForwardScene failed during phase: ") +
|
||||||
|
ToString(scenePhase)).CStr());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::CreatePipelineResources(const RenderContext& context) {
|
bool BuiltinForwardPipeline::CreatePipelineResources(const RenderContext& context) {
|
||||||
m_builtinForwardShader = Resources::ResourceManager::Get().Load<Resources::Shader>(
|
m_builtinForwardShader = Resources::ResourceManager::Get().Load<Resources::Shader>(
|
||||||
Resources::GetBuiltinForwardLitShaderPath());
|
Resources::GetBuiltinForwardLitShaderPath());
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "RHI/RHICommandList.h"
|
#include "RHI/RHICommandList.h"
|
||||||
#include "RHI/RHIDevice.h"
|
#include "RHI/RHIDevice.h"
|
||||||
#include "Rendering/Builtin/BuiltinPassLayoutUtils.h"
|
#include "Rendering/Builtin/BuiltinPassLayoutUtils.h"
|
||||||
|
#include "Rendering/FrameData/RendererListUtils.h"
|
||||||
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
||||||
#include "Rendering/Internal/ShaderVariantUtils.h"
|
#include "Rendering/Internal/ShaderVariantUtils.h"
|
||||||
#include "Rendering/Materials/RenderMaterialResolve.h"
|
#include "Rendering/Materials/RenderMaterialResolve.h"
|
||||||
@@ -687,10 +688,12 @@ BuiltinForwardPipeline::AdditionalLightConstants BuiltinForwardPipeline::BuildAd
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::DrawVisibleItem(
|
bool BuiltinForwardPipeline::DrawVisibleItem(
|
||||||
const RenderContext& context,
|
const FrameExecutionContext& executionContext,
|
||||||
const RenderSurface& surface,
|
|
||||||
const RenderSceneData& sceneData,
|
|
||||||
const VisibleRenderItem& visibleItem) {
|
const VisibleRenderItem& visibleItem) {
|
||||||
|
const RenderContext& context = executionContext.renderContext;
|
||||||
|
const RenderSurface& surface = executionContext.surface;
|
||||||
|
const RenderSceneData& sceneData = executionContext.sceneData;
|
||||||
|
|
||||||
(void)surface;
|
(void)surface;
|
||||||
const RenderResourceCache::CachedMesh* cachedMesh = m_resourceCache.GetOrCreateMesh(m_device, visibleItem.mesh);
|
const RenderResourceCache::CachedMesh* cachedMesh = m_resourceCache.GetOrCreateMesh(m_device, visibleItem.mesh);
|
||||||
if (cachedMesh == nullptr || cachedMesh->vertexBufferView == nullptr) {
|
if (cachedMesh == nullptr || cachedMesh->vertexBufferView == nullptr) {
|
||||||
@@ -861,36 +864,35 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltinForwardPipeline::DrawVisibleItems(
|
bool BuiltinForwardPipeline::DrawVisibleItems(
|
||||||
const RenderContext& context,
|
const FrameExecutionContext& executionContext,
|
||||||
const RenderSurface& surface,
|
const DrawSettings& drawSettings) {
|
||||||
const RenderSceneData& sceneData,
|
const RenderContext& context = executionContext.renderContext;
|
||||||
bool drawTransparentItems) {
|
const RenderSurface& surface = executionContext.surface;
|
||||||
|
const RenderSceneData& sceneData = executionContext.sceneData;
|
||||||
|
|
||||||
RHI::RHICommandList* commandList = context.commandList;
|
RHI::RHICommandList* commandList = context.commandList;
|
||||||
RHI::RHIPipelineState* currentPipelineState = nullptr;
|
RHI::RHIPipelineState* currentPipelineState = nullptr;
|
||||||
for (const VisibleRenderItem& visibleItem : sceneData.visibleItems) {
|
|
||||||
const bool isTransparentItem = IsTransparentRenderQueue(visibleItem.renderQueue);
|
|
||||||
if (isTransparentItem != drawTransparentItems) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto drawVisibleItem = [&](const VisibleRenderItem& visibleItem) {
|
||||||
const Resources::Material* material = ResolveMaterial(visibleItem);
|
const Resources::Material* material = ResolveMaterial(visibleItem);
|
||||||
BuiltinMaterialPass pass = BuiltinMaterialPass::ForwardLit;
|
BuiltinMaterialPass pass = BuiltinMaterialPass::ForwardLit;
|
||||||
if (!TryResolveSurfacePassType(material, pass)) {
|
if (!TryResolveSurfacePassType(material, pass)) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, surface, sceneData, material);
|
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, surface, sceneData, material);
|
||||||
if (pipelineState == nullptr) {
|
if (pipelineState == nullptr) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
if (pipelineState != currentPipelineState) {
|
if (pipelineState != currentPipelineState) {
|
||||||
commandList->SetPipelineState(pipelineState);
|
commandList->SetPipelineState(pipelineState);
|
||||||
currentPipelineState = pipelineState;
|
currentPipelineState = pipelineState;
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawVisibleItem(context, surface, sceneData, visibleItem);
|
DrawVisibleItem(executionContext, visibleItem);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
VisitRendererListVisibleItems(sceneData, drawSettings.rendererListType, drawVisibleItem);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,11 +81,19 @@ std::vector<CameraRenderRequest> SceneRenderRequestPlanner::BuildRequests(
|
|||||||
? static_cast<float>(surface.GetRenderAreaWidth()) /
|
? static_cast<float>(surface.GetRenderAreaWidth()) /
|
||||||
static_cast<float>(surface.GetRenderAreaHeight())
|
static_cast<float>(surface.GetRenderAreaHeight())
|
||||||
: 1.0f;
|
: 1.0f;
|
||||||
|
DirectionalShadowPlanningSettings effectiveShadowSettings =
|
||||||
|
m_directionalShadowPlanningSettings;
|
||||||
|
if (mainDirectionalLight->GetOverridesDirectionalShadowSettings()) {
|
||||||
|
effectiveShadowSettings.sampling =
|
||||||
|
mainDirectionalLight->GetDirectionalShadowSamplingSettings();
|
||||||
|
effectiveShadowSettings.casterBias =
|
||||||
|
mainDirectionalLight->GetDirectionalShadowCasterBiasSettings();
|
||||||
|
}
|
||||||
request.directionalShadow = Internal::BuildDirectionalShadowRenderPlan(
|
request.directionalShadow = Internal::BuildDirectionalShadowRenderPlan(
|
||||||
scene,
|
scene,
|
||||||
*camera,
|
*camera,
|
||||||
*mainDirectionalLight,
|
*mainDirectionalLight,
|
||||||
m_directionalShadowPlanningSettings,
|
effectiveShadowSettings,
|
||||||
viewportAspect);
|
viewportAspect);
|
||||||
if (request.directionalShadow.IsValid()) {
|
if (request.directionalShadow.IsValid()) {
|
||||||
request.shadowCaster.clearFlags = RenderClearFlags::Depth;
|
request.shadowCaster.clearFlags = RenderClearFlags::Depth;
|
||||||
|
|||||||
Reference in New Issue
Block a user