17 device->GetImmediateContext(m_deviceContext.GetAddressOf());
20DirectX11CubemapTexture::~DirectX11CubemapTexture() {
21 m_shaderResourceView.Reset();
23 m_samplerState.Reset();
26bool DirectX11CubemapTexture::LoadCubemap(
27 const std::array<std::string, 6>& facePaths) {
28 stbi_set_flip_vertically_on_load(
false);
31 unsigned char* pixels =
nullptr;
34 std::array<FaceData, 6> faces;
36 for (
int i = 0; i < 6; i++) {
38 faces[i].pixels = stbi_load(facePaths[i].c_str(), &faces[i].w,
39 &faces[i].h, &channels, 4);
40 if (!faces[i].pixels) {
41 SLEAK_ERROR(
"DirectX11CubemapTexture: Failed to load face {}: {}",
43 for (
int j = 0; j < i; j++)
44 stbi_image_free(faces[j].pixels);
50 for (
int i = 1; i < 6; i++) {
51 if (faces[i].w != faces[0].w || faces[i].h != faces[0].h) {
53 "DirectX11CubemapTexture: Face {} size ({}x{}) doesn't match "
55 i, faces[i].w, faces[i].h, faces[0].w, faces[0].h);
56 for (
int j = 0; j < 6; j++)
57 stbi_image_free(faces[j].pixels);
62 uint32_t faceSize =
static_cast<uint32_t
>(faces[0].w);
63 std::vector<unsigned char*> facePointers;
64 for (
int i = 0; i < 6; i++)
65 facePointers.push_back(faces[i].pixels);
67 bool result = CreateCubemapFromFaces(facePointers, faceSize);
69 for (
int i = 0; i < 6; i++)
70 stbi_image_free(faces[i].pixels);
73 SLEAK_INFO(
"DirectX11CubemapTexture: Loaded cubemap ({}x{}, 6 faces)",
80bool DirectX11CubemapTexture::LoadEquirectangular(
const std::string& path,
82 stbi_set_flip_vertically_on_load(
false);
84 int panW, panH, channels;
85 unsigned char* panorama =
86 stbi_load(path.c_str(), &panW, &panH, &channels, 4);
88 SLEAK_ERROR(
"DirectX11CubemapTexture: Failed to load panorama: {}",
93 size_t faceBytes =
static_cast<size_t>(faceSize) * faceSize * 4;
94 std::vector<std::vector<unsigned char>> allFaces(6);
95 for (
int i = 0; i < 6; i++)
96 allFaces[i].resize(faceBytes);
98 for (
int face = 0; face < 6; ++face) {
99 unsigned char* faceData = allFaces[face].data();
101 for (uint32_t y = 0; y < faceSize; ++y) {
102 for (uint32_t x = 0; x < faceSize; ++x) {
103 float u = (2.0f * (x + 0.5f) / faceSize) - 1.0f;
104 float v = (2.0f * (y + 0.5f) / faceSize) - 1.0f;
108 case 0: dx = 1.0f; dy = -v; dz = -u;
break;
109 case 1: dx = -1.0f; dy = -v; dz = u;
break;
110 case 2: dx = u; dy = 1.0f; dz = v;
break;
111 case 3: dx = u; dy = -1.0f; dz = -v;
break;
112 case 4: dx = u; dy = -v; dz = 1.0f;
break;
113 case 5: dx = -u; dy = -v; dz = -1.0f;
break;
114 default: dx = dy = dz = 0.0f;
break;
117 float len = std::sqrt(dx * dx + dy * dy + dz * dz);
118 dx /= len; dy /= len; dz /= len;
120 float lon = std::atan2(dz, dx);
121 float lat = std::asin(std::clamp(dy, -1.0f, 1.0f));
123 float panU = 0.5f + lon / (2.0f * 3.14159265f);
124 float panV = 0.5f - lat / 3.14159265f;
126 float srcX = panU * (panW - 1);
127 float srcY = panV * (panH - 1);
128 int x0 =
static_cast<int>(srcX);
129 int y0 =
static_cast<int>(srcY);
130 int x1 = std::min(x0 + 1, panW - 1);
131 int y1 = std::min(y0 + 1, panH - 1);
132 x0 = std::clamp(x0, 0, panW - 1);
133 y0 = std::clamp(y0, 0, panH - 1);
134 float fx = srcX - x0;
135 float fy = srcY - y0;
137 size_t idx = (y * faceSize + x) * 4;
138 for (
int c = 0; c < 4; ++c) {
139 float c00 = panorama[(y0 * panW + x0) * 4 + c];
140 float c10 = panorama[(y0 * panW + x1) * 4 + c];
141 float c01 = panorama[(y1 * panW + x0) * 4 + c];
142 float c11 = panorama[(y1 * panW + x1) * 4 + c];
143 float val = c00 * (1 - fx) * (1 - fy) +
144 c10 * fx * (1 - fy) +
145 c01 * (1 - fx) * fy +
147 faceData[idx + c] =
static_cast<unsigned char>(
148 std::clamp(val, 0.0f, 255.0f));
154 stbi_image_free(panorama);
156 std::vector<unsigned char*> facePointers;
157 for (
int i = 0; i < 6; i++)
158 facePointers.push_back(allFaces[i].data());
160 bool result = CreateCubemapFromFaces(facePointers, faceSize);
164 "DirectX11CubemapTexture: Loaded equirectangular panorama "
171bool DirectX11CubemapTexture::CreateCubemapFromFaces(
172 const std::vector<unsigned char*>& faceData, uint32_t faceSize) {
177 D3D11_TEXTURE2D_DESC texDesc = {};
178 texDesc.Width = faceSize;
179 texDesc.Height = faceSize;
180 texDesc.MipLevels = 1;
181 texDesc.ArraySize = 6;
182 texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
183 texDesc.SampleDesc.Count = 1;
184 texDesc.SampleDesc.Quality = 0;
185 texDesc.Usage = D3D11_USAGE_DEFAULT;
186 texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
187 texDesc.CPUAccessFlags = 0;
188 texDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
191 D3D11_SUBRESOURCE_DATA subData[6] = {};
192 uint32_t rowPitch = faceSize * 4;
193 for (
int i = 0; i < 6; i++) {
194 subData[i].pSysMem = faceData[i];
195 subData[i].SysMemPitch = rowPitch;
196 subData[i].SysMemSlicePitch = 0;
200 m_device->CreateTexture2D(&texDesc, subData, m_texture.GetAddressOf());
203 "DirectX11CubemapTexture: Failed to create cubemap texture! "
205 static_cast<unsigned int>(hr));
210 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
211 srvDesc.Format = texDesc.Format;
212 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
213 srvDesc.TextureCube.MipLevels = 1;
214 srvDesc.TextureCube.MostDetailedMip = 0;
216 hr = m_device->CreateShaderResourceView(m_texture.Get(), &srvDesc,
217 m_shaderResourceView.GetAddressOf());
220 "DirectX11CubemapTexture: Failed to create SRV! HRESULT: "
222 static_cast<unsigned int>(hr));
226 CreateSamplerState();
230void DirectX11CubemapTexture::CreateSamplerState() {
231 D3D11_SAMPLER_DESC samplerDesc = {};
232 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
233 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
234 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
235 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
236 samplerDesc.MipLODBias = 0.0f;
237 samplerDesc.MaxAnisotropy = 1;
238 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
239 samplerDesc.MinLOD = 0;
240 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
243 m_device->CreateSamplerState(&samplerDesc, m_samplerState.GetAddressOf());
246 "DirectX11CubemapTexture: Failed to create sampler state! "
248 static_cast<unsigned int>(hr));
252bool DirectX11CubemapTexture::LoadFromMemory(
const void* data, uint32_t
width,
254 TextureFormat format) {
262bool DirectX11CubemapTexture::LoadFromFile(
const std::string& filePath) {
267void DirectX11CubemapTexture::Bind(uint32_t slot)
const {
268 if (m_shaderResourceView && m_samplerState) {
269 m_deviceContext->PSSetShaderResources(
270 slot, 1, m_shaderResourceView.GetAddressOf());
271 m_deviceContext->PSSetSamplers(slot, 1, m_samplerState.GetAddressOf());
275void DirectX11CubemapTexture::Unbind()
const {
276 ID3D11ShaderResourceView* nullSRV =
nullptr;
277 ID3D11SamplerState* nullSampler =
nullptr;
278 m_deviceContext->PSSetShaderResources(0, 1, &nullSRV);
279 m_deviceContext->PSSetSamplers(0, 1, &nullSampler);
282void DirectX11CubemapTexture::SetFilter(TextureFilter filter) {
286void DirectX11CubemapTexture::SetWrapMode(TextureWrapMode wrapMode) {
DirectX11CubemapTexture(ID3D11Device *device)
Backend-facing rendering layer shared by the four graphics backends.
Root namespace for everything the engine exposes.