Files
voxel-game/assets/shaders/equirect_to_cube.slang

73 lines
1.6 KiB
Plaintext

import "includes/math";
[[vk::binding(0, 0)]] SamplerState _EquirectangularSampler;
[[vk::binding(1, 0)]] Texture2D _EquirectangularTexture;
[[vk::binding(2, 0)]] WTexture2DArray _CubemapImage;
static const float3x3 MATRIX_2D_TO_CUBE[6] = {
// Positive X
{
0, 0, 1,
0, -1, 0,
-1, 0, 0,
},
// Negative X
{
0, 0, -1,
0, -1, 0,
1, 0, 0,
},
// Positive Y
{
1, 0, 0,
0, 0, 1,
0, 1, 0,
},
// Negative Y
{
1, 0, 0,
0, 0, -1,
0, -1, 0,
},
// Positive Z
{
1, 0, 0,
0, -1, 0,
0, 0, 1,
},
// Negative Z
{
-1, 0, 0,
0, -1, 0,
0, 0, -1,
}
};
float2 cubemapSize() {
uint width, height, elements;
_CubemapImage.GetDimensions(width, height, elements);
return float2(width, height);
}
[shader("compute")]
[numthreads(8, 8, 1)]
void main(uint3 threadID: SV_DispatchThreadID)
{
let size = cubemapSize();
var texCoord = (float2(threadID.xy) + 0.5) / size;
let layerIndex = threadID.z;
texCoord = 2.0 * texCoord - 1.0; // Map to range [-1, 1]
let cubeCoord = mul(MATRIX_2D_TO_CUBE[layerIndex], float3(texCoord, 1.0));
let cubeDir = normalize(cubeCoord);
let theta = atan2(cubeDir.y, cubeDir.x);
let phi = asin(cubeDir.z);
let equirectCoord = float2(theta * HALF_INV_PI, phi * INV_PI) + 0.5;
let irradiance = _EquirectangularTexture.SampleLevel(_EquirectangularSampler, equirectCoord, 0.0);
_CubemapImage.Store(threadID, irradiance);
}