Browse Source

Add blue noise in RT shadows

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
88677600ec

+ 5 - 4
AnKi/Renderer/FinalComposite.cpp

@@ -41,7 +41,7 @@ Error FinalComposite::initInternal(const ConfigSet& config)
 	m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
 	m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
 	m_fbDescr.bake();
 	m_fbDescr.bake();
 
 
-	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoiseLdrRgb64x64.ankitex", m_blueNoise));
+	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoiseRgb864x64.png", m_blueNoise));
 
 
 	// Progs
 	// Progs
 	ANKI_CHECK(getResourceManager().loadResource("Shaders/FinalComposite.ankiprog", m_prog));
 	ANKI_CHECK(getResourceManager().loadResource("Shaders/FinalComposite.ankiprog", m_prog));
@@ -139,12 +139,13 @@ void FinalComposite::run(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 			rgraphCtx.bindColorTexture(0, 10, m_r->getDbg().getRt());
 			rgraphCtx.bindColorTexture(0, 10, m_r->getDbg().getRt());
 		}
 		}
 
 
-		struct PushConsts
+		class PushConsts
 		{
 		{
-			Vec4 m_blueNoiseLayerPad3;
+		public:
+			UVec4 m_frameCountPad3;
 			Mat4 m_prevViewProjMatMulInvViewProjMat;
 			Mat4 m_prevViewProjMatMulInvViewProjMat;
 		} pconsts;
 		} pconsts;
-		pconsts.m_blueNoiseLayerPad3.x() = F32(m_r->getFrameCount() % m_blueNoise->getLayerCount());
+		pconsts.m_frameCountPad3.x() = m_r->getFrameCount() & MAX_U32;
 		pconsts.m_prevViewProjMatMulInvViewProjMat = ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection
 		pconsts.m_prevViewProjMatMulInvViewProjMat = ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection
 													 * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 													 * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 		cmdb->setPushConstants(&pconsts, sizeof(pconsts));
 		cmdb->setPushConstants(&pconsts, sizeof(pconsts));

+ 3 - 0
AnKi/Renderer/RtShadows.cpp

@@ -38,6 +38,8 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	m_useSvgf = cfg.getNumberU8("r_rtShadowsSvgf") != 0;
 	m_useSvgf = cfg.getNumberU8("r_rtShadowsSvgf") != 0;
 	m_atrousPassCount = cfg.getNumberU8("r_rtShadowsSvgfAtrousPassCount");
 	m_atrousPassCount = cfg.getNumberU8("r_rtShadowsSvgfAtrousPassCount");
 
 
