Răsfoiți Sursa

[FEATURE] Some work on SSLR

Panagiotis Christopoulos Charitos 8 ani în urmă
părinte
comite
0fb514b129

+ 24 - 12
programs/Reflections.ankiprog

@@ -20,24 +20,30 @@ http://www.anki3d.org/LICENSE
 
 layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
 
-layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_gbufferRt1;
-layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_gbufferRt2;
-layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_depthRt;
-layout(ANKI_TEX_BINDING(0, 4)) uniform sampler2D u_lightBufferRt;
+layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_gbufferRt1;
+layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_gbufferRt2;
+layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_depthRt;
+layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_lightBufferRt;
 
 layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D u_out;
 
 layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform u0_
 {
-	mat4 u_prevViewProjMatMulInvViewProjMat;
+	mat4 u_viewProjMat;
+	mat4 u_invViewProjMat;
+	vec4 u_camPosPad1;
+	vec4 u_nearPlane;
 };
 
+#define u_camPos u_camPosPad1.xyz
+
 // http://paulbourke.net/geometry/pointlineplane/
 // Line segment A is p1, p2. Line segment B is p3, p4
 vec3 lineSegmentsIntersection(vec3 p1, vec3 p2, vec3 p3, vec3 p4)
 {
 	vec3 p13 = p1 - p3;
 	vec3 p43 = p4 - p3;
+	vec3 p21 = p2 - p1;
 
 	float d1343 = dot(p13, p43);
 	float d4321 = dot(p43, p21);
@@ -66,12 +72,12 @@ vec3 doSslr(vec3 r, vec3 worldPos, vec2 uv, out float contribution)
 
 	// Compute an end point p1 that is p1 = p0 + t*r. p1 will lie in the near plane.
 	// The code is the same used to compute the intersection of a ray to a plane.
-	// NOTE: The nearPlane is a bit in front of the real near plane. We do that to be able to project p1 without 
+	// NOTE: The u_nearPlane is a bit in front of the real near plane. We do that to be able to project p1 without 
 	//       problems
 	vec3 p1;
 	{
-		float d = dot(nearPlane.xyz, p0) - nearPlane.w;
-		float a = dot(nearPlane.xyz, r);
+		float d = dot(u_nearPlane.xyz, p0) - u_nearPlane.w;
+		float a = dot(u_nearPlane.xyz, r);
 
 		float s;
 		if(d > 0.0 && a < 0.0)
@@ -147,6 +153,12 @@ vec3 doSslr(vec3 r, vec3 worldPos, vec2 uv, out float contribution)
 
 void main()
 {
+	if(gl_GlobalInvocationID.x >= FB_SIZE.x || gl_GlobalInvocationID.y >= FB_SIZE.y)
+	{
+		// Skip threads outside the writable image
+		return;
+	}
+
 	vec2 uv = vec2(gl_GlobalInvocationID.xy) / vec2(FB_SIZE);
 
 	// Get normal
@@ -159,15 +171,15 @@ void main()
 	vec3 worldPos = worldPos4.xyz / worldPos4.w;
 
 	// Compute reflection vec
-	vec4 viewDir = normalize(worldPos - u_camPos);
-	vec3 refl = reflect(viewDir, normal);
+	vec3 viewDir = normalize(worldPos - u_camPos);
+	vec3 reflVec = reflect(viewDir, normal);
 
 	// Do SSLR
 	float sslrFactor;
-	vec3 sslrCol = doSslr(r, worldPos, uv, sslrFactor);
+	vec3 sslrCol = doSslr(reflVec, worldPos, uv, sslrFactor);
 
 	// Write it
-	imageStore(u_out, gl_GlobalInvocationID.xy, vec4(sslrCol, 0.0));
+	imageStore(u_out, ivec2(gl_GlobalInvocationID.xy), vec4(sslrCol, 0.0));
 }
 			]]></source>
 		</shader>

+ 1 - 0
src/anki/renderer/Common.h

@@ -34,6 +34,7 @@ class DownscaleBlur;
 class Volumetric;
 class DepthDownscale;
 class TemporalAA;
+class Reflections;
 
 class RenderingContext;
 class DebugDrawer;

