Browse Source

Renderer: Remove some noise from SSAO & enable shadows in volumetric

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
d7dc76edc0

+ 0 - 0
engine_data/BlueNoiseLdrRgb.ankitex → engine_data/BlueNoiseLdrRgb64x64.ankitex


+ 2 - 2
shaders/Ssao.frag.glsl

@@ -30,7 +30,7 @@ layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform _blk
 
 layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_mMsDepthRt;
 layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_msRt;
-layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_noiseMap;
+layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2DArray u_noiseMap;
 
 // Get normal
 vec3 readNormal(in vec2 uv)
@@ -45,7 +45,7 @@ vec3 readRandom(in vec2 uv)
 {
 	const vec2 tmp = vec2(float(WIDTH) / float(NOISE_MAP_SIZE), float(HEIGHT) / float(NOISE_MAP_SIZE));
 
-	vec3 noise = texture(u_noiseMap, tmp * uv).xyz;
+	vec3 noise = texture(u_noiseMap, vec3(tmp * uv, 0.0)).xyz;
 	return noise;
 }
 

+ 12 - 6
shaders/Volumetric.frag.glsl

@@ -7,7 +7,7 @@
 #include "shaders/Functions.glsl"
 #include "shaders/Clusterer.glsl"
 
-#define LIGHT_TEX_BINDING 1
+#define LIGHT_TEX_BINDING 2
 #define LIGHT_UBO_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SET 0
@@ -16,16 +16,21 @@
 layout(location = 0) in vec2 in_uv;
 
 layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_msDepthRt;
+layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2DArray u_noiseTex;
 
 layout(std140, ANKI_UBO_BINDING(0, 3)) uniform ubo0_
 {
-	vec4 u_linearizePad2;
+	vec4 u_linearizeNoiseTexOffsetLayer;
 	vec4 u_fogColorFogFactor;
 };
 
+#define u_linearize u_linearizeNoiseTexOffsetLayer.xy
+#define u_noiseYOffset u_linearizeNoiseTexOffsetLayer.z
+#define u_noiseLayer u_linearizeNoiseTexOffsetLayer.w
+
 layout(location = 0) out vec4 out_color;
 
-#define ENABLE_SHADOWS 0
+#define ENABLE_SHADOWS 1
 const uint MAX_SAMPLES_PER_CLUSTER = 4u;
 
 // Return the diffuse color without taking into account the diffuse term of the particles.
@@ -98,7 +103,7 @@ vec3 computeLightColor(vec3 fragPos[MAX_SAMPLES_PER_CLUSTER], uint iterCount, ui
 
 vec3 fog(in float depth)
 {
-	float linearDepth = linearizeDepthOptimal(depth, u_linearizePad2.x, u_linearizePad2.y);
+	float linearDepth = linearizeDepthOptimal(depth, u_linearize.x, u_linearize.y);
 	float t = linearDepth * u_fogColorFogFactor.w;
 	return u_fogColorFogFactor.rgb * t;
 }
@@ -121,7 +126,8 @@ void main()
 	uint j = uint(in_uv.y * CLUSTER_COUNT.y);
 
 	const float DIST = 1.0 / float(MAX_SAMPLES_PER_CLUSTER);
-	float randFactor = rand(ndc + u_lightingUniforms.rendererSizeTimePad1.z);
+	vec3 noiseTexUv = vec3(vec2(FB_SIZE) / vec2(NOISE_MAP_SIZE) * in_uv + vec2(0.0, u_noiseYOffset), u_noiseLayer);
+	float randFactor = texture(u_noiseTex, noiseTexUv).r;
 	float start = DIST * randFactor;
 	float factors[MAX_SAMPLES_PER_CLUSTER] = float[](start, DIST + start, 2.0 * DIST + start, 3.0 * DIST + start);
 
@@ -157,5 +163,5 @@ void main()
 	}
 
 	newCol = newCol * fog(depth) / max(1.0, float(count));
-	out_color = vec4(newCol, 0.666);
+	out_color = vec4(newCol, 1.0 / 3.0);
 }

+ 1 - 1
src/anki/renderer/Pps.cpp

@@ -55,7 +55,7 @@ Error Pps::initInternal(const ConfigSet& config)
 		m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
 	}
 
-	ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb.ankitex", m_blueNoise));
+	ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb64x64.ankitex", m_blueNoise));
 
 	return ErrorCode::NONE;
 }

+ 6 - 58
src/anki/renderer/Ssao.cpp