+	ANKI_CHECK(getResourceManager().loadResource("EngineAssets/BlueNoiseRgb864x64.png", m_blueNoiseTex));
+
 	// Ray gen program
 	// Ray gen program
 	{
 	{
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsRayGen.ankiprog", m_rayGenProg));
 		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsRayGen.ankiprog", m_rayGenProg));
@@ -500,6 +502,7 @@ void RtShadows::run(RenderPassWorkContext& rgraphCtx)
 	rgraphCtx.bindImage(0, 17, m_runCtx.m_currentHistoryLengthRt);
 	rgraphCtx.bindImage(0, 17, m_runCtx.m_currentHistoryLengthRt);
 	rgraphCtx.bindColorTexture(0, 18, m_runCtx.m_prevMomentsRt);
 	rgraphCtx.bindColorTexture(0, 18, m_runCtx.m_prevMomentsRt);
 	rgraphCtx.bindImage(0, 19, m_runCtx.m_currentMomentsRt);
 	rgraphCtx.bindImage(0, 19, m_runCtx.m_currentMomentsRt);
+	cmdb->bindTexture(0, 20, m_blueNoiseTex->getGrTextureView(), TextureUsageBit::SAMPLED_TRACE_RAYS);
 
 
 	cmdb->bindAllBindless(1);
 	cmdb->bindAllBindless(1);
 
 

+ 2 - 0
AnKi/Renderer/RtShadows.h

@@ -89,6 +89,8 @@ public:
 	ShaderProgramResourcePtr m_visualizeRenderTargetsProg;
 	ShaderProgramResourcePtr m_visualizeRenderTargetsProg;
 	/// @}
 	/// @}
 
 
+	TextureResourcePtr m_blueNoiseTex;
+
 	Array<ShadowLayer, MAX_RT_SHADOW_LAYERS> m_shadowLayers;
 	Array<ShadowLayer, MAX_RT_SHADOW_LAYERS> m_shadowLayers;
 
 
 	U32 m_sbtRecordSize = 256;
 	U32 m_sbtRecordSize = 256;

+ 4 - 3
AnKi/Shaders/FinalComposite.ankiprog

@@ -32,7 +32,7 @@ layout(set = 0, binding = 3) uniform sampler u_trilinearRepeatSampler;
 layout(set = 0, binding = 4) uniform texture2D u_lightShadingRt;
 layout(set = 0, binding = 4) uniform texture2D u_lightShadingRt;
 layout(set = 0, binding = 5) uniform texture2D u_ppsBloomLfRt;
 layout(set = 0, binding = 5) uniform texture2D u_ppsBloomLfRt;
 layout(set = 0, binding = 6) uniform texture3D u_lut;
 layout(set = 0, binding = 6) uniform texture3D u_lut;
-layout(set = 0, binding = 7) uniform texture2DArray u_blueNoise;
+layout(set = 0, binding = 7) uniform texture2D u_blueNoise;
 layout(set = 0, binding = 8) uniform texture2D u_motionVectorsRt;
 layout(set = 0, binding = 8) uniform texture2D u_motionVectorsRt;
 layout(set = 0, binding = 9) uniform texture2D u_depthRt;
 layout(set = 0, binding = 9) uniform texture2D u_depthRt;
 #if DBG_ENABLED
 #if DBG_ENABLED
@@ -41,7 +41,7 @@ layout(set = 0, binding = 10) uniform texture2D u_dbgOutlineRt;
 
 
 layout(push_constant, row_major, std430) uniform pc_
 layout(push_constant, row_major, std430) uniform pc_
 {
 {
-	Vec4 u_blueNoiseLayerPad3;
+	UVec4 u_frameCountPad3;
 	Mat4 u_prevViewProjMatMulInvViewProjMat;
 	Mat4 u_prevViewProjMatMulInvViewProjMat;
 };
 };
 
 
@@ -82,8 +82,9 @@ void main()
 	out_color = colorGrading(out_color);
 	out_color = colorGrading(out_color);
 
 
 #if BLUE_NOISE
 #if BLUE_NOISE
-	const Vec3 bnUvw = Vec3(Vec2(FB_SIZE) / Vec2(64.0) * uv, u_blueNoiseLayerPad3.x);
+	const Vec2 bnUvw = Vec2(FB_SIZE) / Vec2(64.0) * uv;
 	Vec3 blueNoise = textureLod(u_blueNoise, u_trilinearRepeatSampler, bnUvw, 0.0).rgb;
 	Vec3 blueNoise = textureLod(u_blueNoise, u_trilinearRepeatSampler, bnUvw, 0.0).rgb;
+	blueNoise = animateBlueNoise(blueNoise, u_frameCountPad3.x);
 	blueNoise = blueNoise * 2.0 - 1.0;
 	blueNoise = blueNoise * 2.0 - 1.0;
 	blueNoise = sign(blueNoise) * (1.0 - sqrt(1.0 - abs(blueNoise)));
 	blueNoise = sign(blueNoise) * (1.0 - sqrt(1.0 - abs(blueNoise)));
 
 

+ 7 - 0
AnKi/Shaders/Functions.glsl

@@ -576,3 +576,10 @@ Vec4 bilinearFiltering(texture2D tex, sampler nearestSampler, Vec2 uv, F32 lod,
 	const Vec4 s4 = textureLod(tex, nearestSampler, uv + texelSize, lod);
 	const Vec4 s4 = textureLod(tex, nearestSampler, uv + texelSize, lod);
 	return mix(mix(s1, s2, f.x), mix(s3, s4, f.x), f.y);
 	return mix(mix(s1, s2, f.x), mix(s3, s4, f.x), f.y);
 }
 }
+
+// https://www.shadertoy.com/view/WsfBDf
+Vec3 animateBlueNoise(Vec3 inputBlueNoise, U32 frameIdx)
+{
+	const F32 goldenRatioConjugate = 0.61803398875;
+	return fract(inputBlueNoise + F32(frameIdx % 64u) * goldenRatioConjugate);
+}

+ 8 - 0
AnKi/Shaders/RtShadowsRayGen.ankiprog

@@ -32,6 +32,7 @@ layout(set = 0, binding = 16) uniform texture2D u_prevHistoryLengthTex;
 layout(set = 0, binding = 17) uniform image2D u_historyLengthImage;
 layout(set = 0, binding = 17) uniform image2D u_historyLengthImage;
 layout(set = 0, binding = 18) uniform texture2D u_prevMomentsTex;
 layout(set = 0, binding = 18) uniform texture2D u_prevMomentsTex;
 layout(set = 0, binding = 19) uniform image2D u_momentsImage;
 layout(set = 0, binding = 19) uniform image2D u_momentsImage;
+layout(set = 0, binding = 20) uniform texture2D u_blueNoiseTex;
 
 
 ANKI_BINDLESS_SET(1); // Used by the hit shaders
 ANKI_BINDLESS_SET(1); // Used by the hit shaders
 
 
@@ -91,8 +92,15 @@ void main()
 	zeroRtShadowLayers(shadowFactors);
 	zeroRtShadowLayers(shadowFactors);
 
 
 	// Get a random factor
 	// Get a random factor
+#if 0
 	const UVec3 random = rand3DPCG16(UVec3(gl_LaunchIDEXT.xy, u_lightingUniforms.m_frameCount));
 	const UVec3 random = rand3DPCG16(UVec3(gl_LaunchIDEXT.xy, u_lightingUniforms.m_frameCount));
 	const Vec3 randomf = Vec3(random) / F32(0xFFFF) * 2.0 - 1.0; // In [-1.0, 1.0]
 	const Vec3 randomf = Vec3(random) / F32(0xFFFF) * 2.0 - 1.0; // In [-1.0, 1.0]
+#else
+	Vec3 randomf =
+		textureLod(u_blueNoiseTex, u_trilinearRepeatSampler, Vec2(gl_LaunchSizeEXT.xy) / Vec2(64.0) * uv, 0.0).rgb;
+	randomf = animateBlueNoise(randomf, u_lightingUniforms.m_frameCount);
+	randomf = randomf * 2.0 - 1.0;
+#endif
 
 
 	// Dir light
 	// Dir light
 	ANKI_BRANCH if(u_dirLight.m_active != 0u && u_dirLight.m_cascadeCount > 0)
 	ANKI_BRANCH if(u_dirLight.m_active != 0u && u_dirLight.m_cascadeCount > 0)

BIN
EngineAssets/BlueNoiseRgb864x64.png


+ 22 - 20
Tools/Texture/ConvertImage.ph → Tools/Texture/ConvertImage.py

@@ -16,11 +16,11 @@ import shutil
 from PIL import Image
 from PIL import Image
 from ctypes import Structure, sizeof, c_int, c_char, c_byte, c_uint
 from ctypes import Structure, sizeof, c_int, c_char, c_byte, c_uint
 from io import BytesIO
 from io import BytesIO
+import sys
 
 
 
 
 class CStruct(Structure):
 class CStruct(Structure):
     """ C structure """
     """ C structure """
-
     def to_bytearray(self):
     def to_bytearray(self):
         s = BytesIO()
         s = BytesIO()
         s.write(self)
         s.write(self)
@@ -194,27 +194,28 @@ def parse_commandline():
       "need to define the executable explicitly",
       "need to define the executable explicitly",
       formatter_class = argparse.ArgumentDefaultsHelpFormatter)
       formatter_class = argparse.ArgumentDefaultsHelpFormatter)
 
 
