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 "render_node_camera_weather.h"
17
18 #include <3d/implementation_uids.h>
19 #include <3d/render/intf_render_data_store_default_camera.h>
20 #include <3d/render/intf_render_data_store_default_light.h>
21 #include <3d/render/intf_render_data_store_default_scene.h>
22 #include <render/datastore/intf_render_data_store_manager.h>
23 #include <render/datastore/intf_render_data_store_pod.h>
24 #include <render/intf_render_context.h>
25 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
26 #include <render/nodecontext/intf_render_node_context_manager.h>
27 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
28 #include <render/nodecontext/intf_render_node_parser_util.h>
29 #include <render/nodecontext/intf_render_node_util.h>
30
31 #include "render/datastore/render_data_store_weather.h"
32 #include "render/shaders/common/render_post_process_structs_common.h"
33
34 using namespace BASE_NS;
35 using namespace CORE_NS;
36 using namespace RENDER_NS;
37
38 constexpr bool ENABLE_ADDITIONAL { false };
39
40 CORE3D_BEGIN_NAMESPACE()
41 struct RenderNodeCameraWeather::Settings {
42 BASE_NS::Math::Vec4 params[7];
43 BASE_NS::Math::Vec4 padding[16 - 7];
44 };
45
46 namespace {
47 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
48
49 constexpr Math::Vec4 DEBUG_MARKER_COLOR { 0.5f, 0.75f, 0.75f, 1.0f };
50
51 template<typename T>
CreateCloudDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)52 RenderHandleReference CreateCloudDataUniformBuffer(
53 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
54 {
55 CORE_STATIC_ASSERT(sizeof(T) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
56 return gpuResourceMgr.Create(
57 handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
58 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
59 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER, sizeof(T) });
60 }
61 } // namespace
62
InitNode(IRenderNodeContextManager & renderNodeContextMgr)63 void RenderNodeCameraWeather::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
64 {
65 renderNodeContextMgr_ = &renderNodeContextMgr;
66 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
67
68 ParseRenderNodeInputs();
69
70 const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
71 CORE_NS::IClassRegister *cr = renderNodeContextMgr_->GetRenderContext().GetInterface<IClassRegister>();
72 if (cr != nullptr) {
73 if (renderNodeSceneUtil_ = CORE_NS::GetInstance<IRenderNodeSceneUtil>(*cr, UID_RENDER_NODE_SCENE_UTIL);
74 renderNodeSceneUtil_) {
75 stores_ = renderNodeSceneUtil_->GetSceneRenderDataStores(renderNodeContextMgr,
76 renderNodeGraphData.renderNodeGraphDataStoreName);
77 dsWeatherName_ = renderNodeSceneUtil_->GetSceneRenderDataStore(stores_, RenderDataStoreWeather::TYPE_NAME);
78
79 GetSceneUniformBuffers(stores_.dataStoreNameScene);
80 }
81 } else {
82 CORE_LOG_E("get null ClassRegister");
83 }
84 currentScene_ = {};
85
86 valid_ = true;
87 clear_ = true;
88 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
89
90 GpuSamplerDesc desc {};
91 desc.minFilter = Filter::CORE_FILTER_LINEAR;
92 desc.mipMapMode = Filter::CORE_FILTER_NEAREST;
93 desc.magFilter = Filter::CORE_FILTER_LINEAR;
94 desc.enableAnisotropy = false;
95 desc.maxAnisotropy = 1;
96 desc.minLod = 0;
97 desc.maxLod = 0;
98 desc.addressModeU = SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT;
99 desc.addressModeV = SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT;
100 desc.addressModeW = SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_REPEAT;
101 volumeSampler_ = gpuResourceMgr.Create(desc);
102
103 desc.minFilter = Filter::CORE_FILTER_LINEAR;
104 desc.mipMapMode = Filter::CORE_FILTER_NEAREST;
105 desc.magFilter = Filter::CORE_FILTER_LINEAR;
106 desc.enableAnisotropy = false;
107 desc.maxAnisotropy = 1;
108 desc.minLod = 0;
109 desc.maxLod = 0;
110 desc.borderColor = Render::BorderColor::CORE_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
111 desc.addressModeU = SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
112 desc.addressModeV = SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
113 desc.addressModeW = SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
114 weatherSampler_ = gpuResourceMgr.Create(desc);
115
116 builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
117
118 skyTex_ = gpuResourceMgr.GetImageHandle("CORE_DEFAULT_GPU_IMAGE");
119
120 if (renderNodeSceneUtil_) {
121 const auto camHandles = renderNodeSceneUtil_->GetSceneCameraImageHandles(
122 *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
123 currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
124 }
125
126 vector<DescriptorCounts> descriptorCounts;
127 Load("3dshaders://shader/clouds/cloud_volumes.shader", descriptorCounts, cloudVolumeShaderData_, DYNAMIC_STATES, 1);
128
129 Load("3dshaders://shader/clouds/upsample.shader", descriptorCounts, upsampleData1_, DYNAMIC_STATES, 1);
130 Load("3dshaders://shader/clouds/upsample2.shader", descriptorCounts, upsampleData2_, DYNAMIC_STATES, 1);
131
132 renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(descriptorCounts);
133
134 cloudVolumeBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(cloudVolumeShaderData_.pipelineLayoutData);
135 upsample1Binder = renderNodeUtil.CreatePipelineDescriptorSetBinder(upsampleData1_.pipelineLayoutData);
136 upsample2Binder = renderNodeUtil.CreatePipelineDescriptorSetBinder(upsampleData2_.pipelineLayoutData);
137
138 isDefaultImageInUse_ = false;
139
140 // get camera ubo
141 {
142 cameraUboHandle_ = gpuResourceMgr.GetBufferHandle(
143 stores_.dataStoreNameScene + DefaultMaterialCameraConstants::CAMERA_DATA_BUFFER_NAME);
144 }
145
146 uniformBuffer_ = CreateCloudDataUniformBuffer<Settings>(gpuResourceMgr, uniformBuffer_);
147 }
148
149 struct RenderNodeCameraWeather::GlobalFrameData {
150 float time { 0.0f };
151 };
152
PreExecuteFrame()153 void RenderNodeCameraWeather::PreExecuteFrame()
154 {
155 {
156 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
157 const auto* dataStoreScene = static_cast<IRenderDataStoreDefaultScene*>(
158 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
159 const auto* dataStoreCamera = static_cast<IRenderDataStoreDefaultCamera*>(
160 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
161 const auto* dataStoreLight = static_cast<IRenderDataStoreDefaultLight*>(
162 renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
163 const auto* dataStoreWeather =
164 static_cast<RenderDataStoreWeather*>(renderDataStoreMgr.GetRenderDataStore(dsWeatherName_));
165 const bool validRenderDataStore = dataStoreScene && dataStoreCamera && dataStoreLight && dataStoreWeather;
166 if (validRenderDataStore) {
167 UpdateCurrentScene(*dataStoreScene, *dataStoreCamera, *dataStoreLight);
168
169 settings_ = dataStoreWeather->GetWeatherSettings();
170 downscale_ = (int32_t)settings_.cloudRenderingType;
171 }
172 }
173 }
174
ExecuteFrame(IRenderCommandList & cmdList)175 void RenderNodeCameraWeather::ExecuteFrame(IRenderCommandList& cmdList)
176 {
177 lowFrequencyTex_ = settings_.lowFrequencyImage;
178 highFrequencyTex_ = settings_.highFrequencyImage;
179 curlnoiseTex_ = settings_.curlNoiseImage;
180 cirrusTex_ = settings_.cirrusImage;
181 weatherMapTex_ = settings_.weatherMapImage;
182
183 cloudTexture_ = renderNodeContextMgr_->GetGpuResourceManager().GetImageHandle(
184 DefaultMaterialCameraConstants::CAMERA_COLOR_PREFIX_NAME + "CLOUD");
185 cloudTexturePrev_ = renderNodeContextMgr_->GetGpuResourceManager().GetImageHandle(
186 DefaultMaterialCameraConstants::CAMERA_COLOR_PREFIX_NAME + "CLOUD_PREV");
187
188 [this]() {
189 auto& b = cloudVolumeBinder_;
190 uint32_t binding = 0;
191 b->BindSampler(0, binding++, { builtInVariables_.defSampler });
192 b->BindImage(0, binding++, { skyTex_ });
193 b->BindSampler(0, binding++, { volumeSampler_.GetHandle() });
194 b->BindImage(0, binding++, { lowFrequencyTex_ });
195 b->BindImage(0, binding++, { highFrequencyTex_ });
196 b->BindImage(0, binding++, { curlnoiseTex_ });
197 b->BindBuffer(0, binding++, { uniformBuffer_.GetHandle() });
198 b->BindSampler(0, binding++, { weatherSampler_.GetHandle() });
199 b->BindImage(0, binding++, { cirrusTex_ });
200 }();
201
202 if constexpr (ENABLE_ADDITIONAL) {
203 [this]() {
204 auto& b = upsample2Binder;
205 uint32_t binding = 0;
206 b->BindSampler(0, binding++, { builtInVariables_.defSampler });
207 b->BindBuffer(0, binding++, { uniformBuffer_.GetHandle() });
208 b->BindBuffer(0, binding++, { cameraUboHandle_ });
209 }();
210
211 [this]() {
212 auto& b = upsample1Binder;
213 uint32_t binding = 0;
214 b->BindSampler(0, binding++, { builtInVariables_.defSampler });
215 b->BindBuffer(0, binding++, { uniformBuffer_.GetHandle() });
216 b->BindBuffer(0, binding++, { cameraUboHandle_ });
217 }();
218 }
219
220 const auto sHash = BASE_NS::FNV1a32Hash(reinterpret_cast<const uint8_t*>(&settings_), sizeof(settings_));
221 if (uniformHash_ != sHash) {
222 uniformHash_ = sHash;
223 Settings uniformSettings;
224 uniformSettings.params[0U].x = settings_.coverage;
225 uniformSettings.params[0U].y = settings_.precipitation;
226 uniformSettings.params[0U].z = settings_.cloudType;
227 uniformSettings.params[0U].w = settings_.domain[0U];
228
229 uniformSettings.params[1U].x = currentScene_.camera.zNear;
230 uniformSettings.params[1U].y = currentScene_.camera.zFar;
231 uniformSettings.params[1U].z = settings_.silverIntensity;
232 uniformSettings.params[1U].w = settings_.silverSpread;
233
234 uniformSettings.params[2U].x = settings_.sunPos[0U];
235 uniformSettings.params[2U].y = settings_.sunPos[1U];
236 uniformSettings.params[2U].z = settings_.sunPos[2U];
237 uniformSettings.params[2U].w = settings_.domain[1U];
238
239 uniformSettings.params[3U].x = settings_.atmosphereColor[0U];
240 uniformSettings.params[3U].y = settings_.atmosphereColor[1U];
241 uniformSettings.params[3U].z = settings_.atmosphereColor[2U];
242 uniformSettings.params[3U].w = settings_.domain[2U];
243
244 uniformSettings.params[4U].x = settings_.anvil_bias;
245 uniformSettings.params[4U].y = settings_.brightness;
246 uniformSettings.params[4U].z = settings_.eccintricity;
247 uniformSettings.params[4U].w = settings_.domain[3U];
248
249 uniformSettings.params[5U].x = settings_.ambient;
250 uniformSettings.params[5U].y = settings_.direct;
251 uniformSettings.params[5U].z = settings_.lightStep;
252 uniformSettings.params[5U].w = settings_.scatteringDist;
253
254 uniformSettings.params[6U].w = settings_.domain[4U];
255
256 UpdateBufferData<Settings>(
257 renderNodeContextMgr_->GetGpuResourceManager(), uniformBuffer_.GetHandle(), uniformSettings);
258 }
259
260 GlobalFrameData data {};
261 data.time = renderNodeContextMgr_->GetRenderNodeGraphData().renderingConfiguration.renderTimings.z;
262 cameraUboHandle_ = renderNodeContextMgr_->GetGpuResourceManager().GetBufferHandle(
263 stores_.dataStoreNameScene + DefaultMaterialCameraConstants::CAMERA_DATA_BUFFER_NAME);
264
265 {
266 // NOTE: Need to be update every frame if cannot be sure (descriptor set manager tries to optimize not needed
267 // bindings)
268 cmdList.UpdateDescriptorSet(cloudVolumeBinder_->GetDescriptorSetHandle(0),
269 cloudVolumeBinder_->GetDescriptorSetLayoutBindingResources(0));
270 if constexpr (ENABLE_ADDITIONAL) {
271 cmdList.UpdateDescriptorSet(
272 upsample1Binder->GetDescriptorSetHandle(0), upsample1Binder->GetDescriptorSetLayoutBindingResources(0));
273 cmdList.UpdateDescriptorSet(
274 upsample2Binder->GetDescriptorSetHandle(0), upsample2Binder->GetDescriptorSetLayoutBindingResources(0));
275 }
276 }
277
278 if (settings_.cloudRenderingType == RenderDataStoreWeather::CloudRenderingType::REPROJECTED) {
279 ExecuteReprojected(cmdList, data);
280 } else if (settings_.cloudRenderingType == RenderDataStoreWeather::CloudRenderingType::DOWNSCALED) {
281 ExecuteDownscaled(cmdList, data);
282 } else {
283 ExecuteFull(cmdList, data);
284 }
285
286 // change index per frame
287 targetIndex_ = (targetIndex_ + 1) % 2U;
288 }
289
ExecuteReprojected(RENDER_NS::IRenderCommandList & cmdList,const GlobalFrameData & data)290 void RenderNodeCameraWeather::ExecuteReprojected(RENDER_NS::IRenderCommandList& cmdList, const GlobalFrameData& data)
291 {
292 if (clear_) {
293 clear_ = false;
294 ExplicitPass p;
295 p.size.x = currentScene_.camera.renderResolution.x;
296 p.size.y = currentScene_.camera.renderResolution.y;
297 p.p.renderPassDesc.attachmentCount = 2U;
298 p.p.renderPassDesc.attachments[0U].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR;
299 p.p.renderPassDesc.attachments[0U].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
300 p.p.renderPassDesc.attachments[0U].clearValue = ClearValue(0, 0, 0, 0);
301 p.p.renderPassDesc.attachments[1U].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR;
302 p.p.renderPassDesc.attachments[1U].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
303 p.p.renderPassDesc.attachments[1U].clearValue = ClearValue(0, 0, 0, 0);
304 p.p.renderPassDesc.attachmentHandles[0U] = cloudTexture_;
305 p.p.renderPassDesc.attachmentHandles[1U] = cloudTexturePrev_;
306 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x;
307 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y;
308 p.p.renderPassDesc.renderArea.offsetX = 0;
309 p.p.renderPassDesc.renderArea.offsetY = 0;
310 p.p.renderPassDesc.subpassCount = 1;
311 p.p.subpassDesc.colorAttachmentCount = 2u;
312 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
313 p.p.subpassDesc.colorAttachmentIndices[1u] = 1u;
314 p.p.subpassStartIndex = 0u;
315
316 // clear the accumulation buffers on the first frame
317 ExecuteClear(cmdList, p, data);
318 }
319
320 RenderHandle output = ((targetIndex_ % 2U) == 0) ? cloudTexture_ : cloudTexturePrev_;
321
322 ExplicitPass p;
323 p.size.x = currentScene_.camera.renderResolution.x >> downscale_;
324 p.size.y = currentScene_.camera.renderResolution.y >> downscale_;
325 p.p.renderPassDesc.attachmentCount = 1;
326 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR;
327 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
328 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
329 p.p.renderPassDesc.attachmentHandles[0] = output;
330 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x >> downscale_;
331 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y >> downscale_;
332 p.p.renderPassDesc.renderArea.offsetX = 0;
333 p.p.renderPassDesc.renderArea.offsetY = 0;
334 p.p.renderPassDesc.subpassCount = 1;
335 p.p.subpassDesc.colorAttachmentCount = 1u;
336 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
337 p.p.subpassStartIndex = 0u;
338
339 // generate limited information represeting clouds, ambient,direct,blend,transmission
340 ExecuteGenerateClouds(cmdList, p, data);
341
342 if constexpr (ENABLE_ADDITIONAL) {
343 p.size.x = currentScene_.camera.renderResolution.x;
344 p.size.y = currentScene_.camera.renderResolution.y;
345 p.p.renderPassDesc.attachmentCount = 1;
346 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR;
347 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
348 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
349 p.p.renderPassDesc.attachmentHandles[0] = cloudTexture_;
350 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x;
351 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y;
352 p.p.renderPassDesc.renderArea.offsetX = 0;
353 p.p.renderPassDesc.renderArea.offsetY = 0;
354 p.p.renderPassDesc.subpassCount = 1;
355 p.p.subpassDesc.colorAttachmentCount = 1u;
356 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
357 p.p.subpassDesc.subpassFlags = 0;
358 p.p.subpassStartIndex = 0u;
359
360 // NOTE: the reprojection should happen in translucent pass with depth test enabled
361 // this would fix most of the resolution artifacts
362 // probably 1 step upsample should be enough
363
364 // accumulates the results with results reproject from last frame, the results generated by the previous
365 // pass are 1/16th of frame, round robinned.
366 ExecuteUpsampleAndReproject(cmdList, cloudTexture_, cloudTexturePrev_, p, data);
367
368 p.size.x = currentScene_.camera.renderResolution.x;
369 p.size.y = currentScene_.camera.renderResolution.y;
370 p.p.renderPassDesc.attachmentCount = 1;
371 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_LOAD;
372 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
373 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
374 p.p.renderPassDesc.attachmentHandles[0] = cloudTexture_;
375 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x;
376 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y;
377 p.p.renderPassDesc.renderArea.offsetX = 0;
378 p.p.renderPassDesc.renderArea.offsetY = 0;
379 p.p.renderPassDesc.subpassCount = 1;
380 p.p.subpassDesc.colorAttachmentCount = 1u;
381 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
382 p.p.subpassDesc.subpassFlags = CORE_SUBPASS_MERGE_BIT;
383 p.p.subpassStartIndex = 0u;
384
385 // colorize the clouds
386 ExecuteUpsampleAndPostProcess(cmdList, cloudTexturePrev_, p, data);
387 }
388 }
389
ExecuteDownscaled(RENDER_NS::IRenderCommandList & cmdList,const GlobalFrameData & data)390 void RenderNodeCameraWeather::ExecuteDownscaled(RENDER_NS::IRenderCommandList& cmdList, const GlobalFrameData& data)
391 {
392 ExplicitPass p;
393 p.size.x = currentScene_.camera.renderResolution.x >> downscale_;
394 p.size.y = currentScene_.camera.renderResolution.y >> downscale_;
395 p.p.renderPassDesc.attachmentCount = 1;
396 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR;
397 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
398 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
399 p.p.renderPassDesc.attachmentHandles[0] = cloudTexture_;
400 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x >> 1;
401 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y >> 1;
402 p.p.renderPassDesc.renderArea.offsetX = 0;
403 p.p.renderPassDesc.renderArea.offsetY = 0;
404 p.p.renderPassDesc.subpassCount = 1;
405 p.p.subpassDesc.colorAttachmentCount = 1u;
406 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
407 p.p.subpassStartIndex = 0u;
408
409 // generate limited information represeting clouds, ambient, direct, blend, transmission
410 ExecuteGenerateClouds(cmdList, p, data);
411
412 if constexpr (ENABLE_ADDITIONAL) {
413 p.size.x = currentScene_.camera.renderResolution.x;
414 p.size.y = currentScene_.camera.renderResolution.y;
415 p.p.renderPassDesc.attachmentCount = 1;
416 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_LOAD;
417 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
418 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
419 p.p.renderPassDesc.attachmentHandles[0] = cloudTexture_;
420 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x;
421 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y;
422 p.p.renderPassDesc.renderArea.offsetX = 0;
423 p.p.renderPassDesc.renderArea.offsetY = 0;
424 p.p.renderPassDesc.subpassCount = 1;
425 p.p.subpassDesc.colorAttachmentCount = 1u;
426 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
427 p.p.subpassStartIndex = 0u;
428
429 // colorize the clouds
430 ExecuteUpsampleAndPostProcess(cmdList, cloudTexture_, p, data);
431 }
432 }
433
ExecuteFull(RENDER_NS::IRenderCommandList & cmdList,const GlobalFrameData & data)434 void RenderNodeCameraWeather::ExecuteFull(RENDER_NS::IRenderCommandList& cmdList, const GlobalFrameData& data)
435 {
436 ExplicitPass p;
437 p.size.x = currentScene_.camera.renderResolution.x;
438 p.size.y = currentScene_.camera.renderResolution.y;
439 p.p.renderPassDesc.attachmentCount = 1;
440 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR;
441 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
442 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
443 p.p.renderPassDesc.attachmentHandles[0] = cloudTexture_;
444 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x;
445 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y;
446 p.p.renderPassDesc.renderArea.offsetX = 0;
447 p.p.renderPassDesc.renderArea.offsetY = 0;
448 p.p.renderPassDesc.subpassCount = 1;
449 p.p.subpassDesc.colorAttachmentCount = 1u;
450 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
451 p.p.subpassDesc.subpassFlags = CORE_SUBPASS_MERGE_BIT;
452 p.p.subpassStartIndex = 0u;
453
454 // generate limited information represeting clouds, ambient, direct, blend, transmission
455 ExecuteGenerateClouds(cmdList, p, data);
456
457 if constexpr (ENABLE_ADDITIONAL) {
458 p.size.x = currentScene_.camera.renderResolution.x;
459 p.size.y = currentScene_.camera.renderResolution.y;
460 p.p.renderPassDesc.attachmentCount = 1;
461 p.p.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_LOAD;
462 p.p.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
463 p.p.renderPassDesc.attachments[0].clearValue = ClearValue(0, 0, 0, 0);
464 p.p.renderPassDesc.attachmentHandles[0] = cloudTexture_;
465 p.p.renderPassDesc.renderArea.extentWidth = currentScene_.camera.renderResolution.x;
466 p.p.renderPassDesc.renderArea.extentHeight = currentScene_.camera.renderResolution.y;
467 p.p.renderPassDesc.renderArea.offsetX = 0;
468 p.p.renderPassDesc.renderArea.offsetY = 0;
469 p.p.renderPassDesc.subpassCount = 1;
470 p.p.subpassDesc.colorAttachmentCount = 1u;
471 p.p.subpassDesc.colorAttachmentIndices[0u] = 0u;
472 p.p.subpassDesc.subpassFlags = CORE_SUBPASS_MERGE_BIT;
473 p.p.subpassStartIndex = 0u;
474
475 // colorize the clouds
476 ExecuteUpsampleAndPostProcess(cmdList, cloudTexture_, p, data);
477 }
478 }
479
ExecuteUpsampleAndReproject(RENDER_NS::IRenderCommandList & cmdList,RENDER_NS::RenderHandle input,RENDER_NS::RenderHandle prevInput,const ExplicitPass & p,const GlobalFrameData & d)480 void RenderNodeCameraWeather::ExecuteUpsampleAndReproject(RENDER_NS::IRenderCommandList& cmdList,
481 RENDER_NS::RenderHandle input, RENDER_NS::RenderHandle prevInput, const ExplicitPass& p, const GlobalFrameData& d)
482 {
483 // NOTE: not in use at the moment
484 CORE_ASSERT(false);
485
486 const auto& settings = settings_;
487 GraphicsShaderData& s = upsampleData2_;
488 auto& b = upsample2Binder;
489 RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "clouds-upsample", DEBUG_MARKER_COLOR);
490
491 auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
492 uint32_t binding = 0U;
493 // current cloud texture (RGBA: direct, ambient, blend, transmission)
494 b->BindImage(1, binding++, { input });
495 // accumulation texture used in previous frame
496 b->BindImage(1, binding++, { prevInput });
497 // used to derive camera matrices
498 b->BindBuffer(1, binding++, { cameraUboHandle_ });
499 cmdList.UpdateDescriptorSet(b->GetDescriptorSetHandle(1), b->GetDescriptorSetLayoutBindingResources(1));
500 b->PrintPipelineDescriptorSetLayoutBindingValidation();
501
502 RenderPass renderPass = CreateRenderPass(p.p.renderPassDesc.attachmentHandles[0]);
503 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
504
505 const float fEffectWidth = viewportDesc.width;
506 const float fEffectHeight = viewportDesc.height;
507 const Math::Vec4 texSizeInvTexSize { fEffectWidth, fEffectHeight, 1.0f / fEffectWidth, 1.0f / fEffectHeight };
508 const Math::UVec2 size { static_cast<uint32_t>(fEffectWidth), static_cast<uint32_t>(fEffectHeight) };
509
510 BlurShaderPushConstant pcV {};
511
512 pcV.dir[0U].x = d.time;
513 pcV.dir[0U].y = float(targetIndex_) + .5f;
514 pcV.dir[0U].z = settings.density;
515 pcV.dir[0U].w = settings.altitude;
516
517 pcV.dir[1U].x = settings.ambientColor[0U];
518 pcV.dir[1U].y = settings.ambientColor[1U];
519 pcV.dir[1U].z = settings.ambientColor[2U];
520 pcV.dir[1U].w = settings.windDir[0U];
521
522 pcV.dir[2U].x = settings.sunColor[0U];
523 pcV.dir[2U].y = settings.sunColor[1U];
524 pcV.dir[2U].z = settings.sunColor[2U];
525 pcV.dir[2U].w = settings.windDir[1U];
526
527 pcV.dir[3U].w = settings.windDir[2U];
528 const BlurParams<BlurShaderPushConstant, ExplicitPass> vBlur { s, *b, { pcV }, p };
529 RenderFullscreenTriangle(0, cmdList, vBlur);
530 }
531
ExecuteUpsampleAndPostProcess(RENDER_NS::IRenderCommandList & cmdList,RENDER_NS::RenderHandle input,const ExplicitPass & p,const GlobalFrameData & d)532 void RenderNodeCameraWeather::ExecuteUpsampleAndPostProcess(RENDER_NS::IRenderCommandList& cmdList,
533 RENDER_NS::RenderHandle input, const ExplicitPass& p, const GlobalFrameData& d)
534 {
535 // NOTE: not in use at the moment
536 CORE_ASSERT(false);
537
538 const auto& settings = settings_;
539 GraphicsShaderData& s = upsampleData1_;
540 auto& b = upsample1Binder;
541 RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "clouds-postprocess", DEBUG_MARKER_COLOR);
542
543 auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
544 // current accumulated/reprjected results, (RGBA: direct, ambient, blend, transmission)
545 uint32_t binding = 0U;
546 b->BindImage(1, binding++, { input });
547 // used to derive camera matrices
548 b->BindBuffer(1, binding++, { cameraUboHandle_ });
549 cmdList.UpdateDescriptorSet(b->GetDescriptorSetHandle(1), b->GetDescriptorSetLayoutBindingResources(1));
550
551 RenderPass renderPass = CreateRenderPass(p.p.renderPassDesc.attachmentHandles[0]);
552 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
553
554 const float fEffectWidth = viewportDesc.width;
555 const float fEffectHeight = viewportDesc.height;
556 const Math::Vec4 texSizeInvTexSize { fEffectWidth, fEffectHeight, 1.0f / fEffectWidth, 1.0f / fEffectHeight };
557 const Math::UVec2 size { static_cast<uint32_t>(fEffectWidth), static_cast<uint32_t>(fEffectHeight) };
558
559 BlurShaderPushConstant pcV {};
560
561 pcV.dir[0U].x = d.time;
562 pcV.dir[0U].y = settings.windSpeed;
563 pcV.dir[0U].z = settings.density;
564 pcV.dir[0U].w = settings.altitude;
565
566 pcV.dir[1U].x = settings.ambientColor[0U];
567 pcV.dir[1U].y = settings.ambientColor[1U];
568 pcV.dir[1U].z = settings.ambientColor[2U];
569 pcV.dir[1U].w = settings.windDir[0U];
570
571 pcV.dir[2U].x = settings.sunColor[0U];
572 pcV.dir[2U].y = settings.sunColor[1U];
573 pcV.dir[2U].z = settings.sunColor[2U];
574 pcV.dir[2U].w = settings.windDir[1U];
575
576 pcV.dir[3U].w = settings.windDir[2U];
577
578 const BlurParams<BlurShaderPushConstant, ExplicitPass> vBlur { s, *b, { pcV }, p };
579 RenderFullscreenTriangle(0, cmdList, vBlur);
580 }
581
ExecuteGenerateClouds(IRenderCommandList & cmdList,const ExplicitPass & p,const GlobalFrameData & d)582 void RenderNodeCameraWeather::ExecuteGenerateClouds(
583 IRenderCommandList& cmdList, const ExplicitPass& p, const GlobalFrameData& d)
584 {
585 const auto& settings = settings_;
586
587 GraphicsShaderData& s = cloudVolumeShaderData_;
588 auto& b = cloudVolumeBinder_;
589
590 uint32_t binding = 0;
591 // used to derive camera matrices
592 b->BindBuffer(1, binding++, { cameraUboHandle_ });
593 // weather map ( R = coverage %, G = precipation, B = cloud type)
594 b->BindImage(1, binding++, { weatherMapTex_ });
595 cmdList.UpdateDescriptorSet(b->GetDescriptorSetHandle(1), b->GetDescriptorSetLayoutBindingResources(1));
596
597 RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "clouds-generate", DEBUG_MARKER_COLOR);
598
599 BlurShaderPushConstant pcV {};
600
601 pcV.dir[0U].x = d.time;
602 pcV.dir[0U].y = settings.windSpeed;
603 pcV.dir[0U].z = settings.density;
604 pcV.dir[0U].w = settings.altitude;
605
606 pcV.dir[1U].x = settings.ambientColor[0U];
607 pcV.dir[1U].y = settings.ambientColor[1U];
608 pcV.dir[1U].z = settings.ambientColor[2U];
609 pcV.dir[1U].w = settings.windDir[0U];
610
611 pcV.dir[2U].x = settings.sunColor[0U];
612 pcV.dir[2U].y = settings.sunColor[1U];
613 pcV.dir[2U].z = settings.sunColor[2U];
614 pcV.dir[2U].w = settings.windDir[1U];
615
616 pcV.dir[3U].w = settings.windDir[2U];
617
618 const BlurParams<BlurShaderPushConstant, ExplicitPass> vBlur { s, *b, { pcV }, p };
619 RenderFullscreenTriangle(0, cmdList, vBlur);
620 }
621
ExecuteClear(IRenderCommandList & cmdList,const ExplicitPass & p,const GlobalFrameData & d)622 void RenderNodeCameraWeather::ExecuteClear(IRenderCommandList& cmdList, const ExplicitPass& p, const GlobalFrameData& d)
623 {
624 RenderPass pass = p;
625 cmdList.BeginRenderPass(pass.renderPassDesc, pass.subpassStartIndex, pass.subpassDesc);
626 cmdList.EndRenderPass();
627 }
628
629 template<typename T, class U>
RenderFullscreenTriangle(int firstSet,IRenderCommandList & commandList,const BlurParams<T,U> & args)630 void RenderNodeCameraWeather::RenderFullscreenTriangle(
631 int firstSet, IRenderCommandList& commandList, const BlurParams<T, U>& args)
632 {
633 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
634 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(args.data.p);
635 const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(args.data.p);
636 commandList.BeginRenderPass(args.data.p.renderPassDesc, args.data.p.subpassStartIndex, args.data.p.subpassDesc);
637 commandList.BindPipeline(args.shader.pso);
638 commandList.BindDescriptorSets(uint32_t(firstSet), args.binder.GetDescriptorSetHandles());
639 commandList.SetDynamicStateViewport(viewportDesc);
640 commandList.SetDynamicStateScissor(scissorDesc);
641 commandList.PushConstantData(args.shader.pipelineLayoutData.pushConstant, args.pc);
642 commandList.Draw(3u, 1u, 0u, 0u); // draw one triangle
643 commandList.EndRenderPass();
644 }
645
UpdateCurrentScene(const IRenderDataStoreDefaultScene & dataStoreScene,const IRenderDataStoreDefaultCamera & dataStoreCamera,const IRenderDataStoreDefaultLight & dataStoreLight)646 void RenderNodeCameraWeather::UpdateCurrentScene(const IRenderDataStoreDefaultScene& dataStoreScene,
647 const IRenderDataStoreDefaultCamera& dataStoreCamera, const IRenderDataStoreDefaultLight& dataStoreLight)
648 {
649 const auto scene = dataStoreScene.GetScene();
650 uint32_t cameraIdx = scene.cameraIndex;
651 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
652 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraId);
653 } else if (!(jsonInputs_.customCameraName.empty())) {
654 cameraIdx = dataStoreCamera.GetCameraIndex(jsonInputs_.customCameraName);
655 }
656
657 if (const auto cameras = dataStoreCamera.GetCameras(); cameraIdx < (uint32_t)cameras.size()) {
658 // store current frame camera
659 currentScene_.camera = cameras[cameraIdx];
660 }
661 const auto camHandles = renderNodeSceneUtil_->GetSceneCameraImageHandles(
662 *renderNodeContextMgr_, stores_.dataStoreNameScene, currentScene_.camera.name, currentScene_.camera);
663 currentScene_.cameraEnvRadianceHandle = camHandles.radianceCubemap;
664
665 const IRenderDataStoreDefaultLight::LightCounts lightCounts = dataStoreLight.GetLightCounts();
666 currentScene_.hasShadow = ((lightCounts.dirShadow > 0) || (lightCounts.spotShadow > 0)) ? true : false;
667 currentScene_.shadowTypes = dataStoreLight.GetShadowTypes();
668 currentScene_.lightingFlags = dataStoreLight.GetLightingFlags();
669 }
670
GetSceneUniformBuffers(const string_view us)671 void RenderNodeCameraWeather::GetSceneUniformBuffers(const string_view us)
672 {
673 if (renderNodeSceneUtil_) {
674 sceneBuffers_ = renderNodeSceneUtil_->GetSceneBufferHandles(*renderNodeContextMgr_, stores_.dataStoreNameScene);
675 }
676
677 string camName;
678 if (jsonInputs_.customCameraId != INVALID_CAM_ID) {
679 camName = to_string(jsonInputs_.customCameraId);
680 } else if (!(jsonInputs_.customCameraName.empty())) {
681 camName = jsonInputs_.customCameraName;
682 }
683 if (renderNodeSceneUtil_) {
684 cameraBuffers_ = renderNodeSceneUtil_->GetSceneCameraBufferHandles(
685 *renderNodeContextMgr_, stores_.dataStoreNameScene, camName);
686 }
687 }
688
ParseRenderNodeInputs()689 void RenderNodeCameraWeather::ParseRenderNodeInputs()
690 {
691 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
692 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
693 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
694 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
695 jsonInputs_.customCameraName = parserUtil.GetStringValue(jsonVal, "customCameraName");
696 jsonInputs_.customCameraId = parserUtil.GetUintValue(jsonVal, "customCameraId");
697 }
698
699 // for plugin / factory interface
Create()700 IRenderNode* RenderNodeCameraWeather::Create()
701 {
702 return new RenderNodeCameraWeather();
703 }
704
Destroy(IRenderNode * instance)705 void RenderNodeCameraWeather::Destroy(IRenderNode* instance)
706 {
707 delete static_cast<RenderNodeCameraWeather*>(instance);
708 }
709 CORE3D_END_NAMESPACE()
710