Browse Source

Convert IndirectSpecular to HLSL

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
3548aae383

+ 0 - 263
AnKi/Shaders/IndirectSpecular.glsl

@@ -1,263 +0,0 @@
-// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma anki mutator STOCHASTIC 0 1
-#pragma anki mutator EXTRA_REJECTION 0 1
-
-#include <AnKi/Shaders/LightFunctions.glsl>
-#include <AnKi/Shaders/PackFunctions.glsl>
-#include <AnKi/Shaders/Include/MiscRendererTypes.h>
-#include <AnKi/Shaders/TonemappingFunctions.glsl>
-#include <AnKi/Shaders/SsRaymarching.glsl>
-
-layout(set = 0, binding = 0, row_major) uniform b_unis
-{
-	SsrUniforms u_unis;
-};
-
-layout(set = 0, binding = 1) uniform sampler u_trilinearClampSampler;
-layout(set = 0, binding = 2) uniform ANKI_RP texture2D u_gbufferRt1;
-layout(set = 0, binding = 3) uniform ANKI_RP texture2D u_gbufferRt2;
-layout(set = 0, binding = 4) uniform texture2D u_depthRt;
-layout(set = 0, binding = 5) uniform ANKI_RP texture2D u_lightBufferRt;
-
-layout(set = 0, binding = 6) uniform ANKI_RP texture2D u_historyTex;
-layout(set = 0, binding = 7) uniform texture2D u_motionVectorsTex;
-layout(set = 0, binding = 8) uniform ANKI_RP texture2D u_historyLengthTex;
-
-layout(set = 0, binding = 9) uniform sampler u_trilinearRepeatSampler;
-layout(set = 0, binding = 10) uniform ANKI_RP texture2D u_noiseTex;
-const Vec2 NOISE_TEX_SIZE = Vec2(64.0);
-
-#define CLUSTERED_SHADING_SET 0u
-#define CLUSTERED_SHADING_UNIFORMS_BINDING 11u
-#define CLUSTERED_SHADING_REFLECTIONS_BINDING 12u
-#define CLUSTERED_SHADING_CLUSTERS_BINDING 14u
-#include <AnKi/Shaders/ClusteredShadingCommon.glsl>
-
-#if defined(ANKI_COMPUTE_SHADER)
-const UVec2 kWorkgroupSize = UVec2(8, 8);
-layout(local_size_x = kWorkgroupSize.x, local_size_y = kWorkgroupSize.y, local_size_z = 1) in;
-
-layout(set = 0, binding = 15) uniform writeonly image2D u_outImg;
-#else
-layout(location = 0) in Vec2 in_uv;
-layout(location = 0) out Vec3 out_color;
-#endif
-
-void main()
-{
-#if defined(ANKI_COMPUTE_SHADER)
-	if(skipOutOfBoundsInvocations(kWorkgroupSize, u_unis.m_framebufferSize))
-	{
-		return;
-	}
-	const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(u_unis.m_framebufferSize);
-#else
-	const Vec2 uv = in_uv;
-#endif
-
-	// Read part of the G-buffer
-	const F32 roughness = unpackRoughnessFromGBuffer(textureLod(u_gbufferRt1, u_trilinearClampSampler, uv, 0.0));
-	const Vec3 worldNormal = unpackNormalFromGBuffer(textureLod(u_gbufferRt2, u_trilinearClampSampler, uv, 0.0));
-
-	// Get depth
-	const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, uv, 0.0).r;
-
-	// Rand idx
-	const Vec2 noiseUv = Vec2(u_unis.m_framebufferSize) / NOISE_TEX_SIZE * uv;
-	const Vec3 noise =
-		animateBlueNoise(textureLod(u_noiseTex, u_trilinearRepeatSampler, noiseUv, 0.0).rgb, u_unis.m_frameCount % 8u);
-
-	// Get view pos
-	const Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
-	const Vec3 viewPos = viewPos4.xyz / viewPos4.w;
-
-	// Compute refl vector
-	const Vec3 viewDir = -normalize(viewPos);
-	const Vec3 viewNormal = u_unis.m_normalMat * Vec4(worldNormal, 0.0);
-#if STOCHASTIC
-	const Vec3 reflDir = sampleReflectionVector(viewDir, viewNormal, roughness, noise.xy);
-#else
-	const Vec3 reflDir = reflect(-viewDir, viewNormal);
-#endif
-
-	// Is rough enough to deserve SSR?
-	F32 ssrAttenuation = saturate(1.0f - pow(roughness / u_unis.m_roughnessCutoff, 16.0f));
-
-	// Do the heavy work
-	Vec3 hitPoint;
-	if(ssrAttenuation > kEpsilonf)
-	{
-		const U32 lod = 8u; // Use the max LOD for ray marching
-		const U32 step = u_unis.m_firstStepPixels;
-		const F32 stepf = F32(step);
-		const F32 minStepf = stepf / 4.0;
-		F32 hitAttenuation;
-		raymarchGroundTruth(viewPos, reflDir, uv, depth, u_unis.m_projMat, u_unis.m_maxSteps, u_depthRt,
-							u_trilinearClampSampler, F32(lod), u_unis.m_depthBufferSize, step,
-							U32((stepf - minStepf) * noise.x + minStepf), hitPoint, hitAttenuation);
-
-		ssrAttenuation *= hitAttenuation;
-	}
-	else
-	{
-		ssrAttenuation = 0.0f;
-	}
-
-#if EXTRA_REJECTION
-	// Reject backfacing
-	[branch] if(ssrAttenuation > 0.0)
-	{
-		const Vec3 hitNormal =
-			u_unis.m_normalMat
-			* Vec4(unpackNormalFromGBuffer(textureLod(u_gbufferRt2, u_trilinearClampSampler, hitPoint.xy, 0.0)), 0.0);
-		F32 backFaceAttenuation;
-		rejectBackFaces(reflDir, hitNormal, backFaceAttenuation);
-
-		ssrAttenuation *= backFaceAttenuation;
-	}
-
-	// Reject far from hit point
-	[branch] if(ssrAttenuation > 0.0)
-	{
-		const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, hitPoint.xy, 0.0).r;
-		Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(hitPoint.xy), depth, 1.0);
-		const F32 actualZ = viewPos4.z / viewPos4.w;
-
-		viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(hitPoint.xy), hitPoint.z, 1.0);
-		const F32 hitZ = viewPos4.z / viewPos4.w;
-
-		const F32 rejectionMeters = 1.0;
-		const F32 diff = abs(actualZ - hitZ);
-		const F32 distAttenuation = (diff < rejectionMeters) ? 1.0 : 0.0;
-		ssrAttenuation *= distAttenuation;
-	}
-#endif
-
-	// Read the reflection
-	Vec3 outColor = Vec3(0.0);
-	[branch] if(ssrAttenuation > 0.0)
-	{
-		// Reproject the UV because you are reading the previous frame
-		const Vec4 v4 = u_unis.m_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(hitPoint.xy), hitPoint.z, 1.0);
-		hitPoint.xy = NDC_TO_UV(v4.xy / v4.w);
-
-#if STOCHASTIC
-		// LOD stays 0
-		const F32 lod = 0.0;
-#else
-		// Compute the LOD based on the roughness
-		const F32 lod = F32(u_unis.m_lightBufferMipCount - 1u) * roughness;
-#endif
-
-		// Read the light buffer
-		Vec3 ssrColor = textureLod(u_lightBufferRt, u_trilinearClampSampler, hitPoint.xy, lod).rgb;
-		ssrColor = clamp(ssrColor, 0.0, kMaxF32); // Fix the value just in case
-
-		outColor = ssrColor;
-	}
-
-	// Blend with history
-	{
-		const Vec2 historyUv = uv + textureLod(u_motionVectorsTex, u_trilinearClampSampler, uv, 0.0).xy;
-		const F32 historyLength = textureLod(u_historyLengthTex, u_trilinearClampSampler, uv, 0.0).x;
-
-		const F32 lowestBlendFactor = 0.2;
-		const F32 maxHistoryLength = 16.0;
-		const F32 stableFrames = 4.0;
-		const F32 lerp = min(1.0, (historyLength * maxHistoryLength - 1.0) / stableFrames);
-		const F32 blendFactor = mix(1.0, lowestBlendFactor, lerp);
-
-		// Blend with history
-		if(blendFactor < 1.0)
-		{
-			const ANKI_RP Vec3 history = textureLod(u_historyTex, u_trilinearClampSampler, historyUv, 0.0).xyz;
-			outColor = mix(history, outColor, blendFactor);
-		}
-	}
-
-	// Read probes
-	[branch] if(ssrAttenuation < 1.0)
-	{
-#if defined(ANKI_COMPUTE_SHADER)
-		const Vec2 fragCoord = Vec2(gl_GlobalInvocationID.xy) + 0.5;
-#else
-		const Vec2 fragCoord = gl_FragCoord.xy;
-#endif
-
-#if STOCHASTIC
-		const F32 reflLod = 0.0;
-#else
-		const F32 reflLod = (u_clusteredShading.m_reflectionProbesMipCount - 1.0) * roughness;
-#endif
-
-		// Get cluster
-		const Vec2 ndc = UV_TO_NDC(uv);
-		const Vec4 worldPos4 = u_clusteredShading.m_matrices.m_invertedViewProjectionJitter * Vec4(ndc, depth, 1.0);
-		const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
-		Cluster cluster = getClusterFragCoord(Vec3(fragCoord * 2.0, depth));
-
-		// Compute the refl dir in word space this time
-		const ANKI_RP Vec3 viewDir = normalize(u_clusteredShading.m_cameraPosition - worldPos);
-#if STOCHASTIC
-		const Vec3 reflDir = sampleReflectionVector(viewDir, worldNormal, roughness, noise.xy);
-#else
-		const Vec3 reflDir = reflect(-viewDir, worldNormal);
-#endif
-
-		Vec3 probeColor = Vec3(0.0);
-
-		if(bitCount(cluster.m_reflectionProbesMask) == 1)
-		{
-			// Only one probe, do a fast path without blend weight
-
-			const ReflectionProbe probe = u_reflectionProbes[findLSB2(cluster.m_reflectionProbesMask)];
-
-			// Sample
-			const Vec3 cubeUv = intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
-			const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
-			probeColor = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
-		}
-		else
-		{
-			// Zero or more than one probes, do a slow path that blends them together
-
-			F32 totalBlendWeight = kEpsilonf;
-
-			// Loop probes
-			[[dont_unroll]] while(cluster.m_reflectionProbesMask != 0u)
-			{
-				const U32 idx = U32(findLSB2(cluster.m_reflectionProbesMask));
-				cluster.m_reflectionProbesMask &= ~(1u << idx);
-				const ReflectionProbe probe = u_reflectionProbes[idx];
-
-				// Compute blend weight
-				const F32 blendWeight = computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, 0.2);
-				totalBlendWeight += blendWeight;
-
-				// Sample reflections
-				const Vec3 cubeUv =
-					intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
-				const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
-				const Vec3 c = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
-				probeColor += c * blendWeight;
-			}
-
-			// Normalize the colors
-			probeColor /= totalBlendWeight;
-		}
-
-		outColor = mix(probeColor, outColor, ssrAttenuation);
-	}
-
-	// Store
-	ssrAttenuation = saturate(ssrAttenuation);
-#if defined(ANKI_COMPUTE_SHADER)
-	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
-#else
-	out_color = outColor;
-#endif
-}