-    parser.add_argument(
-        "-i", "--input", nargs="+", required=True, help="specify the image(s) to convert. Seperate with space")
+    parser.add_argument("-i",
+                        "--input",
+                        nargs="+",
+                        required=True,
+                        help="specify the image(s) to convert. Seperate with space")
 
 
     parser.add_argument("-o", "--output", required=True, help="specify output AnKi image.")
     parser.add_argument("-o", "--output", required=True, help="specify output AnKi image.")
 
 
-    parser.add_argument(
-        "-t",
-        "--type",
-        default="2D",
-        choices=["2D", "3D", "2DArray"],
-        help="type of the image (2D or cube or 3D or 2DArray)")
+    parser.add_argument("-t",
+                        "--type",
+                        default="2D",
+                        choices=["2D", "3D", "2DArray"],
+                        help="type of the image (2D or cube or 3D or 2DArray)")
 
 
     parser.add_argument("-f", "--fast", type=int, default=0, help="run the fast version of the converters")
     parser.add_argument("-f", "--fast", type=int, default=0, help="run the fast version of the converters")
 
 
     parser.add_argument("-n", "--normal", type=int, default=0, help="assume the texture is normal")
     parser.add_argument("-n", "--normal", type=int, default=0, help="assume the texture is normal")
 
 
