1 /*
2 * Copyright (c) 2023 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_default_environment_blender.h"
17
18 #include <3d/render/intf_render_data_store_default_camera.h>
19 #include <3d/render/intf_render_data_store_default_light.h>
20 #include <3d/render/intf_render_data_store_default_scene.h>
21 #include <base/math/mathf.h>
22 #include <core/log.h>
23 #include <render/datastore/intf_render_data_store_manager.h>
24 #include <render/datastore/intf_render_data_store_pod.h>
25 #include <render/datastore/intf_render_data_store_post_process.h>
26 #include <render/datastore/render_data_store_render_pods.h>
27 #include <render/device/intf_gpu_resource_manager.h>
28 #include <render/device/intf_shader_manager.h>
29 #include <render/device/pipeline_layout_desc.h>
30 #include <render/device/pipeline_state_desc.h>
31 #include <render/namespace.h>
32 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
33 #include <render/nodecontext/intf_node_context_pso_manager.h>
34 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
35 #include <render/nodecontext/intf_render_command_list.h>
36 #include <render/nodecontext/intf_render_node_context_manager.h>
37 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
38 #include <render/nodecontext/intf_render_node_parser_util.h>
39 #include <render/nodecontext/intf_render_node_util.h>
40
41 #include "render/default_constants.h"
42
43 // shaders
44 #include <render/shaders/common/render_post_process_structs_common.h>
45
46 using namespace BASE_NS;
47 using namespace RENDER_NS;
48
49 CORE3D_BEGIN_NAMESPACE()
50 namespace {
51 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
52
53 constexpr uint32_t MAX_MIP_COUNT { 16U };
54 constexpr string_view CORE_DEFAULT_GPU_IMAGE_BLACK { "CORE_DEFAULT_GPU_IMAGE" };
55 constexpr string_view DEFAULT_CUBEMAP_BLENDER_SHADER { "3dshaders://shader/core3d_dm_camera_cubemap_blender.shader" };
56
57 constexpr GpuImageDesc CUBEMAP_DEFAULT_DESC { CORE_IMAGE_TYPE_2D, CORE_IMAGE_VIEW_TYPE_CUBE,
58 BASE_FORMAT_B10G11R11_UFLOAT_PACK32, CORE_IMAGE_TILING_OPTIMAL,
59 CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | CORE_IMAGE_USAGE_SAMPLED_BIT, CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
60 CORE_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS, 256U, 256U, 1U, 9U, 6U,
61 CORE_SAMPLE_COUNT_1_BIT, ComponentMapping {} };
62
GetDefaultImagesAndSamplers(const IRenderNodeGpuResourceManager & gpuResourceMgr)63 RenderNodeDefaultEnvironmentBlender::DefaultImagesAndSamplers GetDefaultImagesAndSamplers(
64 const IRenderNodeGpuResourceManager& gpuResourceMgr)
65 {
66 RenderNodeDefaultEnvironmentBlender::DefaultImagesAndSamplers dias;
67 dias.cubemapSamplerHandle =
68 gpuResourceMgr.GetSamplerHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER);
69 dias.linearHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
70 dias.nearestHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_NEAREST_CLAMP");
71 dias.linearMipHandle = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_MIPMAP_CLAMP");
72 dias.skyBoxRadianceCubemapHandle =
73 gpuResourceMgr.GetImageHandle(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP);
74 return dias;
75 }
76
CreateRadianceCubemap(IRenderNodeGpuResourceManager & gpuResourceMgr,const string_view name)77 RenderHandleReference CreateRadianceCubemap(IRenderNodeGpuResourceManager& gpuResourceMgr, const string_view name)
78 {
79 return gpuResourceMgr.Create(name, CUBEMAP_DEFAULT_DESC);
80 }
81 } // namespace
82
InitNode(IRenderNodeContextManager & renderNodeContextMgr)83 void RenderNodeDefaultEnvironmentBlender::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
84 {
85 renderNodeContextMgr_ = &renderNodeContextMgr;
86
87 valid_ = true;
88
89 ParseRenderNodeInputs();
90 const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
91 stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
92 renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
93
94 UpdateImageData();
95 }
96
PreExecuteFrame()97 void RenderNodeDefaultEnvironmentBlender::PreExecuteFrame()
98 {
99 hasBlendEnvironments_ = false;
100
101 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
102 const auto* dataStoreCamera =
103 static_cast<IRenderDataStoreDefaultCamera*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
104 const auto* dataStoreScene =
105 static_cast<IRenderDataStoreDefaultScene*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
106 valid_ = (dataStoreScene && dataStoreCamera);
107 if (!valid_) {
108 return;
109 }
110 if (!dataStoreCamera->HasBlendEnvironments()) {
111 // need to clear targets
112 envTargetData_ = {};
113 return; // early out
114 }
115
116 hasBlendEnvironments_ = true;
117
118 // create possible targets
119 const auto& renderEnvironments = dataStoreCamera->GetEnvironments();
120 for (uint32_t idx = 0U; idx < static_cast<uint32_t>(renderEnvironments.size()); ++idx) {
121 const auto& currEnv = renderEnvironments[idx];
122 if (currEnv.multiEnvCount != 0U) {
123 if (!currEnv.radianceCubemap) {
124 bool targetFound = false;
125 // create target if not available and mark for frame usage
126 for (auto& targetRef : envTargetData_) {
127 if (targetRef.id == currEnv.id) {
128 targetFound = true;
129 break;
130 }
131 }
132 if (!targetFound) {
133 const string name = string(stores_.dataStoreNameScene) +
134 DefaultMaterialSceneConstants::ENVIRONMENT_RADIANCE_CUBEMAP_PREFIX_NAME +
135 to_hex(currEnv.id);
136 envTargetData_.push_back({ currEnv.id,
137 CreateRadianceCubemap(renderNodeContextMgr_->GetGpuResourceManager(), name.c_str()), true });
138 }
139 }
140 }
141 }
142 }
143
GetExecuteFlags() const144 IRenderNode::ExecuteFlags RenderNodeDefaultEnvironmentBlender::GetExecuteFlags() const
145 {
146 if (valid_ && hasBlendEnvironments_) {
147 return 0U;
148 } else {
149 return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
150 }
151 }
152
ExecuteFrame(IRenderCommandList & cmdList)153 void RenderNodeDefaultEnvironmentBlender::ExecuteFrame(IRenderCommandList& cmdList)
154 {
155 const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
156 const auto* dataStoreCamera =
157 static_cast<IRenderDataStoreDefaultCamera*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
158 const auto* dataStoreScene =
159 static_cast<IRenderDataStoreDefaultScene*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
160 if (valid_ && dataStoreCamera && dataStoreScene) {
161 CORE_ASSERT(dataStoreCamera->HasBlendEnvironments());
162 UpdateImageData();
163 InitializeShaderData();
164
165 RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "3DEnvCubemapBlender", DefaultDebugConstants::DEFAULT_DEBUG_COLOR);
166 const auto renderEnvironments = dataStoreCamera->GetEnvironments();
167
168 environmentUbo_ = renderNodeContextMgr_->GetGpuResourceManager().GetBufferHandle(
169 stores_.dataStoreNameScene.c_str() + DefaultMaterialSceneConstants::SCENE_ENVIRONMENT_DATA_BUFFER_NAME);
170 if (RenderHandleUtil::IsValid(environmentUbo_)) {
171 for (uint32_t idx = 0U; idx < static_cast<uint32_t>(renderEnvironments.size()); ++idx) {
172 const auto& ref = renderEnvironments[idx];
173 if (ref.multiEnvCount != 0U) {
174 ExecuteSingleEnvironment(cmdList, renderEnvironments, idx);
175 }
176 }
177 }
178 }
179
180 // clear targets which are not used this frame
181 for (auto iter = envTargetData_.begin(); iter != envTargetData_.end();) {
182 if (iter->usedThisFrame) {
183 ++iter;
184 } else {
185 envTargetData_.erase(iter);
186 }
187 }
188 }
189
190 namespace {
191 constexpr ImageResourceBarrier SRC_UNDEFINED { 0, CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CORE_IMAGE_LAYOUT_UNDEFINED };
192 constexpr ImageResourceBarrier COL_ATTACHMENT { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
193 CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
194 constexpr ImageResourceBarrier SHDR_READ { CORE_ACCESS_SHADER_READ_BIT, CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
195 CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
196 } // namespace
197
GetEnvironmentTargetHandle(const RenderCamera::Environment & environment)198 RenderHandle RenderNodeDefaultEnvironmentBlender::GetEnvironmentTargetHandle(
199 const RenderCamera::Environment& environment)
200 {
201 RenderHandle target;
202 if (environment.radianceCubemap) {
203 // there's a target available which we should use
204 target = environment.radianceCubemap.GetHandle();
205 #if (CORE3D_VALIDATION_ENABLED == 1)
206 const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
207 const GpuImageDesc& desc = gpuResourceMgr.GetImageDescriptor(target);
208 if ((desc.usageFlags & ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0U) {
209 CORE_LOG_ONCE_W("target_usage_cubemap_color_attachment_" + to_string(target.id),
210 "CORE3D_VALIDATION: Environment blending radiance cubemap target has invalid flags");
211 }
212 #endif
213 } else {
214 // mark for frame usage
215 for (auto& targetRef : envTargetData_) {
216 if (targetRef.id == environment.id) {
217 targetRef.usedThisFrame = true;
218 target = targetRef.handle.GetHandle();
219 break;
220 }
221 }
222 if (!RenderHandleUtil::IsValid(target)) {
223 CORE_LOG_W("Target handle issues with cubemap blender");
224 }
225 }
226 return target;
227 }
228
FillBlendEnvironments(const array_view<const RenderCamera::Environment> environments,const uint32_t envIdx,array_view<RenderHandle> & blendEnvs) const229 void RenderNodeDefaultEnvironmentBlender::FillBlendEnvironments(
230 const array_view<const RenderCamera::Environment> environments, const uint32_t envIdx,
231 array_view<RenderHandle>& blendEnvs) const
232 {
233 const auto& env = environments[envIdx];
234 // fetch all the radiance cubemaps
235 uint32_t mvEnvIdx = 0U;
236 for (uint32_t idx = 0; idx < env.multiEnvCount; ++idx) {
237 if (mvEnvIdx >= blendEnvs.size()) {
238 break;
239 }
240 if (idx < env.multiEnvCount) {
241 for (const auto& mvEnvRef : environments) {
242 if (mvEnvRef.id == env.multiEnvIds[idx]) {
243 blendEnvs[mvEnvIdx++] = (mvEnvRef.radianceCubemap)
244 ? mvEnvRef.radianceCubemap.GetHandle()
245 : defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle;
246 break;
247 }
248 }
249 }
250 }
251 }
252
ExecuteSingleEnvironment(IRenderCommandList & cmdList,const array_view<const RenderCamera::Environment> environments,const uint32_t envIdx)253 void RenderNodeDefaultEnvironmentBlender::ExecuteSingleEnvironment(
254 IRenderCommandList& cmdList, const array_view<const RenderCamera::Environment> environments, const uint32_t envIdx)
255 {
256 const auto& envRef = environments[envIdx];
257 CORE_ASSERT(envRef.multiEnvCount > 0U);
258
259 const RenderHandle target = GetEnvironmentTargetHandle(envRef);
260 if (!RenderHandleUtil::IsValid(target)) {
261 return;
262 }
263
264 RenderHandle blendEnvironments[2U] { defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle,
265 defaultImagesAndSamplers_.skyBoxRadianceCubemapHandle };
266 array_view<RenderHandle> beView { blendEnvironments, countof(blendEnvironments) };
267 FillBlendEnvironments(environments, envIdx, beView);
268
269 const GpuImageDesc desc = renderNodeContextMgr_->GetGpuResourceManager().GetImageDescriptor(target);
270 Math::UVec2 currSize = { desc.width, desc.height };
271
272 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
273 RenderPass renderPass;
274 renderPass.renderPassDesc.attachmentCount = 1U;
275 renderPass.renderPassDesc.attachmentHandles[0U] = target;
276 renderPass.renderPassDesc.attachments[0U].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
277 renderPass.renderPassDesc.attachments[0U].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
278 renderPass.renderPassDesc.attachments[0U].layer = 0U;
279 renderPass.renderPassDesc.renderArea = { 0U, 0U, currSize.x, currSize.y };
280 renderPass.renderPassDesc.subpassCount = 1U;
281 renderPass.subpassDesc.viewMask = 0x3f;
282 renderPass.subpassDesc.colorAttachmentCount = 1U;
283 renderPass.subpassDesc.colorAttachmentIndices[0U] = 0U;
284
285 auto& sets = allEnvSets_[envIdx];
286 for (uint32_t mipIdx = 0; mipIdx < desc.mipCount; ++mipIdx) {
287 // handle all descriptor set updates
288 UpdateSet0(cmdList, beView, envIdx, mipIdx);
289 const auto& bindings = sets.localSets[mipIdx]->GetDescriptorSetLayoutBindingResources();
290 cmdList.UpdateDescriptorSet(sets.localSets[mipIdx]->GetDescriptorSetHandle(), bindings);
291 }
292
293 cmdList.BeginDisableAutomaticBarrierPoints();
294
295 // change all the layouts accordingly
296 {
297 ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0,
298 PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
299 cmdList.CustomImageBarrier(target, SRC_UNDEFINED, COL_ATTACHMENT, imageSubresourceRange);
300 cmdList.AddCustomBarrierPoint();
301 }
302
303 for (uint32_t mipIdx = 0; mipIdx < desc.mipCount; ++mipIdx) {
304 renderPass.renderPassDesc.attachments[0U].mipLevel = mipIdx;
305 if (mipIdx != 0U) {
306 currSize.x = Math::max(1U, currSize.x / 2U);
307 currSize.y = Math::max(1U, currSize.y / 2U);
308 }
309 renderPass.renderPassDesc.renderArea = { 0U, 0U, currSize.x, currSize.y };
310
311 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
312
313 cmdList.BindPipeline(psoHandle_);
314 // bind all sets
315 cmdList.BindDescriptorSet(0U, sets.localSets[mipIdx]->GetDescriptorSetHandle());
316
317 // dynamic state
318 const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
319 const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
320 cmdList.SetDynamicStateViewport(viewportDesc);
321 cmdList.SetDynamicStateScissor(scissorDesc);
322
323 if (pipelineLayout_.pushConstant.byteSize > 0U) {
324 // mipIdx as lodlevel
325 Math::UVec4 indices { envIdx, mipIdx, 0U, 0U };
326 cmdList.PushConstantData(pipelineLayout_.pushConstant, arrayviewU8(indices));
327 }
328
329 cmdList.Draw(3u, 1u, 0u, 0u);
330 cmdList.EndRenderPass();
331 }
332
333 // change all the layouts accordingly
334 {
335 ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0,
336 PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
337 cmdList.CustomImageBarrier(target, COL_ATTACHMENT, SHDR_READ, imageSubresourceRange);
338 cmdList.AddCustomBarrierPoint();
339 }
340
341 cmdList.EndDisableAutomaticBarrierPoints();
342 }
343
UpdateSet0(IRenderCommandList & cmdList,const array_view<const RenderHandle> blendImages,const uint32_t envIdx,const uint32_t mipIdx)344 void RenderNodeDefaultEnvironmentBlender::UpdateSet0(IRenderCommandList& cmdList,
345 const array_view<const RenderHandle> blendImages, const uint32_t envIdx, const uint32_t mipIdx)
346 {
347 // bind all radiance cubemaps
348 const auto& sets = allEnvSets_[envIdx];
349 auto& binder = *sets.localSets[mipIdx];
350 CORE_ASSERT(sets.localSets[mipIdx]);
351 CORE_ASSERT(blendImages.size() == 2U);
352
353 const uint32_t maxCount = Math::min(DefaultMaterialCameraConstants::MAX_CAMERA_MULTI_ENVIRONMENT_COUNT, 2U);
354 uint32_t binding = 0U;
355 binder.BindBuffer(binding++, { environmentUbo_ });
356 BindableImage bi;
357 // additional cubemaps from first index
358 for (uint32_t resIdx = 0U; resIdx < maxCount; ++resIdx) {
359 // filled with valid handles
360 bi.handle = blendImages[resIdx];
361 bi.samplerHandle = defaultImagesAndSamplers_.cubemapSamplerHandle;
362 binder.BindImage(binding++, bi, {});
363 }
364 }
365
InitializeShaderData()366 void RenderNodeDefaultEnvironmentBlender::InitializeShaderData()
367 {
368 if (!hasInitializedShaderData_) {
369 hasInitializedShaderData_ = true;
370
371 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
372 defaultImagesAndSamplers_ = GetDefaultImagesAndSamplers(gpuResourceMgr);
373 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
374 const RenderHandleType handleType = RenderHandleUtil::GetHandleType(shader_);
375 const RenderHandle plHandle = shaderMgr.GetReflectionPipelineLayoutHandle(shader_);
376 pipelineLayout_ = shaderMgr.GetPipelineLayout(plHandle);
377 if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
378 const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader_);
379 psoHandle_ = renderNodeContextMgr_->GetPsoManager().GetGraphicsPsoHandle(
380 shader_, graphicsState, pipelineLayout_, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
381 } else {
382 CORE_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
383 }
384 InitCreateBinders();
385 }
386 }
387
InitCreateBinders()388 void RenderNodeDefaultEnvironmentBlender::InitCreateBinders()
389 {
390 const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
391 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
392 {
393 DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
394 for (uint32_t idx = 0; idx < dc.counts.size(); ++idx) {
395 dc.counts[idx].count *= MAX_MIP_COUNT * CORE_DEFAULT_MATERIAL_MAX_ENVIRONMENT_COUNT;
396 }
397 descriptorSetMgr.ResetAndReserve(dc);
398 }
399
400 allEnvSets_.clear();
401 allEnvSets_.resize(CORE_DEFAULT_MATERIAL_MAX_ENVIRONMENT_COUNT);
402
403 for (auto& setsRef : allEnvSets_) {
404 setsRef.localSets.resize(MAX_MIP_COUNT);
405 const auto& bindings = pipelineLayout_.descriptorSetLayouts[0U].bindings;
406 for (uint32_t idx = 0; idx < MAX_MIP_COUNT; ++idx) {
407 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
408 setsRef.localSets[idx] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
409 }
410 }
411
412 if ((!RenderHandleUtil::IsValid(shader_)) || (!RenderHandleUtil::IsValid(psoHandle_))) {
413 valid_ = false;
414 }
415 }
416
ParseRenderNodeInputs()417 void RenderNodeDefaultEnvironmentBlender::ParseRenderNodeInputs()
418 {
419 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
420 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
421 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
422 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
423 if (!shaderName.empty()) {
424 shader_ = shaderMgr.GetShaderHandle(shaderName);
425 } else {
426 shader_ = shaderMgr.GetShaderHandle(DEFAULT_CUBEMAP_BLENDER_SHADER);
427 }
428 }
429
UpdateImageData()430 void RenderNodeDefaultEnvironmentBlender::UpdateImageData()
431 {
432 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
433 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
434 builtInVariables_.defBlackImage = gpuResourceMgr.GetImageHandle(CORE_DEFAULT_GPU_IMAGE_BLACK);
435 }
436 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
437 builtInVariables_.defSampler = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
438 }
439 }
440
441 // for plugin / factory interface
Create()442 IRenderNode* RenderNodeDefaultEnvironmentBlender::Create()
443 {
444 return new RenderNodeDefaultEnvironmentBlender();
445 }
446
Destroy(IRenderNode * instance)447 void RenderNodeDefaultEnvironmentBlender::Destroy(IRenderNode* instance)
448 {
449 delete static_cast<RenderNodeDefaultEnvironmentBlender*>(instance);
450 }
451 CORE3D_END_NAMESPACE()
452