Browse Source

Add 2 new shaders

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
3986cb1c21
2 changed files with 274 additions and 0 deletions
  1. 103 0
      shaders/SsgiDenoise.ankiprog
  2. 171 0
      shaders/SsgiRecontruct.ankiprog

+ 103 - 0
shaders/SsgiDenoise.ankiprog

@@ -0,0 +1,103 @@
+// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki mutator VARIANT 0 1 2 3
+#pragma anki mutator ORIENTATION 0 1 // 0: VERTICAL, 1: HORIZONTAL
+#pragma anki mutator SAMPLE_COUNT 3 5 7 9 11 13 15
+
+ANKI_SPECIALIZATION_CONSTANT_UVEC2(IN_TEXTURE_SIZE, 0, UVec2(1));
+
+#pragma anki start comp
+
+#include <shaders/Common.glsl>
+
+#if SAMPLE_COUNT < 3
+#	error See file
+#endif
+
+const UVec2 WORKGROUP_SIZE = UVec2(8u, 8u);
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
+layout(set = 0, binding = 1) uniform texture2D u_inTex;
+layout(set = 0, binding = 2) uniform texture2D u_depthTex;
+layout(set = 0, binding = 3) writeonly uniform image2D u_outImg;
+
+F32 computeDepthWeight(F32 refDepth, F32 depth)
+{
+	const F32 diff = abs(refDepth - depth);
+	const F32 weight = 1.0 - pow(diff, 0.5);
+	return weight;
+}
+
+F32 readDepth(Vec2 uv)
+{
+	return textureLod(u_depthTex, u_linearAnyClampSampler, uv, 0.0).r;
+}
+
+void sampleTex(Vec2 inUv, Vec2 depthUv, F32 refDepth, inout Vec3 col, inout F32 weight)
+{
+	const Vec3 color = textureLod(u_inTex, u_linearAnyClampSampler, inUv, 0.0).rgb;
+	const F32 w = computeDepthWeight(refDepth, readDepth(depthUv));
+	col += color * w;
+	weight += w;
+}
+
+void main()
+{
+	// Set UVs
+	ANKI_BRANCH if(gl_GlobalInvocationID.x >= IN_TEXTURE_SIZE.x || gl_GlobalInvocationID.y >= IN_TEXTURE_SIZE.y)
+	{
+		// Out of bounds
+		return;
+	}
+
+	const Vec2 inUv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(IN_TEXTURE_SIZE);
+#if VARIANT == 0
+	const UVec2 depthReadOffset = UVec2(0, 0);
+#elif VARIANT == 1
+	const UVec2 depthReadOffset = UVec2(1, 0);
+#elif VARIANT == 2
+	const UVec2 depthReadOffset = UVec2(1, 1);
+#else
+	const UVec2 depthReadOffset = UVec2(1, 0);
+#endif
+	const Vec2 depthUv = (Vec2(gl_GlobalInvocationID.xy * 2 + depthReadOffset) + 0.5) / Vec2(IN_TEXTURE_SIZE * 2);
+
+	const Vec2 IN_TEXEL_SIZE = 1.0 / Vec2(IN_TEXTURE_SIZE);
+	const Vec2 DEPTH_TEXEL_SIZE = 1.0 / Vec2(IN_TEXTURE_SIZE * 2);
+
+	// Reference
+	Vec3 color = textureLod(u_inTex, u_linearAnyClampSampler, inUv, 0.0).rgb;
+	const F32 refDepth = readDepth(depthUv);
+	F32 weight = 1.0;
+
+#if ORIENTATION == 1
+#	define X_OR_Y x
+#else
+#	define X_OR_Y y
+#endif
+
+	Vec2 inUvOffset = Vec2(0.0);
+	inUvOffset.X_OR_Y = 1.5 * IN_TEXEL_SIZE.X_OR_Y;
+	Vec2 depthUvOffset = Vec2(0.0);
+	depthUvOffset.X_OR_Y = 1.5 * DEPTH_TEXEL_SIZE.X_OR_Y;
+
+	ANKI_UNROLL for(U32 i = 0u; i < (SAMPLE_COUNT - 1u) / 2u; ++i)
+	{
+		sampleTex(inUv + inUvOffset, depthUv + depthUvOffset, refDepth, color, weight);
+		sampleTex(inUv - inUvOffset, depthUv - depthUvOffset, refDepth, color, weight);
+
+		inUvOffset.X_OR_Y += IN_TEXEL_SIZE.X_OR_Y;
+		depthUvOffset.X_OR_Y += DEPTH_TEXEL_SIZE.X_OR_Y;
+	}
+
+	color /= weight;
+
+	// Write value
+	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(color, 0.0));
+}
+
+#pragma anki end

