SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
Skybox.cpp
Go to the documentation of this file.
1#include <Runtime/Skybox.hpp>
2#include <Runtime/Texture.hpp>
8#include <Camera/Camera.hpp>
9#include <Core/Logger.hpp>
10
11#include <vector>
12
13namespace Sleak {
14
15/// GPU constant buffer layout for the skybox shader.
16struct alignas(16) SkyboxCBData {
18};
19
20Skybox::Skybox(const std::array<std::string, 6>& facePaths)
21 : m_mode(SkyboxMode::Cubemap), m_facePaths(facePaths) {}
22
23Skybox::Skybox(const std::string& panoramaPath)
24 : m_mode(SkyboxMode::Panorama), m_panoramaPath(panoramaPath) {}
25
26Skybox::Skybox(float topR, float topG, float topB,
27 float midR, float midG, float midB,
28 float botR, float botG, float botB)
29 : m_mode(SkyboxMode::Gradient),
30 m_topR(topR), m_topG(topG), m_topB(topB),
31 m_midR(midR), m_midG(midG), m_midB(midB),
32 m_botR(botR), m_botG(botG), m_botB(botB) {}
33
35 : m_mode(SkyboxMode::Default),
36 m_panoramaPath("assets/textures/default_skybox.hdr") {}
37
39
41 if (m_initialized) return;
42
43 // Create cube mesh for skybox (unit cube, vertices only need position)
44 MeshData cube;
45 cube.vertices.AddVertex(Vertex(-1, -1, 1, 0,0,0, 0,0,0,0, 0,0)); // 0
46 cube.vertices.AddVertex(Vertex(-1, 1, 1, 0,0,0, 0,0,0,0, 0,0)); // 1
47 cube.vertices.AddVertex(Vertex( 1, 1, 1, 0,0,0, 0,0,0,0, 0,0)); // 2
48 cube.vertices.AddVertex(Vertex( 1, -1, 1, 0,0,0, 0,0,0,0, 0,0)); // 3
49 cube.vertices.AddVertex(Vertex(-1, -1, -1, 0,0,0, 0,0,0,0, 0,0)); // 4
50 cube.vertices.AddVertex(Vertex(-1, 1, -1, 0,0,0, 0,0,0,0, 0,0)); // 5
51 cube.vertices.AddVertex(Vertex( 1, 1, -1, 0,0,0, 0,0,0,0, 0,0)); // 6
52 cube.vertices.AddVertex(Vertex( 1, -1, -1, 0,0,0, 0,0,0,0, 0,0)); // 7
53
54 // Winding order: visible from inside the cube
55 cube.indices = {
56 0, 2, 1, 0, 3, 2, // Front (+Z)
57 4, 5, 6, 4, 6, 7, // Back (-Z)
58 4, 1, 5, 4, 0, 1, // Left (-X)
59 3, 6, 2, 3, 7, 6, // Right (+X)
60 1, 6, 5, 1, 2, 6, // Top (+Y)
61 4, 3, 0, 4, 7, 3 // Bottom (-Y)
62 };
63
67 cube.vertices.GetRawData()));
68
71 cube.indices.GetByteSize(),
72 cube.indices.GetRawData()));
73
74 // Constant buffer for ViewProjection matrix
75 SkyboxCBData cbData;
79 sizeof(SkyboxCBData),
80 &cbData));
81 m_constantBuffer->SetSlot(0);
82
83 // Create shader (skybox.hlsl resolves to backend-specific shaders)
85 "assets/shaders/skybox.hlsl"));
86 if (!m_shader.IsValid()) {
87 SLEAK_ERROR("Skybox: Failed to create skybox shader");
88 return;
89 }
90
91 // Create cubemap texture based on mode
92 if (m_mode == SkyboxMode::Cubemap) {
93 m_cubemapTexture = RefPtr(
95 if (!m_cubemapTexture.IsValid()) {
96 SLEAK_WARN("Skybox: Failed to load cubemap faces, falling back to panorama");
97 m_mode = SkyboxMode::Default;
98 m_panoramaPath = "assets/textures/default_skybox.hdr";
99 }
100 }
101
102 if (m_mode == SkyboxMode::Panorama || m_mode == SkyboxMode::Default) {
103 m_cubemapTexture = RefPtr(
105 if (!m_cubemapTexture.IsValid()) {
106 SLEAK_WARN("Skybox: Failed to load panorama '{}', falling back to gradient",
107 m_panoramaPath);
108 m_mode = SkyboxMode::Gradient;
109 }
110 }
111
112 if (m_mode == SkyboxMode::Gradient) {
113 SLEAK_INFO("Skybox: Using gradient mode (no cubemap texture)");
114 }
115
116 m_initialized = true;
117 SLEAK_INFO("Skybox initialized successfully (mode: {})",
118 m_mode == SkyboxMode::Cubemap ? "cubemap" :
119 m_mode == SkyboxMode::Panorama ? "panorama" :
120 m_mode == SkyboxMode::Gradient ? "gradient" : "default");
121}
122
124 if (!m_initialized) return;
125 if (!m_shader.IsValid()) return;
126
127 // Build view-projection matrix with translation zeroed out
129 view(3, 0) = 0.0f;
130 view(3, 1) = 0.0f;
131 view(3, 2) = 0.0f;
132
134 Math::Matrix4 viewProj = view * proj;
135
136 // Update constant buffer data
137 SkyboxCBData cbData;
138 cbData.ViewProjection = viewProj;
139 m_constantBuffer->Update(&cbData, sizeof(SkyboxCBData));
140
141 // Capture resources for the lambda
142 auto shader = m_shader;
143 auto vb = m_vertexBuffer;
144 auto ib = m_indexBuffer;
145 auto cb = m_constantBuffer;
146 auto cubemap = m_cubemapTexture;
147
149 [shader, vb, ib, cb, cubemap](RenderEngine::RenderContext* ctx) {
150 // Bind shader first (sets per-shader PSO in DX12)
151 shader->bind();
152
153 // Switch to skybox pipeline/state AFTER bind so the
154 // specialised skybox PSO is not overwritten by the generic one
155 ctx->BeginSkyboxPass();
156
157 // Set depth state: write disabled, test LEQUAL, no culling
158 ctx->SetDepthWrite(false);
160 ctx->SetCullEnabled(false);
161
162 // Bind cubemap texture to slot 0
163 ctx->BindTexture(cubemap, 0);
164
165 // Bind constant buffer
166 ctx->BindConstantBuffer(cb, 0);
167
168 // Bind vertex and index buffers, then draw
169 ctx->BindVertexBuffer(vb, 0);
170 ctx->BindIndexBuffer(ib, 0);
171 ctx->DrawIndexed(36);
172
173 // Restore to main pipeline/state
174 ctx->EndSkyboxPass();
175
176 // Restore depth state for OpenGL
177 ctx->SetDepthWrite(true);
179 ctx->SetCullEnabled(true);
180 });
181}
182
183} // namespace Sleak
#define SLEAK_ERROR(...)
Definition Logger.hpp:22
#define SLEAK_INFO(...)
Definition Logger.hpp:20
#define SLEAK_WARN(...)
Definition Logger.hpp:21
static const Math::Matrix4 & GetMainProjectionMatrix()
Definition Camera.hpp:107
static const Math::Matrix4 & GetMainViewMatrix()
Definition Camera.hpp:103
void * GetRawData()
Definition List.hpp:159
size_t GetByteSize() const
Definition List.hpp:152
static Matrix< float, Rows, Rows > Identity()
Definition Matrix.hpp:203
void SubmitCustomCommand(CustomCommand::ExecuteFunction function)
Queues an arbitrary callback to run inline with other render commands.
static RenderCommandQueue * GetInstance()
Lazily creates and returns the process-wide singleton instance.
Abstract interface for high-level graphics command execution and resource management.
virtual void BindTexture(RefPtr< Sleak::Texture > texture, uint32_t slot=0)
virtual void SetCullEnabled(bool enabled)
virtual void SetDepthCompare(DepthCompare compare)
virtual void BindVertexBuffer(RefPtr< BufferBase > buffer, uint32_t slot=0)=0
virtual void BindIndexBuffer(RefPtr< BufferBase > buffer, uint32_t slot=0)=0
virtual void SetDepthWrite(bool enabled)
virtual void BindConstantBuffer(RefPtr< BufferBase > buffer, uint32_t slot=0)=0
virtual void DrawIndexed(uint32_t indexCount)=0
Indexed draw from the currently bound vertex/index buffers.
static Sleak::Texture * CreateCubemapTextureFromPanorama(const std::string &PanoramaPath)
Loads a cubemap from a single equirectangular panorama via the currently registered backend factory.
static Shader * CreateShader(const std::string &ShaderPath)
Compiles a shader via the currently registered backend factory.
static BufferBase * CreateBuffer(BufferType Type, uint32_t Size, void *Data)
Creates a buffer via the currently registered backend factory.
static Sleak::Texture * CreateCubemapTexture(const std::array< std::string, 6 > &FacePaths)
Loads a cubemap from six face image paths via the currently registered backend factory.
void Render()
Submit render commands for this frame.
Definition Skybox.cpp:123
Skybox()
Default skybox: loads built-in sky panorama.
Definition Skybox.cpp:34
void Initialize()
Create GPU resources (shader, buffers, cubemap texture).
Definition Skybox.cpp:40
void AddVertex(const Vertex &vertex)
Definition MeshData.hpp:80
void * GetRawData()
Definition MeshData.hpp:90
size_t GetSizeInBytes() const
Definition MeshData.hpp:92
Matrix< float, 4, 4 > Matrix4
Definition Matrix.hpp:413
Root namespace for everything the engine exposes.
Definition Camera.hpp:10
IndexGroup indices
Definition MeshData.hpp:105
VertexGroup vertices
Definition MeshData.hpp:104
GPU constant buffer layout for the skybox shader.
Definition Skybox.cpp:16
Math::Matrix4 ViewProjection
Definition Skybox.cpp:17