2222
2323#include "common/globalconstants.h"
2424#include "common/irradiancefieldparams.h"
25+ #include "utils/encoding.hlsl"
2526#include "utils/constants.hlsl"
2627#include "utils/helpers.hlsl"
2728
@@ -33,7 +34,7 @@ Texture2D<float2> IrradianceFieldProbeDepth : register(t1);
3334struct VS_OUTPUT
3435{
3536 float4 Position : SV_Position ;
36- float2 TexCoord : TEXCOORD0 ;
37+ float3 WorldPos : TEXCOORD0 ;
3738 nointerpolation uint ProbeIndex : TEXCOORD1 ;
3839};
3940
@@ -51,70 +52,88 @@ float3 GetProbeWorldPosition(uint probeIndex)
5152
5253// TODO: This calculation is probably accounting for the border wrong!!
5354// Also, it is not interpolating
54- float3 SampleProbeIrradiance (uint probeIndex, float2 uv )
55+ float3 SampleProbeIrradiance (uint probeIndex, float3 worldDir )
5556{
56- const uint x = probeIndex % IrradianceFieldParams.m_GridResolution.x;
57- const uint temp = probeIndex / IrradianceFieldParams.m_GridResolution.x;
58- const uint y = temp % IrradianceFieldParams.m_GridResolution.y;
59- const uint z = temp / IrradianceFieldParams.m_GridResolution.y;
60-
61- const uint probeAtlasX = x + y * IrradianceFieldParams.m_GridResolution.x;
62- const uint probeAtlasY = z;
63-
64- const float2 probeUV = uv * (IrradianceFieldParams.m_NumProbeIrradianceInteriorTexels + 1.0 );
65-
66- const uint2 atlasCoord = uint2 (
67- probeAtlasX * IrradianceFieldParams.m_NumProbeIrradianceInteriorTexels + probeUV.x,
68- probeAtlasY * IrradianceFieldParams.m_NumProbeIrradianceInteriorTexels + probeUV.y
57+ uint x = probeIndex % IrradianceFieldParams.m_GridResolution.x;
58+ uint temp = probeIndex / IrradianceFieldParams.m_GridResolution.x;
59+ uint y = temp % IrradianceFieldParams.m_GridResolution.y;
60+ uint z = temp / IrradianceFieldParams.m_GridResolution.y;
61+
62+ uint probeAtlasX = x + y * IrradianceFieldParams.m_GridResolution.x;
63+ uint probeAtlasY = z;
64+
65+ float2 octCoord = OctahedralEncode (normalize (worldDir));
66+ float2 probeUV = octCoord * IrradianceFieldParams.m_NumProbeIrradianceInteriorTexels + 1.0 ;
67+
68+ uint probeSize = IrradianceFieldParams.m_NumProbeIrradianceInteriorTexels + 2 ;
69+ uint2 atlasCoord = uint2 (
70+ probeAtlasX * probeSize + probeUV.x,
71+ probeAtlasY * probeSize + probeUV.y
6972 );
70-
71- // Debug visualize temp
72- return float3 (uv, 1.0f );
73-
73+
7474 return IrradianceFieldProbeAtlas[atlasCoord];
7575}
7676
77+ float2 RayIntersectSphere (float3 rayOrigin, float3 rayDir, float4 sphere)
78+ {
79+ float3 oc = rayOrigin - sphere.xyz;
80+ float b = dot (oc, rayDir);
81+ float c = dot (oc, oc) - sphere.w * sphere.w;
82+ float h = b * b - c;
83+
84+ if (h < 0.0 )
85+ return float2 (-1.0 , -1.0 );
86+
87+ h = sqrt (h);
88+ return float2 (-b - h, -b + h);
89+ }
90+
7791VS_OUTPUT VS_Main (uint vertexID : SV_VertexID , uint instanceID : SV_InstanceID )
7892{
7993 VS_OUTPUT output;
8094
81- const float2 offsets[6 ] =
95+ const float2 offsets[6 ] =
8296 {
8397 float2 (-1 , -1 ), float2 (1 , -1 ), float2 (1 , 1 ),
8498 float2 (-1 , -1 ), float2 (1 , 1 ), float2 (-1 , 1 )
8599 };
86100
87- const float2 uvs[6 ] =
88- {
89- float2 (0 , 1 ), float2 (1 , 1 ), float2 (1 , 0 ),
90- float2 (0 , 1 ), float2 (1 , 0 ), float2 (0 , 0 )
91- };
92-
93101 const float3 probeWorldPos = GetProbeWorldPosition (instanceID);
94- const float3 viewDir = normalize (GlobalConstants.m_CameraPosition.xyz - probeWorldPos);
95102
96- // Create orthonormal basis for billboard
97- float3 up = float3 (0 , 1 , 0 );
98- float3 right = normalize (cross (up, viewDir));
99- up = cross (viewDir, right);
103+ const float4 probeClipPos = mul (GlobalConstants.m_ViewProjectionMatrix, float4 (probeWorldPos, 1.0 ));
104+ const float3 probeNDC = probeClipPos.xyz / probeClipPos.w;
105+ const float screenRadius = IrradianceFieldParams.m_VisualizeProbeRadius * 2.0f / probeClipPos.w;
106+
107+ const float aspectRatio = GlobalConstants.m_ProjectionMatrix[1 ][1 ] / GlobalConstants.m_ProjectionMatrix[0 ][0 ];
108+ float2 ndcOffset = offsets[vertexID] * screenRadius;
109+ ndcOffset.x /= aspectRatio;
100110
101- float3 worldPos = probeWorldPos + (right * offsets[vertexID].x + up * offsets[vertexID].y) * IrradianceFieldParams.m_VisualizeProbeRadius;
102- output.Position = mul (GlobalConstants.m_ViewProjectionMatrix, float4 (worldPos, 1.0 ));
103- output.TexCoord = uvs[vertexID];
111+ const float4 vertexClipPos = float4 (probeNDC.xy + ndcOffset, probeNDC.z, 1.0 );
112+ const float4 vertexWorldPos = mul (GlobalConstants.m_ViewProjectionMatrixInv, vertexClipPos);
113+
114+ output.Position = vertexClipPos;
115+ output.WorldPos = vertexWorldPos.xyz / vertexWorldPos.w;
104116 output.ProbeIndex = instanceID;
105117
106118 return output;
107119}
108120
109121float4 PS_Main (VS_OUTPUT IN) : SV_Target
110122{
111- float dist = length (IN.TexCoord * 2.0 - 1.0 );
112- if (dist > 1.0 )
113- discard ;
123+ const float3 probeWorldCenter = GetProbeWorldPosition (IN.ProbeIndex);
124+ const float probeRadius = IrradianceFieldParams.m_VisualizeProbeRadius;
125+ const float3 rayOrigin = GlobalConstants.m_CameraPosition.xyz;
126+ const float3 rayDir = normalize (IN.WorldPos - rayOrigin);
127+
128+ const float4 sphere = float4 (probeWorldCenter, probeRadius);
129+ const float2 intersections = RayIntersectSphere (rayOrigin, rayDir, sphere);
130+ clip (intersections.x);
114131
115- float3 probeColor = SampleProbeIrradiance (IN.ProbeIndex, IN.TexCoord);
132+ const float3 intersectionPos = rayOrigin + rayDir * intersections.x;
133+ const float3 worldDir = normalize (intersectionPos - probeWorldCenter);
134+ const float3 probeColor = SampleProbeIrradiance (IN.ProbeIndex, worldDir);
116135
117- return float4 (probeColor , 1.0 );
136+ return float4 (worldDir , 1.0 );
118137}
119138
120139#endif // __IRRADIANCE_FIELD_VISUALIZE_VSPS_HLSL__
0 commit comments