VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
shadowMap.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 02.10.2025.
5//
6#include "shadowMap.h"
7
8#include "scene/constants.h"
9#include "scene/light.h"
12
13namespace visutwin::canvas
14{
15 std::unique_ptr<ShadowMap> ShadowMap::create(GraphicsDevice* device, Light* light)
16 {
17 if (!device || !light) {
18 return nullptr;
19 }
20
21 const int resolution = light->shadowResolution();
22 const ShadowType shadowType = light->shadowType();
23 const auto& info = shadowTypeInfo.at(shadowType);
24
25 auto shadowMap = std::make_unique<ShadowMap>();
26
27 const bool isOmni = (light->type() == LightType::LIGHTTYPE_OMNI);
28
29 // Create the depth texture for the shadow map.
30 // Omni lights use a cubemap depth texture (6 faces), others use 2D.
31 TextureOptions depthOptions;
32 depthOptions.name = isOmni ? "OmniShadowCube" : "ShadowMap";
33 depthOptions.width = static_cast<uint32_t>(resolution);
34 depthOptions.height = static_cast<uint32_t>(resolution);
35 depthOptions.format = info.format;
36 depthOptions.mipmaps = false;
39 depthOptions.cubemap = isOmni;
40 shadowMap->_shadowTexture = std::make_shared<Texture>(device, depthOptions);
41 shadowMap->_shadowTexture->setAddressU(AddressMode::ADDRESS_CLAMP_TO_EDGE);
42 shadowMap->_shadowTexture->setAddressV(AddressMode::ADDRESS_CLAMP_TO_EDGE);
43
44 // Create render target(s). Directional gets 1 (cascades use viewport sub-regions),
45 // spot gets 1, omni gets 6 (cubemap faces).
46 //create2dMap() returns [target] for directional.
47 const int faceCount = (light->type() == LightType::LIGHTTYPE_DIRECTIONAL)
48 ? 1 : light->numShadowFaces();
49 for (int face = 0; face < faceCount; ++face) {
50 RenderTargetOptions rtOptions;
51 rtOptions.graphicsDevice = device;
52 rtOptions.name = "ShadowMapRT-face" + std::to_string(face);
53 rtOptions.face = face; // Cubemap face index (used by Metal render pass for slice selection)
54
55 if (info.pcf) {
56 // PCF uses depth-only render target.
57 rtOptions.depthBuffer = shadowMap->_shadowTexture.get();
58 rtOptions.depth = true;
59 } else {
60 // VSM uses color render target (depth written to color channels).
61 rtOptions.colorBuffer = shadowMap->_shadowTexture.get();
62 rtOptions.depth = true;
63 }
64
65 shadowMap->_renderTargets.push_back(device->createRenderTarget(rtOptions));
66 }
67
68 return shadowMap;
69 }
70}
Abstract GPU interface for resource creation, state management, and draw submission.
virtual std::shared_ptr< RenderTarget > createRenderTarget(const RenderTargetOptions &options)=0
Directional, point, spot, or area light with shadow mapping and cookie projection.
Definition light.h:54
int shadowResolution() const
Definition light.h:113
ShadowType shadowType() const
Definition light.h:104
int numShadowFaces() const
Definition light.cpp:31
LightType type() const
Definition light.h:70
static std::unique_ptr< ShadowMap > create(GraphicsDevice *device, Light *light)
Definition shadowMap.cpp:15
const std::unordered_map< ShadowType, ShadowTypeInfo > shadowTypeInfo
Definition constants.cpp:10