+ 6 - 3
src/anki/renderer/DownscaleBlur.cpp

@@ -60,14 +60,17 @@ Error DownscaleBlur::initInternal(const ConfigSet&)
 	return Error::NONE;
 }
 
+void DownscaleBlur::importRenderTargets(RenderingContext& ctx)
+{
+	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
+	m_runCtx.m_rt = rgraph.importRenderTarget("Down/Blur", m_rtTex, TextureUsageBit::NONE);
+}
+
 void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 	m_runCtx.m_crntPassIdx = 0;
 
-	// Create RT
-	m_runCtx.m_rt = rgraph.importRenderTarget("Down/Blur", m_rtTex, TextureUsageBit::NONE);
-
 	// Create passes
 	static const Array<CString, 8> passNames = {{"DownBlur #0",
 		"Down/Blur #1",

+ 3 - 0
src/anki/renderer/DownscaleBlur.h

@@ -26,6 +26,9 @@ anki_internal:
 
 	ANKI_USE_RESULT Error init(const ConfigSet& cfg);
 
+	/// Import render targets
+	void importRenderTargets(RenderingContext& ctx);
+
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);
 

+ 38 - 9
src/anki/renderer/Reflections.cpp

@@ -8,6 +8,8 @@
 #include <anki/renderer/GBuffer.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/DownscaleBlur.h>
+#include <anki/renderer/RenderQueue.h>
+#include <anki/collision/Functions.h>
 
 namespace anki
 {
@@ -28,23 +30,27 @@ Error Reflections::init(const ConfigSet& cfg)
 
 Error Reflections::initInternal(const ConfigSet& cfg)
 {
-	U32 width = m_r->getWidth() / 2;
-	U32 height = m_r->getHeight() / 2;
+	U32 width = m_r->getWidth();
+	U32 height = m_r->getHeight();
 	ANKI_R_LOGI("Initializing reflection pass (%ux%u)", width, height);
 
 	// Create RT descr
 	m_rtDescr = m_r->create2DRenderTargetDescription(width,
 		height,
 		LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::IMAGE_COMPUTE_WRITE,
+		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::IMAGE_COMPUTE_WRITE
+			| TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
 		"Refl");
 	m_rtDescr.bake();
 
 	// Create shader
 	ANKI_CHECK(getResourceManager().loadResource("programs/Reflections.ankiprog", m_prog));
 
-	ShaderProgramResourceConstantValueInitList<1> consts(m_prog);
-	consts.add("OUT_TEX_SIZE", UVec2(width, height));
+	ShaderProgramResourceConstantValueInitList<4> consts(m_prog);
+	consts.add("FB_SIZE", UVec2(width, height));
+	consts.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
+	consts.add("MAX_STEPS", U32(256));
+	consts.add("LIGHT_BUFFER_MIP_COUNT", U32(m_r->getDownscaleBlur().getMipmapCount()));
 
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(consts.get(), variant);
@@ -56,6 +62,7 @@ Error Reflections::initInternal(const ConfigSet& cfg)
 void Reflections::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
+	m_runCtx.m_ctx = &ctx;
 
 	// Create RT
 	m_runCtx.m_rt = rgraph.newRenderTarget(m_rtDescr);
@@ -76,16 +83,38 @@ void Reflections::run(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
-	rgraphCtx.bindColorTextureAndSampler(0, 0, m_r->getGBuffer().getColorRt(2), m_r->getLinearSampler());
-	rgraphCtx.bindColorTextureAndSampler(0, 1, m_r->getDepthDownscale().getHalfDepthColorRt(), m_r->getLinearSampler());
-	rgraphCtx.bindColorTextureAndSampler(0, 2, m_r->getDownscaleBlur().getRt(), m_r->getLinearSampler());
+	struct Unis
+	{
+		Mat4 m_viewProjMat;
+		Mat4 m_invViewProjMat;
+		Vec4 m_camPosPad1;
+		Vec4 m_nearPlane;
+	};
+
+	Unis* unis = allocateAndBindUniforms<Unis*>(sizeof(Unis), cmdb, 0, 0);
+	unis->m_viewProjMat = m_runCtx.m_ctx->m_renderQueue->m_viewProjectionMatrix;
+	unis->m_invViewProjMat = m_runCtx.m_ctx->m_renderQueue->m_viewProjectionMatrix.getInverse();
+	unis->m_camPosPad1 = m_runCtx.m_ctx->m_renderQueue->m_cameraTransform.getTranslationPart();
+
+	Plane nearPlane;
+	Array<Plane*, U(FrustumPlaneType::COUNT)> planes = {};
+	planes[FrustumPlaneType::NEAR] = &nearPlane;
+	extractClipPlanes(m_runCtx.m_ctx->m_renderQueue->m_viewProjectionMatrix, planes);
+	unis->m_nearPlane = Vec4(nearPlane.getNormal().xyz(), nearPlane.getOffset() + 0.1f);
+
+	rgraphCtx.bindColorTextureAndSampler(0, 0, m_r->getGBuffer().getColorRt(1), m_r->getLinearSampler());
+	rgraphCtx.bindColorTextureAndSampler(0, 1, m_r->getGBuffer().getColorRt(2), m_r->getLinearSampler());
+	rgraphCtx.bindColorTextureAndSampler(0, 2, m_r->getDepthDownscale().getHalfDepthColorRt(), m_r->getLinearSampler());
+	rgraphCtx.bindColorTextureAndSampler(0, 3, m_r->getDownscaleBlur().getRt(), m_r->getTrilinearRepeatSampler());
 
 	TextureSubresourceInfo subresource;
 	rgraphCtx.bindImage(0, 0, m_runCtx.m_rt, subresource);
 
 	cmdb->bindShaderProgram(m_grProg);
 
-	cmdb->dispatchCompute(m_r->getWidth() / 2, m_r->getHeight() / 2, 1);
+	cmdb->dispatchCompute((m_r->getWidth() + m_workgroupSize[0] - 1) / m_workgroupSize[0],
+		(m_r->getHeight() + m_workgroupSize[1] - 1) / m_workgroupSize[1],
+		1);
 }
 
 } // end namespace anki

+ 3 - 0
src/anki/renderer/Reflections.h

@@ -35,10 +35,13 @@ private:
 
 	RenderTargetDescription m_rtDescr;
 
+	Array<U8, 2> m_workgroupSize = {{32, 32}};
+
 	class
 	{
 	public:
 		RenderTargetHandle m_rt;
+		RenderingContext* m_ctx ANKI_DBG_NULLIFY;
 	} m_runCtx;
 
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& cfg);

+ 7 - 0
src/anki/renderer/Renderer.cpp

@@ -23,6 +23,7 @@
 #include <anki/renderer/Volumetric.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/TemporalAA.h>
+#include <anki/renderer/Reflections.h>
 
 namespace anki
 {
@@ -135,6 +136,9 @@ Error Renderer::initInternal(const ConfigSet& config)
 	m_downscale.reset(getAllocator().newInstance<DownscaleBlur>(this));
 	ANKI_CHECK(m_downscale->init(config));
 
+	m_refl.reset(m_alloc.newInstance<Reflections>(this));
+	ANKI_CHECK(m_refl->init(config));
+
 	m_tonemapping.reset(getAllocator().newInstance<Tonemapping>(this));
 	ANKI_CHECK(m_tonemapping->init(config));
 
@@ -247,6 +251,9 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 		m_resourcesDirty = false;
 	}
 
+	// Import RTs first
+	m_downscale->importRenderTargets(ctx);
+
 	// Populate render graph. WARNING Watch the order
 	m_shadowMapping->populateRenderGraph(ctx);
 	m_indirect->populateRenderGraph(ctx);

+ 1 - 0
src/anki/renderer/Renderer.h

@@ -329,6 +329,7 @@ private:
 	UniquePtr<Indirect> m_indirect;
 	UniquePtr<ShadowMapping> m_shadowMapping; ///< Shadow mapping.
 	UniquePtr<GBuffer> m_gbuffer; ///< Material rendering stage
+	UniquePtr<Reflections> m_refl;
 	UniquePtr<LightShading> m_lightShading; ///< Illumination rendering stage
 	UniquePtr<DepthDownscale> m_depth;
 	UniquePtr<ForwardShading> m_forwardShading; ///< Forward shading.