• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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