@@ -15,9 +15,9 @@
 namespace anki
 {
 
-const U NOISE_TEX_SIZE = 8;
-const U KERNEL_SIZE = 8;
 const F32 HEMISPHERE_RADIUS = 1.1; // In game units
+const U KERNEL_SIZE = 8;
+const PixelFormat Ssao::RT_PIXEL_FORMAT(ComponentFormat::R8, TransformFormat::UNORM);
 
 template<typename TVec>
 static void genHemisphere(TVec* ANKI_RESTRICT arr, TVec* ANKI_RESTRICT arrEnd)
@@ -33,29 +33,10 @@ static void genHemisphere(TVec* ANKI_RESTRICT arr, TVec* ANKI_RESTRICT arrEnd)
 		arr->normalize();
 
 		// Adjust the length
-		(*arr) *= randRange(0.0, 1.0);
-	} while(++arr != arrEnd);
-}
-
-static void genNoise(Array<I8, 4>* ANKI_RESTRICT arr, Array<I8, 4>* ANKI_RESTRICT arrEnd)
-{
-	ANKI_ASSERT(arr && arrEnd && arr != arrEnd);
-
-	do
-	{
-		// Calculate the normal
-		Vec3 v(randRange(-1.0f, 1.0f), randRange(-1.0f, 1.0f), 0.0f);
-		v.normalize();
-
-		(*arr)[0] = v[0] * MAX_I8;
-		(*arr)[1] = v[1] * MAX_I8;
-		(*arr)[2] = v[2] * MAX_I8;
-		(*arr)[3] = 0;
+		(*arr) *= randRange(HEMISPHERE_RADIUS / 2.0f, HEMISPHERE_RADIUS);
 	} while(++arr != arrEnd);
 }
 
-const PixelFormat Ssao::RT_PIXEL_FORMAT(ComponentFormat::R8, TransformFormat::UNORM);
-
 Error Ssao::createFb(FramebufferPtr& fb, TexturePtr& rt)
 {
 	// Set to bilinear because the blurring techniques take advantage of that
@@ -79,8 +60,6 @@ Error Ssao::createFb(FramebufferPtr& fb, TexturePtr& rt)
 
 Error Ssao::initInternal(const ConfigSet& config)
 {
-	GrManager& gr = getGrManager();
-
 	m_blurringIterationsCount = config.getNumber("ssao.blurringIterationsCount");
 
 	//
@@ -100,38 +79,7 @@ Error Ssao::initInternal(const ConfigSet& config)
 	//
 	// noise texture
 	//
-	TextureInitInfo tinit;
-
-	tinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::UPLOAD;
-	tinit.m_width = tinit.m_height = NOISE_TEX_SIZE;
-	tinit.m_depth = 1;
-	tinit.m_layerCount = 1;
-	tinit.m_type = TextureType::_2D;
-	tinit.m_format = PixelFormat(ComponentFormat::R8G8B8A8, TransformFormat::SNORM);
-	tinit.m_mipmapsCount = 1;
-	tinit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
-	tinit.m_sampling.m_repeat = true;
-
-	m_noiseTex = gr.newInstance<Texture>(tinit);
-
-	StagingGpuMemoryToken token;
-	const U noiseSize = NOISE_TEX_SIZE * NOISE_TEX_SIZE * sizeof(Array<I8, 4>);
-	Array<I8, 4>* noise = static_cast<Array<I8, 4>*>(
-		m_r->getStagingGpuMemoryManager().allocateFrame(noiseSize, StagingGpuMemoryType::TRANSFER, token));
-
-	genNoise(&noise[0], &noise[0] + noiseSize);
-
-	CommandBufferInitInfo cmdbInit;
-	cmdbInit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::TRANSFER_WORK;
-	CommandBufferPtr cmdb = gr.newInstance<CommandBuffer>(cmdbInit);
-
-	TextureSurfaceInfo surf(0, 0, 0, 0);
-
-	cmdb->setTextureSurfaceBarrier(m_noiseTex, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, surf);
-	cmdb->copyBufferToTextureSurface(token.m_buffer, token.m_offset, token.m_range, m_noiseTex, surf);
-	cmdb->setTextureSurfaceBarrier(m_noiseTex, TextureUsageBit::UPLOAD, TextureUsageBit::SAMPLED_FRAGMENT, surf);
-
-	cmdb->flush();
+	ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb64x64.ankitex", m_noiseTex));
 
 	//
 	// Kernel
@@ -164,7 +112,7 @@ Error Ssao::initInternal(const ConfigSet& config)
 		"#define KERNEL_SIZE %u\n"
 		"#define KERNEL_ARRAY %s\n"
 		"#define RADIUS float(%f)\n",
-		NOISE_TEX_SIZE,
+		m_noiseTex->getWidth(),
 		m_width,
 		m_height,
 		KERNEL_SIZE,
@@ -242,7 +190,7 @@ void Ssao::run(RenderingContext& ctx)
 
 	cmdb->bindTexture(0, 0, m_r->getDepthDownscale().m_qd.m_depthRt);
 	cmdb->bindTexture(0, 1, m_r->getMs().m_rt2);
-	cmdb->bindTexture(0, 2, m_noiseTex);
+	cmdb->bindTexture(0, 2, m_noiseTex->getGrTexture());
 
 	Vec4* unis = allocateAndBindUniforms<Vec4*>(sizeof(Vec4) * 2, cmdb, 0, 0);
 	const FrustumComponent& frc = *ctx.m_frustumComponent;

+ 1 - 1
src/anki/renderer/Ssao.h

@@ -55,7 +55,7 @@ private:
 	ShaderProgramPtr m_hblurProg;
 	ShaderProgramPtr m_vblurProg;
 
-	TexturePtr m_noiseTex;
+	TextureResourcePtr m_noiseTex;
 
 	ANKI_USE_RESULT Error createFb(FramebufferPtr& fb, TexturePtr& rt);
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);

+ 16 - 5
src/anki/renderer/Volumetric.cpp

@@ -36,6 +36,9 @@ Error Volumetric::initInternal(const ConfigSet& config)
 	U width = m_r->getWidth() / VOLUMETRIC_FRACTION;
 	U height = m_r->getHeight() / VOLUMETRIC_FRACTION;
 
+	// Misc
+	ANKI_CHECK(getResourceManager().loadResource("engine_data/BlueNoiseLdrRgb64x64.ankitex", m_noiseTex));
+
 	// Create RTs
 	m_r->createRenderTarget(width,
 		height,
@@ -50,13 +53,15 @@ Error Volumetric::initInternal(const ConfigSet& config)
 	// Create shaders
 	ANKI_CHECK(m_r->createShaderf("shaders/Volumetric.frag.glsl",
 		m_frag,
-		"#define RPASS_SIZE uvec2(%uu, %uu)\n"
-		"#define CLUSTER_COUNT uvec3(%uu, %uu, %uu)\n",
+		"#define FB_SIZE uvec2(%uu, %uu)\n"
+		"#define CLUSTER_COUNT uvec3(%uu, %uu, %uu)\n"
+		"#define NOISE_MAP_SIZE %u\n",
 		width,
 		height,
 		m_r->getIs().getLightBin().getClusterer().getClusterCountX(),
 		m_r->getIs().getLightBin().getClusterer().getClusterCountY(),
-		m_r->getIs().getLightBin().getClusterer().getClusterCountZ()));
+		m_r->getIs().getLightBin().getClusterer().getClusterCountZ(),
+		m_noiseTex->getWidth()));
 
 	// Create prog
 	m_r->createDrawQuadShaderProgram(m_frag->getGrShader(), m_prog);