+ 171 - 0
shaders/SsgiRecontruct.ankiprog

@@ -0,0 +1,171 @@
+// Copyright (C) 2009-2020, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki mutator VARIANT 0 1 2 3
+
+ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 0, UVec2(1));
+
+#pragma anki start comp
+
+#include <shaders/Common.glsl>
+
+const UVec2 WORKGROUP_SIZE = UVec2(8u, 8u);
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+
+layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
+layout(set = 0, binding = 1) uniform texture2D u_inTex;
+layout(set = 0, binding = 2) uniform texture2D u_depthTex;
+layout(set = 0, binding = 3) writeonly uniform image2D u_outImg;
+
+shared Vec3 s_colors[WORKGROUP_SIZE.y + 2][WORKGROUP_SIZE.x + 2];
+shared Vec4 s_depths[WORKGROUP_SIZE.y + 2][WORKGROUP_SIZE.x + 2];
+
+Vec3 computeDepthWeights(F32 refDepth, Vec3 depths)
+{
+	const Vec3 diffs = abs(refDepth - depths);
+	const Vec3 weights = 1.0 - pow(diffs, Vec3(0.5));
+	return weights;
+}
+
+void reconstruct(IVec2 storeCoord, F32 depthRef, Vec4 colorAndDepth0, Vec4 colorAndDepth1, Vec4 colorAndDepth2)
+{
+	const Vec3 weights = computeDepthWeights(depthRef, Vec3(colorAndDepth0.w, colorAndDepth1.w, colorAndDepth2.w));
+	const F32 weightSum = weights[0] + weights[1] + weights[2];
+
+	Vec3 col = colorAndDepth0.rgb * weights[0];
+	col += colorAndDepth1.rgb * weights[1];
+	col += colorAndDepth2.rgb * weights[2];
+	col /= weightSum;
+
+	imageStore(u_outImg, storeCoord, Vec4(col, 0.0));
+}
+
+void main()
+{
+	const UVec2 IN_TEXTURE_SIZE = FB_SIZE / 2;
+	ANKI_BRANCH if(gl_GlobalInvocationID.x >= IN_TEXTURE_SIZE.x || gl_GlobalInvocationID.y >= IN_TEXTURE_SIZE.y)
+	{
+		// Out of bounds
+		return;
+	}
+
+	const Vec2 inTexelSize = 1.0 / Vec2(IN_TEXTURE_SIZE);
+	const Vec2 fbTexelSize = 1.0 / Vec2(FB_SIZE);
+
+	// Compute UVs
+	const Vec2 inUv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(IN_TEXTURE_SIZE);
+
+#if VARIANT == 0
+	const Vec2 fbOffset = Vec2(0.0, 0.0);
+#elif VARIANT == 1
+	const Vec2 fbOffset = Vec2(1.0, 0.0);
+#elif VARIANT == 1
+	const Vec2 fbOffset = Vec2(1.0, 1.0);
+#else
+	const Vec2 fbOffset = Vec2(0.0, 1.0);
+#endif
+	const Vec2 fbUv = (Vec2(gl_GlobalInvocationID.xy) * 2.0 + fbOffset + 0.5) / Vec2(FB_SIZE);
+
+	// Read the color and store it
+	const Vec3 centerColor = textureLod(u_inTex, u_linearAnyClampSampler, inUv, 0.0).rgb;
+	s_colors[gl_LocalInvocationID.y + 1][gl_LocalInvocationID.x + 1] = centerColor;
+
+	if(gl_LocalInvocationID.x == 0)
+	{
+		const Vec3 c = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, 0.0, IVec2(-1, 0)).rgb;
+		s_colors[gl_LocalInvocationID.y + 1][0] = c;
+	}
+	else if(gl_LocalInvocationID.x == WORKGROUP_SIZE.x - 1)
+	{
+		const Vec3 c = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, 0.0, IVec2(1, 0)).rgb;
+		s_colors[gl_LocalInvocationID.y + 1][WORKGROUP_SIZE.x + 1] = c;
+	}
+
+	if(gl_LocalInvocationID.y == 0)
+	{
+		const Vec3 c = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, 0.0, IVec2(-1, 0)).rgb;
+		s_colors[0][gl_LocalInvocationID.x + 1] = c;
+	}
+	else if(gl_LocalInvocationID.y == WORKGROUP_SIZE.y - 1)
+	{
+		const Vec3 c = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, 0.0, IVec2(-1, 0)).rgb;
+		s_colors[0][gl_LocalInvocationID.x + 1] = c;
+	}
+
+	// Read the texels in and around the current cell
+	const Vec3 centerColor = textureLod(u_inTex, u_linearAnyClampSampler, inUv, 0.0).rgb;
+
+	const Vec3 leftColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(-1, 0) 0.0).rgb;
+	const Vec3 rightColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(1, 0) 0.0).rgb;
+	const Vec3 topColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(0, 1) 0.0).rgb;
+	const Vec3 bottomColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(0, -1) 0.0).rgb;
+
+	const Vec3 leftTopColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(-1, 1) 0.0).rgb;
+	const Vec3 rightTopColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(1, 1) 0.0).rgb;
+	const Vec3 leftBottomColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(-1, -1) 0.0).rgb;
+	const Vec3 rightBottomColor = textureLodOffset(u_inTex, u_linearAnyClampSampler, inUv, IVec2(1, -1) 0.0).rgb;
+
+	// Also the depths around
+	const F32 leftDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(-2, 0)).r;
+	const F32 rightDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(2, 0)).r;
+	const F32 topDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(0, 2)).r;
+	const F32 bottomDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(0, -2)).r;
+
+	const F32 leftTopDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(-2, 2)).r;
+	const F32 rightTopDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(2, 2)).r;
+	const F32 leftBottomDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(-2, -2)).r;
+	const F32 rightBottomDepth = textureLodOffset(u_depthTex, u_linearAnyClampSampler, fbUv, 0.0, IVec2(2, -2)).r;
+
+	// Combine them
+	const Vec4 leftColorAndDepth = Vec4(leftColor, leftDepth);
+	const Vec4 rightColorAndDepth = Vec4(rightColor, rightDepth);
+	const Vec4 topColorAndDepth = Vec4(topColor, topDepth);
+	const Vec4 bottomColorAndDepth = Vec4(topColor, topDepth);
+
+	// Get the depth references of the current 2x2 cell
+	const Vec4 depthRefs = textureGather(sampler2D(u_depthTex, u_linearAnyClampSampler),
+		(Vec2(gl_GlobalInvocationID.xy) * 2.0 + 1.0) / Vec2(FB_SIZE),
+		0);
+	const F32 bottomLeftDref = depthRefs.w;
+	const F32 bottomRightDref = depthRefs.z;
+	const F32 topRightDref = depthRefs.y;
+	const F32 topLeftDref = depthRefs.x;
+
+	//     +---+
+	//     |3|2|
+	//     +---+  top
+	//     |0|1|
+	// +---+---+---+
+	// |3|2|3|2|3|2|
+	// +---+---+---+ left, center, right
+	// |0|1|0|1|0|1|
+	// +---+---+---+
+	//     |3|2|
+	//     +---+ bottom
+	//     |0|1|
+	//     +---+
+#if VARIANT == 0
+	imageStore(u_outImg, fbCoord, Vec4(centerColor, 0.0));
+	const Vec4 centerColorAndDepth = Vec4(centerColor, bottomLeftDref);
+
+	reconstruct(fbCoord + IVec2(1, 0), bottomRightDref, centerColorAndDepth, bottomColorAndDepth, rightColorAndDepth);
+	reconstruct(fbCoord + IVec2(1, 1), topRightDref, centerColorAndDepth, topColorAndDepth, rightColorAndDepth);
+	reconstruct(fbCoord + IVec2(0, 1), topLeftDref, centerColorAndDepth, topColorAndDepth, leftColorAndDepth);
+#elif VARIANT == 1
+	imageStore(u_outImg, fbCoord, Vec4(centerColor, 0.0));
+	const Vec4 centerColorAndDepth = Vec4(centerColor, bottomRightDref);
+
+	reconstruct(fbCoord + IVec2(-1, 0), bottomLeftDref, centerColorAndDepth, bottomColorAndDepth, leftColorAndDepth);
+	reconstruct(fbCoord + IVec2(0, 1), topRightDref, centerColorAndDepth, topColorAndDepth, rightColorAndDepth);
+	reconstruct(fbCoord + IVec2(-1, 1), topLeftDref, centerColorAndDepth, topColorAndDepth, leftColorAndDepth);
+#elif VARIANT == 2
+	imageStore(u_outImg, fbCoord, Vec4(centerColor, 0.0));
+	const Vec4 centerColorAndDepth = Vec4(centerColor, topRightDref);
+
+	reconstruct(fbCoord + IVec2(-1, -1), bottomLeftDref, centerColorAndDepth, bottomColorAndDepth, leftColorAndDepth);
+#endif
+}
+
+#pragma anki end