-    parser.add_argument(
-        "-c",
-        "--convert-path",
-        default="/usr/bin/convert",
-        help="the executable where convert tool is located. Stupid etcpack cannot get it from PATH")
+    parser.add_argument("-c",
+                        "--convert-path",
+                        default="/usr/bin/convert",
+                        help="the executable where convert tool is located. Stupid etcpack cannot get it from PATH")
 
 
     parser.add_argument("--no-alpha", type=int, default=0, help="remove alpha channel")
     parser.add_argument("--no-alpha", type=int, default=0, help="remove alpha channel")
 
 
@@ -230,11 +231,10 @@ def parse_commandline():
         default=0,
         default=0,
         help="assume the input textures are sRGB. If this option is true then convert them to linear RGB")
         help="assume the input textures are sRGB. If this option is true then convert them to linear RGB")
 
 
-    parser.add_argument(
-        "--filter",
-        default="default",
-        choices=["default", "linear", "nearest"],
-        help="texture filtering. Can be: default, linear, nearest")
+    parser.add_argument("--filter",
+                        default="default",
+                        choices=["default", "linear", "nearest"],
+                        help="texture filtering. Can be: default, linear, nearest")
 
 
     parser.add_argument("--mip-count", type=int, default=0xFFFF, help="Max number of mipmaps")
     parser.add_argument("--mip-count", type=int, default=0xFFFF, help="Max number of mipmaps")
 
 
@@ -426,7 +426,9 @@ def create_dds_images(mips_fnames, tmp_dir, fast, color_format, normal):
         args.append(out_fname)
         args.append(out_fname)
 
 
         printi("  " + " ".join(args))
         printi("  " + " ".join(args))
-        subprocess.check_call(args, stdout=subprocess.PIPE)
+        my_env = os.environ.copy()
+        my_env["PATH"] = sys.path[0] + "/../../ThirdParty/Bin/compressonator/:" + my_env["PATH"]
+        subprocess.check_call(args, stdout=subprocess.PIPE, env=my_env)
 
 
 
 
 def write_raw(tex_file, fname, width, height, color_format):
 def write_raw(tex_file, fname, width, height, color_format):