+ 258 - 0
AnKi/Shaders/IndirectSpecular.hlsl

@@ -0,0 +1,258 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki hlsl
+
+#pragma anki mutator STOCHASTIC 0 1
+#pragma anki mutator EXTRA_REJECTION 0 1
+
+#include <AnKi/Shaders/LightFunctions.hlsl>
+#include <AnKi/Shaders/PackFunctions.hlsl>
+#include <AnKi/Shaders/Include/MiscRendererTypes.h>
+#include <AnKi/Shaders/TonemappingFunctions.hlsl>
+#include <AnKi/Shaders/SsRaymarching.hlsl>
+
+[[vk::binding(0)]] ConstantBuffer<SsrUniforms> g_unis;
+
+[[vk::binding(1)]] SamplerState g_trilinearClampSampler;
+[[vk::binding(2)]] Texture2D<RVec4> g_gbufferRt1;
+[[vk::binding(3)]] Texture2D<RVec4> g_gbufferRt2;
+[[vk::binding(4)]] Texture2D g_depthRt;
+[[vk::binding(5)]] Texture2D<RVec4> g_lightBufferRt;
+
+[[vk::binding(6)]] Texture2D<RVec4> g_historyTex;
+[[vk::binding(7)]] Texture2D g_motionVectorsTex;
+[[vk::binding(8)]] Texture2D<RVec4> g_historyLengthTex;
+
+[[vk::binding(9)]] SamplerState g_trilinearRepeatSampler;
+[[vk::binding(10)]] Texture2D<RVec4> g_noiseTex;
+constexpr Vec2 kNoiseTexSize = 64.0;
+
+#define CLUSTERED_SHADING_SET 0u
+#define CLUSTERED_SHADING_UNIFORMS_BINDING 11u
+#define CLUSTERED_SHADING_REFLECTIONS_BINDING 12u
+#define CLUSTERED_SHADING_CLUSTERS_BINDING 14u
+#include <AnKi/Shaders/ClusteredShadingCommon.hlsl>
+
+#if defined(ANKI_COMPUTE_SHADER)
+[[vk::binding(15)]] RWTexture2D<RVec4> g_outUav;
+#endif
+
+#if defined(ANKI_COMPUTE_SHADER)
+[numthreads(8, 8, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
+#else
+RVec3 main(Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITION) : SV_TARGET0
+#endif
+{
+#if defined(ANKI_COMPUTE_SHADER)
+	if(any(svDispatchThreadId.xy >= g_unis.m_framebufferSize))
+	{
+		return;
+	}
+	const Vec2 uv = (Vec2(svDispatchThreadId.xy) + 0.5) / Vec2(g_unis.m_framebufferSize);
+#endif
+
+	// Read part of the G-buffer
+	const F32 roughness = unpackRoughnessFromGBuffer(g_gbufferRt1.SampleLevel(g_trilinearClampSampler, uv, 0.0));
+	const Vec3 worldNormal = unpackNormalFromGBuffer(g_gbufferRt2.SampleLevel(g_trilinearClampSampler, uv, 0.0));
+
+	// Get depth
+	const F32 depth = g_depthRt.SampleLevel(g_trilinearClampSampler, uv, 0.0).r;
+
+	// Rand idx
+	const Vec2 noiseUv = Vec2(g_unis.m_framebufferSize) / kNoiseTexSize * uv;
+	const Vec3 noise =
+		animateBlueNoise(g_noiseTex.SampleLevel(g_trilinearRepeatSampler, noiseUv, 0.0).rgb, g_unis.m_frameCount % 8u);
+
+	// Get view pos
+	const Vec4 viewPos4 = mul(g_unis.m_invProjMat, Vec4(uvToNdc(uv), depth, 1.0));
+	const Vec3 viewPos = viewPos4.xyz / viewPos4.w;
+
+	// Compute refl vector
+	const Vec3 viewDir = -normalize(viewPos);
+	const Vec3 viewNormal = mul(g_unis.m_normalMat, Vec4(worldNormal, 0.0));
+#if STOCHASTIC
+	const Vec3 reflDir = sampleReflectionVector(viewDir, viewNormal, roughness, noise.xy);
+#else
+	const Vec3 reflDir = reflect(-viewDir, viewNormal);
+#endif
+
+	// Is rough enough to deserve SSR?
+	F32 ssrAttenuation = saturate(1.0f - pow(roughness / g_unis.m_roughnessCutoff, 16.0f));
+
+	// Do the heavy work
+	Vec3 hitPoint;
+	if(ssrAttenuation > kEpsilonF32)
+	{
+		const U32 lod = 8u; // Use the max LOD for ray marching
+		const U32 step = g_unis.m_firstStepPixels;
+		const F32 stepf = F32(step);
+		const F32 minStepf = stepf / 4.0;
+		F32 hitAttenuation;
+		raymarchGroundTruth(viewPos, reflDir, uv, depth, g_unis.m_projMat, g_unis.m_maxSteps, g_depthRt,
+							g_trilinearClampSampler, F32(lod), g_unis.m_depthBufferSize, step,
+							U32((stepf - minStepf) * noise.x + minStepf), hitPoint, hitAttenuation);
+
+		ssrAttenuation *= hitAttenuation;
+	}
+	else
+	{
+		ssrAttenuation = 0.0f;
+	}
+
+#if EXTRA_REJECTION
+	// Reject backfacing
+	[branch] if(ssrAttenuation > 0.0)
+	{
+		const Vec3 gbufferNormal =
+			unpackNormalFromGBuffer(g_gbufferRt2.SampleLevel(g_trilinearClampSampler, hitPoint.xy, 0.0));
+		const Vec3 hitNormal = mul(g_unis.m_normalMat, Vec4(gbufferNormal, 0.0));
+		F32 backFaceAttenuation;
+		rejectBackFaces(reflDir, hitNormal, backFaceAttenuation);
+
+		ssrAttenuation *= backFaceAttenuation;
+	}
+
+	// Reject far from hit point
+	[branch] if(ssrAttenuation > 0.0)
+	{
+		const F32 depth = g_depthRt.SampleLevel(g_trilinearClampSampler, hitPoint.xy, 0.0).r;
+		Vec4 viewPos4 = mul(g_unis.m_invProjMat, Vec4(uvToNdc(hitPoint.xy), depth, 1.0));
+		const F32 actualZ = viewPos4.z / viewPos4.w;
+
+		viewPos4 = mul(g_unis.m_invProjMat, Vec4(uvToNdc(hitPoint.xy), hitPoint.z, 1.0));
+		const F32 hitZ = viewPos4.z / viewPos4.w;
+
+		const F32 rejectionMeters = 1.0;
+		const F32 diff = abs(actualZ - hitZ);
+		const F32 distAttenuation = (diff < rejectionMeters) ? 1.0 : 0.0;
+		ssrAttenuation *= distAttenuation;
+	}
+#endif
+
+	// Read the reflection
+	Vec3 outColor = 0.0;
+	[branch] if(ssrAttenuation > 0.0)
+	{
+		// Reproject the UV because you are reading the previous frame
+		const Vec4 v4 = mul(g_unis.m_prevViewProjMatMulInvViewProjMat, Vec4(uvToNdc(hitPoint.xy), hitPoint.z, 1.0));
+		hitPoint.xy = ndcToUv(v4.xy / v4.w);
+
+#if STOCHASTIC
+		// LOD stays 0
+		const F32 lod = 0.0;
+#else
+		// Compute the LOD based on the roughness
+		const F32 lod = F32(g_unis.m_lightBufferMipCount - 1u) * roughness;
+#endif
+
+		// Read the light buffer
+		Vec3 ssrColor = g_lightBufferRt.SampleLevel(g_trilinearClampSampler, hitPoint.xy, lod).rgb;
+		ssrColor = clamp(ssrColor, 0.0, kMaxF32); // Fix the value just in case
+
+		outColor = ssrColor;
+	}
+
+	// Blend with history
+	{
+		const Vec2 historyUv = uv + g_motionVectorsTex.SampleLevel(g_trilinearClampSampler, uv, 0.0).xy;
+		const F32 historyLength = g_historyLengthTex.SampleLevel(g_trilinearClampSampler, uv, 0.0).x;
+
+		const F32 lowestBlendFactor = 0.2;
+		const F32 maxHistoryLength = 16.0;
+		const F32 stableFrames = 4.0;
+		const F32 lerpv = min(1.0, (historyLength * maxHistoryLength - 1.0) / stableFrames);
+		const F32 blendFactor = lerp(1.0, lowestBlendFactor, lerpv);
+
+		// Blend with history
+		if(blendFactor < 1.0)
+		{
+			const RVec3 history = g_historyTex.SampleLevel(g_trilinearClampSampler, historyUv, 0.0).xyz;
+			outColor = lerp(history, outColor, blendFactor);
+		}
+	}
+
+	// Read probes
+	[branch] if(ssrAttenuation < 1.0)
+	{
+#if defined(ANKI_COMPUTE_SHADER)
+		const Vec2 fragCoord = Vec2(svDispatchThreadId.xy) + 0.5;
+#else
+		const Vec2 fragCoord = svPosition.xy;
+#endif
+
+#if STOCHASTIC
+		const F32 reflLod = 0.0;
+#else
+		const F32 reflLod = (g_clusteredShading.m_reflectionProbesMipCount - 1.0) * roughness;
+#endif
+
+		// Get cluster
+		const Vec2 ndc = uvToNdc(uv);
+		const Vec4 worldPos4 = mul(g_clusteredShading.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
+		const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
+		Cluster cluster = getClusterFragCoord(Vec3(fragCoord * 2.0, depth));
+
+		// Compute the refl dir in word space this time
+		const RVec3 viewDir = normalize(g_clusteredShading.m_cameraPosition - worldPos);
+#if STOCHASTIC
+		const Vec3 reflDir = sampleReflectionVector(viewDir, worldNormal, roughness, noise.xy);
+#else
+		const Vec3 reflDir = reflect(-viewDir, worldNormal);
+#endif
+
+		Vec3 probeColor = 0.0;
+
+		if(countbits(cluster.m_reflectionProbesMask) == 1)
+		{
+			// Only one probe, do a fast path without blend weight
+
+			const ReflectionProbe probe = g_reflectionProbes[firstbitlow2(cluster.m_reflectionProbesMask)];
+
+			// Sample
+			const Vec3 cubeUv = intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
+			const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
+			probeColor = g_reflectionsTex.SampleLevel(g_trilinearClampSampler, cubeArrUv, reflLod).rgb;
+		}
+		else
+		{
+			// Zero or more than one probes, do a slow path that blends them together
+
+			F32 totalBlendWeight = kEpsilonF32;
+
+			// Loop probes
+			[loop] while(cluster.m_reflectionProbesMask != 0u)
+			{
+				const U32 idx = U32(firstbitlow2(cluster.m_reflectionProbesMask));
+				cluster.m_reflectionProbesMask &= ~(1u << idx);
+				const ReflectionProbe probe = g_reflectionProbes[idx];
+
+				// Compute blend weight
+				const F32 blendWeight = computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, 0.2);
+				totalBlendWeight += blendWeight;
+
+				// Sample reflections
+				const Vec3 cubeUv =
+					intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
+				const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
+				const Vec3 c = g_reflectionsTex.SampleLevel(g_trilinearClampSampler, cubeArrUv, reflLod).rgb;
+				probeColor += c * blendWeight;
+			}
+
+			// Normalize the colors
+			probeColor /= totalBlendWeight;
+		}
+
+		outColor = lerp(probeColor, outColor, ssrAttenuation);
+	}
+
+	// Store
+	ssrAttenuation = saturate(ssrAttenuation);
+#if defined(ANKI_COMPUTE_SHADER)
+	g_outUav[svDispatchThreadId.xy] = RVec4(outColor, 0.0);
+#else
+	return outColor;
+#endif
+}

+ 1 - 1
AnKi/Shaders/IndirectSpecularCompute.ankiprog

@@ -4,5 +4,5 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #pragma anki start comp
 #pragma anki start comp
-#include <AnKi/Shaders/IndirectSpecular.glsl>
+#include <AnKi/Shaders/IndirectSpecular.hlsl>
 #pragma anki end
 #pragma anki end

+ 2 - 2
AnKi/Shaders/IndirectSpecularRaster.ankiprog

@@ -4,9 +4,9 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #pragma anki start vert
 #pragma anki start vert
-#include <AnKi/Shaders/QuadVert.glsl>
+#include <AnKi/Shaders/QuadVert.hlsl>
 #pragma anki end
 #pragma anki end
 
 
 #pragma anki start frag
 #pragma anki start frag
-#include <AnKi/Shaders/IndirectSpecular.glsl>
+#include <AnKi/Shaders/IndirectSpecular.hlsl>
 #pragma anki end
 #pragma anki end

+ 17 - 16
AnKi/Shaders/SsRaymarching.glsl → AnKi/Shaders/SsRaymarching.hlsl

@@ -7,7 +7,7 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <AnKi/Shaders/Common.glsl>
+#include <AnKi/Shaders/Common.hlsl>
 
 
 // Find the intersection of a ray and a AABB when the ray is inside the AABB
 // Find the intersection of a ray and a AABB when the ray is inside the AABB
 void rayAabbIntersectionInside2d(Vec2 rayOrigin, Vec2 rayDir, Vec2 aabbMin, Vec2 aabbMax, out F32 t)
 void rayAabbIntersectionInside2d(Vec2 rayOrigin, Vec2 rayDir, Vec2 aabbMin, Vec2 aabbMax, out F32 t)
@@ -62,9 +62,11 @@ void raymarch(Vec3 rayOrigin, // Ray origin in view space
 			  Vec2 uv, // UV the ray starts
 			  Vec2 uv, // UV the ray starts
 			  F32 depthRef, // Depth the ray starts
 			  F32 depthRef, // Depth the ray starts
 			  Mat4 projMat, // Projection matrix
 			  Mat4 projMat, // Projection matrix
-			  U32 randFrom0To3, U32 maxIterations, texture2D hizTex, sampler hizSampler, U32 hizMipCount,
+			  U32 randFrom0To3, U32 maxIterations, Texture2D hizTex, SamplerState hizSampler, U32 hizMipCount,
 			  UVec2 hizMip0Size, out Vec3 hitPoint, out F32 attenuation)
 			  UVec2 hizMip0Size, out Vec3 hitPoint, out F32 attenuation)
 {
 {
+	ANKI_MAYBE_UNUSED(uv);
+	ANKI_MAYBE_UNUSED(depthRef);
 	attenuation = 0.0;
 	attenuation = 0.0;
 
 
 	// Check for view facing reflections [sakibsaikia]
 	// Check for view facing reflections [sakibsaikia]
@@ -76,7 +78,7 @@ void raymarch(Vec3 rayOrigin, // Ray origin in view space
 	}
 	}
 
 
 	// Dither and set starting pos
 	// Dither and set starting pos
-	const F32 bayerMat[4] = F32[](1.0, 4.0, 2.0, 3.0);
+	const F32 bayerMat[4] = {1.0, 4.0, 2.0, 3.0};
 	const Vec3 p0 = rayOrigin + rayDir * (tmin * bayerMat[randFrom0To3]);
 	const Vec3 p0 = rayOrigin + rayDir * (tmin * bayerMat[randFrom0To3]);
 
 
 	// p1
 	// p1
@@ -84,12 +86,12 @@ void raymarch(Vec3 rayOrigin, // Ray origin in view space
 	const Vec3 p1 = rayOrigin + rayDir * tmax;
 	const Vec3 p1 = rayOrigin + rayDir * tmax;
 
 
 	// Compute start & end in clip space (well not clip space since x,y are in [0, 1])
 	// Compute start & end in clip space (well not clip space since x,y are in [0, 1])
-	Vec4 v4 = projMat * Vec4(p0, 1.0);
+	Vec4 v4 = mul(projMat, Vec4(p0, 1.0));
 	Vec3 start = v4.xyz / v4.w;
 	Vec3 start = v4.xyz / v4.w;
-	start.xy = NDC_TO_UV(start.xy);
-	v4 = projMat * Vec4(p1, 1.0);
+	start.xy = ndcToUv(start.xy);
+	v4 = mul(projMat, Vec4(p1, 1.0));
 	Vec3 end = v4.xyz / v4.w;
 	Vec3 end = v4.xyz / v4.w;
-	end.xy = NDC_TO_UV(end.xy);
+	end.xy = ndcToUv(end.xy);
 
 
 	// Ray
 	// Ray
 	Vec3 origin = start;
 	Vec3 origin = start;
@@ -104,9 +106,9 @@ void raymarch(Vec3 rayOrigin, // Ray origin in view space
 		stepToNextCell(origin, dir, U32(mipLevel), hizMip0Size, newOrigin);
 		stepToNextCell(origin, dir, U32(mipLevel), hizMip0Size, newOrigin);
 		origin = newOrigin;
 		origin = newOrigin;
 
 
-		if(all(greaterThan(origin.xy, Vec2(0.0))) && all(lessThan(origin.xy, Vec2(1.0))))
+		if(all(origin.xy > Vec2(0.0, 0.0)) && all(origin.xy < Vec2(1.0, 1.0)))
 		{
 		{
-			const F32 newDepth = textureLod(hizTex, hizSampler, origin.xy, F32(mipLevel)).r;
+			const F32 newDepth = hizTex.SampleLevel(hizSampler, origin.xy, F32(mipLevel)).r;
 
 
 			if(origin.z < newDepth)
 			if(origin.z < newDepth)
 			{
 			{
@@ -148,8 +150,8 @@ void raymarchGroundTruth(Vec3 rayOrigin, // Ray origin in view space
 						 F32 depthRef, // Depth the ray starts
 						 F32 depthRef, // Depth the ray starts
 						 Mat4 projMat, // Projection matrix
 						 Mat4 projMat, // Projection matrix
 						 U32 maxSteps, // The max iterations of the base algorithm
 						 U32 maxSteps, // The max iterations of the base algorithm
-						 texture2D depthTex, // Depth tex
-						 sampler depthSampler, // Sampler for depthTex
+						 Texture2D depthTex, // Depth tex
+						 SamplerState depthSampler, // Sampler for depthTex
 						 F32 depthLod, // LOD to pass to the textureLod
 						 F32 depthLod, // LOD to pass to the textureLod
 						 UVec2 depthTexSize, // Size of the depthTex
 						 UVec2 depthTexSize, // Size of the depthTex
 						 U32 initialStepIncrement, // Initial step increment
 						 U32 initialStepIncrement, // Initial step increment
@@ -168,14 +170,13 @@ void raymarchGroundTruth(Vec3 rayOrigin, // Ray origin in view space
 	}
 	}
 
 
 	// Start point
 	// Start point
-	const Vec3 p0 = rayOrigin;
 	const Vec3 start = Vec3(uv, depthRef);
 	const Vec3 start = Vec3(uv, depthRef);
 
 
 	// Project end point
 	// Project end point
 	const Vec3 p1 = rayOrigin + rayDir * 0.1;
 	const Vec3 p1 = rayOrigin + rayDir * 0.1;
-	const Vec4 end4 = projMat * Vec4(p1, 1.0);
+	const Vec4 end4 = mul(projMat, Vec4(p1, 1.0));
 	Vec3 end = end4.xyz / end4.w;
 	Vec3 end = end4.xyz / end4.w;
-	end.xy = NDC_TO_UV(end.xy);
+	end.xy = ndcToUv(end.xy);
 
 
 	// Compute the ray and step size
 	// Compute the ray and step size
 	Vec3 dir = end - start;
 	Vec3 dir = end - start;
@@ -189,7 +190,7 @@ void raymarchGroundTruth(Vec3 rayOrigin, // Ray origin in view space
 
 
 	// Search
 	// Search
 	Vec3 origin;
 	Vec3 origin;
-	[[dont_unroll]] while(maxSteps-- != 0u)
+	[loop] while(maxSteps-- != 0u)
 	{
 	{
 		origin = start + dir * (F32(crntStep) * stepSize);
 		origin = start + dir * (F32(crntStep) * stepSize);
 
 
@@ -199,7 +200,7 @@ void raymarchGroundTruth(Vec3 rayOrigin, // Ray origin in view space
 			break;
 			break;
 		}
 		}
 
 
-		const F32 depth = textureLod(depthTex, depthSampler, origin.xy, depthLod).r;
+		const F32 depth = depthTex.SampleLevel(depthSampler, origin.xy, depthLod).r;
 		const Bool hit = origin.z - depth >= 0.0;
 		const Bool hit = origin.z - depth >= 0.0;
 		if(!hit)
 		if(!hit)
 		{
 		{