Browse Source

Renderer: Improve volumetric a bit

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
e0a6d0010f

+ 10 - 0
shaders/FsUpscale.frag.glsl

@@ -19,10 +19,20 @@ layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_ssaoTex;
 
 const float DEPTH_THRESHOLD = 1.0 / 4000.0;
 
+layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
+{
+	vec4 u_linearizeCfPad2;
+};
+
 void main()
 {
+#if 0
 	// Get the depth of the current fragment
 	vec3 color = nearestDepthUpscale(in_uv, u_depthFullTex, u_depthHalfTex, u_fsRt, DEPTH_THRESHOLD);
+#else
+	vec3 color =
+		bilateralUpsample(u_depthFullTex, u_depthHalfTex, u_fsRt, 1.0 / vec2(SRC_SIZE), in_uv, u_linearizeCfPad2.xy);
+#endif
 
 #if SSAO_ENABLED
 	float ssao = textureLod(u_ssaoTex, in_uv, 0.0).r;

+ 55 - 0
shaders/Functions.glsl

@@ -6,6 +6,8 @@
 #ifndef ANKI_SHADERS_FUNCTIONS_GLSL
 #define ANKI_SHADERS_FUNCTIONS_GLSL
 
+#include "shaders/Common.glsl"
+
 vec3 dither(in vec3 col, in float C)
 {
 	vec3 vDither = vec3(dot(vec2(171.0, 231.0), gl_FragCoord.xy));
@@ -119,4 +121,57 @@ vec3 nearestDepthUpscale(vec2 uv, sampler2D depthFull, sampler2D depthHalf, samp
 	return color;
 }
 
+float _calcDepthWeight(sampler2D depthLow, vec2 uv, float ref, vec2 linearDepthCf)
+{
+	float d = texture(depthLow, uv).r;
+	float linearD = linearizeDepthOptimal(d, linearDepthCf.x, linearDepthCf.y);
+	return 1.0 / (EPSILON + abs(ref - linearD));
+}
+
+vec3 _sampleAndWeight(sampler2D depthLow,
+	sampler2D colorLow,
+	vec2 lowInvSize,
+	vec2 uv,
+	vec2 offset,
+	float ref,
+	float weight,
+	vec2 linearDepthCf,
+	inout float normalize)
+{
+	uv += offset * lowInvSize;
+	float dw = _calcDepthWeight(depthLow, uv, ref, linearDepthCf);
+	vec3 v = texture(colorLow, uv).rgb;
+	normalize += weight * dw;
+	return v * dw * weight;
+}
+
+vec3 bilateralUpsample(
+	sampler2D depthHigh, sampler2D depthLow, sampler2D colorLow, vec2 lowInvSize, vec2 uv, vec2 linearDepthCf)
+{
+	const vec3 WEIGHTS = vec3(0.25, 0.125, 0.0625);
+	float depthRef = linearizeDepthOptimal(texture(depthHigh, uv).r, linearDepthCf.x, linearDepthCf.y);
+	float normalize = 0.0;
+
+	vec3 sum = _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(0.0, 0.0), depthRef, WEIGHTS.x, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(-1.0, 0.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(0.0, -1.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(1.0, 0.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(0.0, 1.0), depthRef, WEIGHTS.y, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(1.0, 1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(1.0, -1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(-1.0, 1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
+	sum += _sampleAndWeight(
+		depthLow, colorLow, lowInvSize, uv, vec2(-1.0, -1.0), depthRef, WEIGHTS.z, linearDepthCf, normalize);
+
+	return sum / normalize;
+}
+
 #endif

+ 10 - 0
shaders/VolumetricUpscale.frag.glsl

@@ -14,7 +14,17 @@ layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_colorTex;
 
 const float DEPTH_THRESHOLD = 1.0 / 5000.0;
 
+layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
+{
+	vec4 u_linearizeCfPad2;
+};
+
 void main()
 {
+#if 0
 	out_color = nearestDepthUpscale(in_uv, u_depthFullTex, u_depthHalfTex, u_colorTex, DEPTH_THRESHOLD);
+#else
+	out_color =
+		bilateralUpsample(u_depthFullTex, u_depthHalfTex, u_colorTex, 1.0 / SRC_SIZE, in_uv, u_linearizeCfPad2.xy);
+#endif
 }

+ 18 - 2
src/anki/renderer/Fs.cpp

@@ -94,7 +94,11 @@ Error Fs::init(const ConfigSet&)
 
 Error Fs::initVol()
 {
-	ANKI_CHECK(getResourceManager().loadResource("shaders/VolumetricUpscale.frag.glsl", m_vol.m_frag));
+	ANKI_CHECK(m_r->createShader("shaders/VolumetricUpscale.frag.glsl",
+		m_vol.m_frag,
+		"#define SRC_SIZE vec2(float(%u), float(%u))\n",
+		m_r->getWidth() / VOLUMETRIC_FRACTION,
+		m_r->getHeight() / VOLUMETRIC_FRACTION));
 
 	ColorStateInfo color;
 	color.m_attachmentCount = 1;
@@ -111,7 +115,10 @@ Error Fs::initVol()
 	rcinit.m_textures[0].m_texture = m_r->getDepthDownscale().m_hd.m_depthRt;
 	rcinit.m_textures[0].m_sampler = getGrManager().newInstance<Sampler>(sinit);
 	rcinit.m_textures[1].m_texture = m_r->getDepthDownscale().m_qd.m_depthRt;
+	rcinit.m_textures[1].m_sampler = rcinit.m_textures[0].m_sampler;
 	rcinit.m_textures[2].m_texture = m_r->getVolumetric().m_rt;
+	rcinit.m_uniformBuffers[0].m_uploadedMemory = true;
+	rcinit.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_FRAGMENT;
 	m_vol.m_rc = getGrManager().newInstance<ResourceGroup>(rcinit);
 
 	return ErrorCode::NONE;
@@ -119,8 +126,17 @@ Error Fs::initVol()
 
 void Fs::drawVolumetric(RenderingContext& ctx, CommandBufferPtr cmdb)
 {
+	const Frustum& fr = ctx.m_frustumComponent->getFrustum();
+
 	cmdb->bindPipeline(m_vol.m_ppline);
-	cmdb->bindResourceGroup(m_vol.m_rc, 0, nullptr);
+
+	TransientMemoryInfo trans;
+	Vec4* unis = static_cast<Vec4*>(getGrManager().allocateFrameTransientMemory(
+		sizeof(Vec4), BufferUsageBit::UNIFORM_ALL, trans.m_uniformBuffers[0]));
+	computeLinearizeDepthOptimal(fr.getNear(), fr.getFar(), unis->x(), unis->y());
+
+	cmdb->bindResourceGroup(m_vol.m_rc, 0, &trans);
+
 	m_r->drawQuad(cmdb);
 }
 

+ 4 - 2
src/anki/renderer/FsUpscale.cpp

@@ -37,12 +37,14 @@ Error FsUpscale::init(const ConfigSet& config)
 
 	rcInit.m_textures[3].m_texture = m_r->getSsao().getRt();
 
+	rcInit.m_uniformBuffers[0].m_uploadedMemory = true;
+	rcInit.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_FRAGMENT;
+
 	m_rcGroup = getGrManager().newInstance<ResourceGroup>(rcInit);
 
 	// Shader
 	StringAuto pps(getFrameAllocator());
-	pps.sprintf("#define TEXTURE_WIDTH %uu\n"
-				"#define TEXTURE_HEIGHT %uu\n"
+	pps.sprintf("#define SRC_SIZE uvec2(%uu, %uu)\n"
 				"#define SSAO_ENABLED %u\n",
 		m_r->getWidth() / FS_FRACTION,
 		m_r->getHeight() / FS_FRACTION,