1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "util/render_util.h"
17
18 #include <algorithm>
19
20 #include <3d/intf_graphics_context.h>
21 #include <3d/render/intf_render_data_store_default_camera.h>
22 #include <core/intf_engine.h>
23 #include <core/json/json.h>
24 #include <core/namespace.h>
25 #include <render/device/intf_device.h>
26 #include <render/device/intf_gpu_resource_manager.h>
27 #include <render/intf_plugin.h>
28 #include <render/intf_render_context.h>
29 #include <render/render_data_structures.h>
30
31 CORE3D_BEGIN_NAMESPACE()
32 using namespace BASE_NS;
33 using namespace CORE_NS;
34 using namespace RENDER_NS;
35
36 namespace {
37 constexpr const string_view SCENE_STR = "3drendernodegraphs://core3d_rng_scene.rng";
38 constexpr const string_view CAM_SCENE_LWRP_STR = "3drendernodegraphs://core3d_rng_cam_scene_lwrp.rng";
39 constexpr const string_view CAM_SCENE_LWRP_MSAA_STR = "3drendernodegraphs://core3d_rng_cam_scene_lwrp_msaa.rng";
40 constexpr const string_view CAM_SCENE_LWRP_MSAA_DEPTH_STR =
41 "3drendernodegraphs://core3d_rng_cam_scene_lwrp_msaa_depth.rng";
42 constexpr const string_view CAM_SCENE_LWRP_MSAA_GLES_STR =
43 "3drendernodegraphs://core3d_rng_cam_scene_lwrp_msaa_gles.rng";
44 constexpr const string_view CAM_SCENE_HDRP_STR = "3drendernodegraphs://core3d_rng_cam_scene_hdrp.rng";
45 constexpr const string_view CAM_SCENE_HDRP_MSAA_STR = "3drendernodegraphs://core3d_rng_cam_scene_hdrp_msaa.rng";
46 constexpr const string_view CAM_SCENE_HDRP_MSAA_DEPTH_STR =
47 "3drendernodegraphs://core3d_rng_cam_scene_hdrp_msaa_depth.rng";
48 constexpr const string_view CAM_SCENE_REFLECTION_STR = "3drendernodegraphs://core3d_rng_reflection_cam_scene.rng";
49 constexpr const string_view CAM_SCENE_REFLECTION_MSAA_STR =
50 "3drendernodegraphs://core3d_rng_reflection_cam_scene_msaa.rng";
51 constexpr const string_view CAM_SCENE_PRE_PASS_STR = "3drendernodegraphs://core3d_rng_cam_scene_pre_pass.rng";
52 constexpr const string_view CAM_SCENE_DEFERRED_STR = "3drendernodegraphs://core3d_rng_cam_scene_deferred.rng";
53 constexpr const string_view CAM_SCENE_POST_PROCESS_STR = "3drendernodegraphs://core3d_rng_cam_scene_post_process.rng";
54
55 constexpr const string_view RENDER_NODE_DEFAULT_CAMERA_CONTROLLER_STR = "RenderNodeDefaultCameraController";
56 constexpr const string_view RENDER_NODE_DEFAULT_MATERIAL_RENDER_SLOT_STR = "RenderNodeDefaultMaterialRenderSlot";
57 constexpr const string_view RENDER_NODE_CAMERA_WEATHER_STR = "RenderNodeCameraWeather";
58
59 constexpr bool ENABLE_WEATHER_INJECT { true };
60
LoadRenderNodeGraph(IRenderNodeGraphLoader & rngLoader,const string_view rng)61 RenderNodeGraphDesc LoadRenderNodeGraph(IRenderNodeGraphLoader& rngLoader, const string_view rng)
62 {
63 IRenderNodeGraphLoader::LoadResult lr = rngLoader.Load(rng);
64 if (!lr.success) {
65 CORE_LOG_E("error loading render node graph: %s - error: %s", rng.data(), lr.error.data());
66 }
67 return lr.desc;
68 }
69
GetDefaultCameraControllerNode()70 inline RenderNodeDesc GetDefaultCameraControllerNode()
71 {
72 RenderNodeDesc rnd;
73 rnd.typeName = RENDER_NODE_DEFAULT_CAMERA_CONTROLLER_STR;
74 rnd.nodeName = "CORE3D_RN_CAM_CTRL";
75 rnd.nodeJson = "{\"typeName\" : \"RenderNodeDefaultCameraController\",\"nodeName\" : \"CORE3D_RN_CAM_CTRL\"}";
76 return rnd;
77 }
78
GetDefaultCameraCloudsNode()79 inline RenderNodeDesc GetDefaultCameraCloudsNode()
80 {
81 RenderNodeDesc rnd;
82 rnd.typeName = RENDER_NODE_CAMERA_WEATHER_STR;
83 rnd.nodeName = "CORE3D_RN_CAM_WEATHER";
84 rnd.nodeJson = "{\"typeName\" : \"RenderNodeCameraWeather\",\"nodeName\" : \"CORE3D_RN_CAM_WEATHER\"}";
85 return rnd;
86 }
87
GetPodPostProcess(const string_view name)88 inline json::standalone_value GetPodPostProcess(const string_view name)
89 {
90 auto renderDataStore = json::standalone_value { json::standalone_value::object {} };
91 renderDataStore["dataStoreName"] = "RenderDataStorePod";
92 renderDataStore["typeName"] = "RenderDataStorePod"; // This is render data store TYPE_NAME
93 renderDataStore["configurationName"] = string(name);
94 return renderDataStore;
95 }
96
GetPostProcess(const string_view name)97 inline json::standalone_value GetPostProcess(const string_view name)
98 {
99 auto renderDataStore = json::standalone_value { json::standalone_value::object {} };
100 renderDataStore["dataStoreName"] = "RenderDataStorePostProcess";
101 renderDataStore["typeName"] = "RenderDataStorePostProcess"; // This is render data store TYPE_NAME
102 renderDataStore["configurationName"] = string(name);
103 return renderDataStore;
104 }
105
HasRenderDataStorePostProcess(const json::standalone_value & dataStore)106 inline bool HasRenderDataStorePostProcess(const json::standalone_value& dataStore)
107 {
108 if (const auto typeName = dataStore.find("typeName"); typeName) {
109 if (typeName->is_string() && (typeName->string_ == "RenderDataStorePostProcess")) {
110 return true;
111 }
112 }
113 return false;
114 }
115
GetCameraName(const RenderCamera & camera)116 inline string GetCameraName(const RenderCamera& camera)
117 {
118 return camera.name.empty() ? string(to_hex(camera.id)) : string(camera.name);
119 }
120
GetSceneName(const RenderScene & scene)121 inline string GetSceneName(const RenderScene& scene)
122 {
123 return scene.name.empty() ? string(to_hex(scene.id)) : string(scene.name);
124 }
125
GetRenderNodesWithDependencies()126 vector<const RENDER_NS::RenderNodeTypeInfo*> GetRenderNodesWithDependencies()
127 {
128 // Gather RenderNodeTypeInfo which have after of before dependencies.
129 vector<const RENDER_NS::RenderNodeTypeInfo*> renderNodesWithDependencies;
130 auto typeInfos = CORE_NS::GetPluginRegister().GetTypeInfos(RENDER_NS::RenderNodeTypeInfo::UID);
131 for (auto* info : typeInfos) {
132 if (info && (info->typeUid == RenderNodeTypeInfo::UID)) {
133 auto* renderNodeTypeInfo = static_cast<const RenderNodeTypeInfo*>(info);
134 if ((renderNodeTypeInfo->afterNode != Uid {}) || (renderNodeTypeInfo->beforeNode != Uid {})) {
135 renderNodesWithDependencies.push_back(renderNodeTypeInfo);
136 }
137 }
138 }
139 return renderNodesWithDependencies;
140 }
141
InjectRenderNodes(RenderNodeGraphDesc & desc)142 void InjectRenderNodes(RenderNodeGraphDesc& desc)
143 {
144 const auto typeInfos = CORE_NS::GetPluginRegister().GetTypeInfos(RENDER_NS::RenderNodeTypeInfo::UID);
145 const auto renderNodeTypeInfos =
146 array_view(reinterpret_cast<const RenderNodeTypeInfo* const*>(typeInfos.data()), typeInfos.size());
147 const auto renderNodesWithDependencies = GetRenderNodesWithDependencies();
148 for (const auto* depending : renderNodesWithDependencies) {
149 // Try adding only if node isn't already there.
150 if (std::any_of(desc.nodes.cbegin(), desc.nodes.cend(),
151 [typeName = depending->typeName](const RenderNodeDesc& desc) { return desc.typeName == typeName; })) {
152 continue;
153 }
154
155 ptrdiff_t index = -1;
156
157 // Find the insertion index based on afterNode
158 if (depending->afterNode != Uid {}) {
159 // Find the typeinfo of the dependency UID
160 auto info = std::find_if(renderNodeTypeInfos.cbegin(), renderNodeTypeInfos.cend(),
161 [uid = depending->afterNode](const RenderNodeTypeInfo* info) { return info->uid == uid; });
162 if (info != renderNodeTypeInfos.cend()) {
163 // Find the last instance matching dependency typeName
164 auto graphIt = std::find_if(desc.nodes.crbegin(), desc.nodes.crend(),
165 [typeName = (*info)->typeName](const RenderNodeDesc& desc) { return desc.typeName == typeName; });
166 if (graphIt != desc.nodes.crend()) {
167 index = graphIt.base() - desc.nodes.cbegin();
168 }
169 }
170 }
171
172 // Find the insertion index based on beforeNode
173 if (depending->beforeNode != Uid {}) {
174 // Find the typeinfo of the dependency UID
175 auto info = std::find_if(renderNodeTypeInfos.cbegin(), renderNodeTypeInfos.cend(),
176 [uid = depending->beforeNode](const RenderNodeTypeInfo* info) { return info->uid == uid; });
177 if (info != renderNodeTypeInfos.cend()) {
178 // Find the last instance matching dependency typeName
179 auto graphIt = std::find_if(desc.nodes.crbegin(), desc.nodes.crend(),
180 [typeName = (*info)->typeName](const RenderNodeDesc& desc) { return desc.typeName == typeName; });
181 if (graphIt != desc.nodes.crend()) {
182 index = graphIt.base() - desc.nodes.cbegin();
183 }
184 }
185 }
186
187 // If no valid index found, continue to the next node
188 if (index < 0 || size_t(index) > desc.nodes.size()) {
189 continue;
190 }
191
192 // Create the new render node descriptor
193 json::standalone_value jsonVal(json::standalone_value::object {});
194 jsonVal["typeName"] = depending->typeName;
195 auto nodeName = RenderDataConstants::RenderDataFixedString("CORE3D_RN_SCENE_") + depending->typeName;
196 jsonVal["nodeName"] = nodeName.data();
197 desc.nodes.insert(
198 desc.nodes.cbegin() + index, RenderNodeDesc { depending->typeName, nodeName, {}, to_string(jsonVal) });
199 }
200 }
201
FillCameraDescsData(const RenderCamera & renderCamera,const string & customCameraName,RenderNodeGraphDesc & desc)202 void FillCameraDescsData(const RenderCamera& renderCamera, const string& customCameraName, RenderNodeGraphDesc& desc)
203 {
204 // check for render compatibility for render node graph RenderNodeDefaultCameraController
205 if (!renderCamera.customRenderNodeGraphFile.empty()) {
206 bool forceInject = true;
207 for (const auto& rnRef : desc.nodes) {
208 if (rnRef.typeName == RENDER_NODE_DEFAULT_CAMERA_CONTROLLER_STR) {
209 forceInject = false;
210 break;
211 }
212 }
213 if (forceInject) {
214 for (size_t nodeIdx = 0; nodeIdx < desc.nodes.size(); ++nodeIdx) {
215 if (desc.nodes[nodeIdx].typeName == RENDER_NODE_DEFAULT_MATERIAL_RENDER_SLOT_STR) {
216 desc.nodes.insert(desc.nodes.begin() + int64_t(nodeIdx), GetDefaultCameraControllerNode());
217 #if (CORE3D_DEV_ENABLED == 1)
218 CORE_LOG_W("Injecting camera RenderNodeDefaultCameraController render node for compatibility");
219 #endif
220 break;
221 }
222 }
223 }
224 }
225
226 // inject camera weather effect render node (for e.g. clouds) after camera controller
227 if constexpr (ENABLE_WEATHER_INJECT) {
228 if (renderCamera.environment.flags & RenderCamera::Environment::ENVIRONMENT_FLAG_CAMERA_WEATHER_BIT) {
229 for (size_t nodeIdx = 0; nodeIdx < desc.nodes.size(); ++nodeIdx) {
230 if (desc.nodes[nodeIdx].typeName == RENDER_NODE_DEFAULT_CAMERA_CONTROLLER_STR) {
231 desc.nodes.insert(desc.nodes.begin() + int64_t(nodeIdx + 1), GetDefaultCameraCloudsNode());
232 #if (CORE3D_DEV_ENABLED == 1)
233 CORE_LOG_I("Injecting camera RenderNodeCameraWeather render node");
234 #endif
235 break;
236 }
237 }
238 }
239 }
240 InjectRenderNodes(desc);
241
242 for (auto& rnRef : desc.nodes) {
243 json::standalone_value jsonVal = CORE_NS::json::parse(rnRef.nodeJson.data());
244 jsonVal["customCameraId"] = renderCamera.id; // cam id
245 jsonVal["customCameraName"] = customCameraName;
246 if (renderCamera.flags & RenderCamera::CAMERA_FLAG_REFLECTION_BIT) {
247 jsonVal["nodeFlags"] = 7u; // NOTE: hard coded
248 }
249 if (auto dataStore = jsonVal.find("renderDataStore"); dataStore) {
250 if (auto config = dataStore->find("configurationName"); config) {
251 if (!config->string_.empty()) {
252 const bool rpp = HasRenderDataStorePostProcess(*dataStore);
253 auto renderDataStore = rpp ? GetPostProcess(renderCamera.postProcessName)
254 : GetPodPostProcess(renderCamera.postProcessName);
255 jsonVal["renderDataStore"] = move(renderDataStore);
256 }
257 }
258 }
259 rnRef.nodeJson = to_string(jsonVal);
260 }
261 }
262
FillCameraPostProcessDescsData(const RenderCamera & renderCamera,const uint64_t baseCameraId,const string & customCameraName,const bool customPostProcess,RenderNodeGraphDesc & desc)263 void FillCameraPostProcessDescsData(const RenderCamera& renderCamera, const uint64_t baseCameraId,
264 const string& customCameraName, const bool customPostProcess, RenderNodeGraphDesc& desc)
265 {
266 InjectRenderNodes(desc);
267
268 for (auto& rnRef : desc.nodes) {
269 json::standalone_value jsonVal = CORE_NS::json::parse(rnRef.nodeJson.data());
270 // add camera info as well
271 jsonVal["customCameraId"] = renderCamera.id; // cam id
272 jsonVal["customCameraName"] = customCameraName;
273 jsonVal["multiviewBaseCameraId"] = baseCameraId;
274 if (auto dataStore = jsonVal.find("renderDataStore"); dataStore) {
275 if (auto config = dataStore->find("configurationName"); config) {
276 if (config->is_string() && (!config->string_.empty())) {
277 const bool rpp = customPostProcess || HasRenderDataStorePostProcess(*dataStore);
278 auto renderDataStore = rpp ? GetPostProcess(renderCamera.postProcessName)
279 : GetPodPostProcess(renderCamera.postProcessName);
280 jsonVal["renderDataStore"] = move(renderDataStore);
281 }
282 }
283 }
284 rnRef.nodeJson = to_string(jsonVal);
285 }
286 }
287 } // namespace
288
RenderUtil(IGraphicsContext & graphicsContext)289 RenderUtil::RenderUtil(IGraphicsContext& graphicsContext)
290 : context_(graphicsContext.GetRenderContext()), backendType_(context_.GetDevice().GetBackendType())
291 {
292 InitRenderNodeGraphs();
293 }
294
InitRenderNodeGraphs()295 void RenderUtil::InitRenderNodeGraphs()
296 {
297 IRenderNodeGraphManager& rngm = context_.GetRenderNodeGraphManager();
298 IRenderNodeGraphLoader& rngl = rngm.GetRenderNodeGraphLoader();
299
300 rngdScene_ = LoadRenderNodeGraph(rngl, SCENE_STR);
301 rngdCamLwrp_ = LoadRenderNodeGraph(rngl, CAM_SCENE_LWRP_STR);
302 rngdCamLwrpMsaa_ = LoadRenderNodeGraph(rngl, CAM_SCENE_LWRP_MSAA_STR);
303 rngdCamLwrpMsaaDepth_ = LoadRenderNodeGraph(rngl, CAM_SCENE_LWRP_MSAA_DEPTH_STR);
304 rngdCamLwrpMsaaGles_ = LoadRenderNodeGraph(rngl, CAM_SCENE_LWRP_MSAA_GLES_STR);
305 rngdCamHdr_ = LoadRenderNodeGraph(rngl, CAM_SCENE_HDRP_STR);
306 rngdCamHdrMsaa_ = LoadRenderNodeGraph(rngl, CAM_SCENE_HDRP_MSAA_STR);
307 rngdCamHdrMsaaDepth_ = LoadRenderNodeGraph(rngl, CAM_SCENE_HDRP_MSAA_DEPTH_STR);
308 rngdReflCam_ = LoadRenderNodeGraph(rngl, CAM_SCENE_REFLECTION_STR);
309 rngdReflCamMsaa_ = LoadRenderNodeGraph(rngl, CAM_SCENE_REFLECTION_MSAA_STR);
310 rngdCamPrePass_ = LoadRenderNodeGraph(rngl, CAM_SCENE_PRE_PASS_STR);
311
312 rngdDeferred_ = LoadRenderNodeGraph(rngl, CAM_SCENE_DEFERRED_STR);
313
314 rngdPostProcess_ = LoadRenderNodeGraph(rngl, CAM_SCENE_POST_PROCESS_STR);
315 }
316
SelectBaseDesc(const RenderCamera & renderCamera) const317 RenderNodeGraphDesc RenderUtil::SelectBaseDesc(const RenderCamera& renderCamera) const
318 {
319 if (!renderCamera.customRenderNodeGraphFile.empty()) {
320 // custom render node graph file given which is patched
321 IRenderNodeGraphLoader& rngl = context_.GetRenderNodeGraphManager().GetRenderNodeGraphLoader();
322 return LoadRenderNodeGraph(rngl, renderCamera.customRenderNodeGraphFile);
323 }
324
325 if (renderCamera.flags & RenderCamera::CAMERA_FLAG_REFLECTION_BIT) {
326 // check for msaa
327 return (renderCamera.flags & RenderCamera::CAMERA_FLAG_MSAA_BIT) ? rngdReflCamMsaa_ : rngdReflCam_;
328 }
329 if (renderCamera.flags & RenderCamera::CAMERA_FLAG_OPAQUE_BIT) {
330 return rngdCamPrePass_;
331 }
332 if (renderCamera.renderPipelineType == RenderCamera::RenderPipelineType::DEFERRED) {
333 return rngdDeferred_;
334 }
335 if (renderCamera.flags & RenderCamera::CAMERA_FLAG_MSAA_BIT) {
336 // NOTE: check for optimal GL(ES) render node graph if backbuffer is multisampled
337 const bool depthOutput =
338 ((renderCamera.flags & RenderCamera::CameraFlagBits::CAMERA_FLAG_OUTPUT_DEPTH_BIT) != 0U);
339 if (renderCamera.renderPipelineType != RenderCamera::RenderPipelineType::LIGHT_FORWARD) {
340 return depthOutput ? rngdCamHdrMsaaDepth_ : rngdCamHdrMsaa_;
341 }
342
343 if ((backendType_ == DeviceBackendType::VULKAN) ||
344 (renderCamera.flags & RenderCamera::CameraFlagBits::CAMERA_FLAG_CUSTOM_TARGETS_BIT)) {
345 return depthOutput ? rngdCamLwrpMsaaDepth_ : rngdCamLwrpMsaa_;
346 }
347 const auto& gpuResourceMgr = context_.GetDevice().GetGpuResourceManager();
348 // NOTE: special handling on msaa swapchain with GLES
349 // creates issues with multi-ECS cases and might need to be dropped
350 // Prefer assigning swapchain image to camera in this case
351 const RenderHandleReference imageHandle = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_BACKBUFFER");
352 const GpuImageDesc imageDesc = gpuResourceMgr.GetImageDescriptor(imageHandle);
353 if ((renderCamera.flags & RenderCamera::CAMERA_FLAG_MAIN_BIT) && (imageDesc.sampleCountFlags > 1) &&
354 (!depthOutput)) {
355 #if (CORE3D_VALIDATION_ENABLED == 1)
356 CORE_LOG_ONCE_I("3d_util_depth_gles_mixing" + to_string(renderCamera.id),
357 "CORE3D_VALIDATION: GL(ES) Camera MSAA flags checked from CORE_DEFAULT_BACKBUFFER. "
358 "Prefer assigning swapchain handle to camera.");
359 #endif
360 return rngdCamLwrpMsaaGles_;
361 }
362 return depthOutput ? rngdCamLwrpMsaaDepth_ : rngdCamLwrpMsaa_;
363 }
364 if (renderCamera.renderPipelineType != RenderCamera::RenderPipelineType::LIGHT_FORWARD) {
365 return rngdCamHdr_;
366 }
367 return rngdCamLwrp_;
368 }
369
GetBasePostProcessDesc(const RenderCamera & renderCamera) const370 RenderNodeGraphDesc RenderUtil::GetBasePostProcessDesc(const RenderCamera& renderCamera) const
371 {
372 // light forward and opaque / pre-pass camera does not have separate post processes
373 if ((renderCamera.renderPipelineType != RenderCamera::RenderPipelineType::LIGHT_FORWARD) &&
374 ((renderCamera.flags & RenderCamera::CAMERA_FLAG_OPAQUE_BIT) == 0)) {
375 return rngdPostProcess_;
376 } else {
377 return {};
378 }
379 }
380
GetRenderNodeGraphDesc(const RenderScene & renderScene,const RenderCamera & renderCamera,const uint32_t flags) const381 RenderNodeGraphDesc RenderUtil::GetRenderNodeGraphDesc(
382 const RenderScene& renderScene, const RenderCamera& renderCamera, const uint32_t flags) const
383 {
384 const string customCameraName = GetCameraName(renderCamera);
385 RenderNodeGraphDesc desc = SelectBaseDesc(renderCamera);
386 // process
387 desc.renderNodeGraphName = renderScene.name + to_hex(renderCamera.id);
388 FillCameraDescsData(renderCamera, customCameraName, desc);
389 return desc;
390 }
391
GetRenderNodeGraphDescs(const RenderScene & renderScene,const RenderCamera & renderCamera,const uint32_t flags,const array_view<const RenderCamera> multiviewCameras) const392 IRenderUtil::CameraRenderNodeGraphDescs RenderUtil::GetRenderNodeGraphDescs(const RenderScene& renderScene,
393 const RenderCamera& renderCamera, const uint32_t flags, const array_view<const RenderCamera> multiviewCameras) const
394 {
395 // Gets RenderNodeGraphDescs for camera and patches
396 // 1. With built-in RNGs
397 // * Select RNG for camera
398 // * Select RNG for camera post process (if not LIGHT_FORWARD)
399 // 2. With built-in RNG for camera and custom for post process
400 // * Select RNG for camera
401 // * Load RNG for camera post process
402 // 3. With custom RNG for camera
403 // * Load RNG for camera
404 // * Load RNG for camera post process, only if custom given
405 // NOTE: special opaque / pre-pass camera (transmission) has built-in post process in RNG
406
407 const string customCameraName = GetCameraName(renderCamera);
408 IRenderUtil::CameraRenderNodeGraphDescs descs;
409 // process camera
410 {
411 auto& desc = descs.camera;
412 desc = SelectBaseDesc(renderCamera);
413 desc.renderNodeGraphName = renderScene.name + to_hex(renderCamera.id);
414 FillCameraDescsData(renderCamera, customCameraName, desc);
415 }
416 // process post process
417 // NOTE: we do not add base post process render node graph to custom camera render node graphs
418 {
419 // NOTE: currently there are separate paths for new post process configurations and old
420 auto& desc = descs.postProcess;
421 const bool customPostProcess = !renderCamera.customPostProcessRenderNodeGraphFile.empty();
422 if (customPostProcess) {
423 IRenderNodeGraphLoader& rngl = context_.GetRenderNodeGraphManager().GetRenderNodeGraphLoader();
424 desc = LoadRenderNodeGraph(rngl, renderCamera.customPostProcessRenderNodeGraphFile);
425 } else if (renderCamera.customRenderNodeGraphFile.empty()) {
426 // only fetched when using built-in camera RNGs
427 desc = GetBasePostProcessDesc(renderCamera);
428 }
429 if (!desc.nodes.empty()) {
430 desc.renderNodeGraphName = renderScene.name + to_hex(renderCamera.id);
431 FillCameraPostProcessDescsData(
432 renderCamera, RenderSceneDataConstants::INVALID_ID, customCameraName, customPostProcess, desc);
433 }
434 #if (CORE3D_VALIDATION_ENABLED == 1)
435 if (renderCamera.multiViewCameraCount != static_cast<uint32_t>(multiviewCameras.size())) {
436 CORE_LOG_W("CORE3D_VALIDATION: Multi-view camera count mismatch in render node graph creation.");
437 }
438 #endif
439 // multi-view camera post processes
440 if (renderCamera.multiViewCameraCount == static_cast<uint32_t>(multiviewCameras.size())) {
441 #if (CORE3D_VALIDATION_ENABLED == 1)
442 if (!renderCamera.customPostProcessRenderNodeGraphFile.empty()) {
443 CORE_LOG_W("CORE3D_VALIDATION: Multi-view camera custom post process render node graph not supported.");
444 }
445 #endif
446 CORE_ASSERT(descs.multiViewCameraCount <= countof(descs.multiViewCameraPostProcesses));
447 descs.multiViewCameraCount = renderCamera.multiViewCameraCount;
448 for (size_t mvIdx = 0; mvIdx < descs.multiViewCameraCount; ++mvIdx) {
449 const auto& mvCameraRef = multiviewCameras[mvIdx];
450 auto& ppDesc = descs.multiViewCameraPostProcesses[mvIdx];
451 ppDesc = GetBasePostProcessDesc(mvCameraRef);
452 if (!ppDesc.nodes.empty()) {
453 const string ppCustomCameraName = GetCameraName(mvCameraRef);
454 ppDesc.renderNodeGraphName = renderScene.name + to_hex(mvCameraRef.id);
455 FillCameraPostProcessDescsData(mvCameraRef, renderCamera.id, ppCustomCameraName, false, ppDesc);
456 }
457 }
458 }
459 }
460
461 return descs;
462 }
463
GetRenderNodeGraphDescs(const RenderScene & renderScene,const RenderCamera & renderCamera,const uint32_t flags) const464 IRenderUtil::CameraRenderNodeGraphDescs RenderUtil::GetRenderNodeGraphDescs(
465 const RenderScene& renderScene, const RenderCamera& renderCamera, const uint32_t flags) const
466 {
467 return GetRenderNodeGraphDescs(renderScene, renderCamera, flags, {});
468 }
469
GetRenderNodeGraphDesc(const RenderScene & renderScene,const uint32_t flags) const470 RenderNodeGraphDesc RenderUtil::GetRenderNodeGraphDesc(const RenderScene& renderScene, const uint32_t flags) const
471 {
472 RenderNodeGraphDesc desc;
473 if (!renderScene.customRenderNodeGraphFile.empty()) {
474 // custom render node graph file given which is patched
475 IRenderNodeGraphLoader& rngl = context_.GetRenderNodeGraphManager().GetRenderNodeGraphLoader();
476 desc = LoadRenderNodeGraph(rngl, renderScene.customRenderNodeGraphFile);
477 } else {
478 desc = rngdScene_;
479 }
480
481 InjectRenderNodes(desc);
482
483 const string customSceneName = GetSceneName(renderScene);
484 const auto sceneIdStr = to_hex(renderScene.id);
485 const auto combinedStr = renderScene.name + sceneIdStr;
486 desc.renderNodeGraphName = combinedStr;
487 for (auto& rnRef : desc.nodes) {
488 json::standalone_value jsonVal = CORE_NS::json::parse(rnRef.nodeJson.data());
489 jsonVal[string_view("customId")] = renderScene.id; // cam id
490 jsonVal[string_view("customName")] = customSceneName;
491 rnRef.nodeJson = to_string(jsonVal);
492 }
493 return desc;
494 }
495
GetRenderNodeGraphDesc(const RenderScene & renderScene,const string & rngFile,const uint32_t flags) const496 RenderNodeGraphDesc RenderUtil::GetRenderNodeGraphDesc(
497 const RenderScene& renderScene, const string& rngFile, const uint32_t flags) const
498 {
499 RenderNodeGraphDesc desc;
500 if (!rngFile.empty()) {
501 // custom render node graph file given which is patched
502 IRenderNodeGraphLoader& rngl = context_.GetRenderNodeGraphManager().GetRenderNodeGraphLoader();
503 desc = LoadRenderNodeGraph(rngl, rngFile);
504 } else {
505 desc = rngdScene_;
506 }
507
508 InjectRenderNodes(desc);
509
510 const string customSceneName = GetSceneName(renderScene);
511 const auto sceneIdStr = to_hex(renderScene.id);
512 const auto combinedStr = renderScene.name + sceneIdStr;
513 desc.renderNodeGraphName = combinedStr;
514 for (auto& rnRef : desc.nodes) {
515 json::standalone_value jsonVal = CORE_NS::json::parse(rnRef.nodeJson.data());
516 jsonVal[string_view("customId")] = renderScene.id;
517 jsonVal[string_view("customName")] = customSceneName;
518 rnRef.nodeJson = to_string(jsonVal);
519 }
520 return desc;
521 }
522 CORE3D_END_NAMESPACE()
523