@@ -97,8 +102,9 @@ void Volumetric::run(RenderingContext& ctx)
 	cmdb->setBlendFactors(0, BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA);
 
 	cmdb->bindTexture(0, 0, m_r->getDepthDownscale().m_qd.m_depthRt);
-	cmdb->bindTexture(0, 1, m_r->getSm().m_spotTexArray);
-	cmdb->bindTexture(0, 2, m_r->getSm().m_omniTexArray);
+	cmdb->bindTexture(0, 1, m_noiseTex->getGrTexture());
+	cmdb->bindTexture(0, 2, m_r->getSm().m_spotTexArray);
+	cmdb->bindTexture(0, 3, m_r->getSm().m_omniTexArray);
 
 	bindUniforms(cmdb, 0, 0, ctx.m_is.m_commonToken);
 	bindUniforms(cmdb, 0, 1, ctx.m_is.m_pointLightsToken);
@@ -106,6 +112,11 @@ void Volumetric::run(RenderingContext& ctx)
 
 	Vec4* uniforms = allocateAndBindUniforms<Vec4*>(sizeof(Vec4) * 2, cmdb, 0, 3);
 	computeLinearizeDepthOptimal(frc.getNear(), frc.getFar(), uniforms[0].x(), uniforms[0].y());
+
+	F32 texelOffset = (1.0 / m_noiseTex->getWidth()) * 1.0;
+	uniforms[0].z() = m_r->getFrameCount() * texelOffset;
+	uniforms[0].w() = m_r->getFrameCount() & (m_noiseTex->getLayerCount() - 1);
+
 	uniforms[1] = Vec4(m_fogColor, m_fogFactor);
 
 	bindStorage(cmdb, 0, 0, ctx.m_is.m_clustersToken);

+ 2 - 0
src/anki/renderer/Volumetric.h

@@ -47,6 +47,8 @@ private:
 	Vec3 m_fogColor = Vec3(1.0);
 	F32 m_fogFactor = 1.0;
 
+	TextureResourcePtr m_noiseTex;
+
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& config);
 };
 /// @}

+ 4 - 0
tools/texture/convert_image.py

@@ -338,6 +338,10 @@ def create_mipmaps(in_file, tmp_dir, width_, height_, color_format, to_linear_rg
 			args.append("-colorspace")
 			args.append("RGB")
 
+		# Add this because it will automatically convert gray-like images to grayscale TGAs
+		args.append("-type")
+		args.append("TrueColor")
+
 		# resize
 		args.append("-resize")
 		args.append(size_str)