Ver Fonte

Some more work on IBL

Panagiotis Christopoulos Charitos há 10 anos atrás
pai
commit
566e4dc378

+ 22 - 0
include/anki/renderer/Ir.h

@@ -8,6 +8,7 @@
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/RenderingPass.h>
 #include <anki/renderer/Clusterer.h>
+#include <anki/resource/TextureResource.h>
 
 namespace anki
 {
@@ -40,6 +41,11 @@ anki_internal:
 		return m_envCubemapArr;
 	}
 
+	TexturePtr getIrradianceCubemapArray() const
+	{
+		return m_irradianceCubemapArr;
+	}
+
 	DynamicBufferToken getProbesToken() const
 	{
 		return m_probesToken;
@@ -65,6 +71,16 @@ anki_internal:
 		return m_clusterer;
 	}
 
+	TexturePtr getIntegrationLut() const
+	{
+		return m_integrationLut->getGrTexture();
+	}
+
+	SamplerPtr getIntegrationLutSampler() const
+	{
+		return m_integrationLutSampler;
+	}
+
 private:
 	class CacheEntry
 	{
@@ -73,6 +89,8 @@ private:
 		Timestamp m_timestamp = 0; ///< When last rendered.
 	};
 
+	static const PixelFormat IRRADIANCE_RT_PIXEL_FORMAT;
+
 	Renderer m_nestedR;
 	TexturePtr m_envCubemapArr;
 	U16 m_cubemapArrMipCount = 0;
@@ -88,6 +106,10 @@ private:
 	PipelinePtr m_computeIrradiancePpline;
 	ResourceGroupPtr m_computeIrradianceResources;
 
+	// Other
+	TextureResourcePtr m_integrationLut;
+	SamplerPtr m_integrationLutSampler;
+
 	// Tokens
 	DynamicBufferToken m_probesToken;
 	DynamicBufferToken m_clustersToken;

+ 1 - 3
include/anki/renderer/Refl.h

@@ -42,7 +42,7 @@ private:
 	// Sub-stages
 	UniquePtr<Ir> m_ir;
 
-	// 1st pass
+	// 1st pass: Do the indirect lighting computation
 	ShaderResourcePtr m_frag;
 	PipelinePtr m_ppline;
 	TexturePtr m_rt;
@@ -50,8 +50,6 @@ private:
 	ResourceGroupPtr m_rcGroup;
 	BufferPtr m_uniforms;
 	Timestamp m_uniformsUpdateTimestamp = 0;
-	TextureResourcePtr m_integrationLut;
-	SamplerPtr m_integrationLutSampler;
 
 	// 2nd pass: Blit
 	ResourceGroupPtr m_blitRcGroup;

+ 2 - 2
include/anki/util/Ptr.h

@@ -120,7 +120,7 @@ public:
 	{
 	}
 
-	WeakPtr(T* ptr)
+	explicit WeakPtr(T* ptr)
 		: Base(ptr)
 	{
 	}
@@ -339,7 +339,7 @@ public:
 	{
 	}
 
-	IntrusivePtr(T* ptr)
+	explicit IntrusivePtr(T* ptr)
 		: Base()
 	{
 		reset(ptr);

+ 32 - 9
shaders/ImageReflections.glsl

@@ -51,6 +51,13 @@ layout(std430,
 layout(TEX_BINDING(IMAGE_REFLECTIONS_SET,
 	IMAGE_REFLECTIONS_TEX_BINDING)) uniform samplerCubeArray u_reflectionsTex;
 
+layout(TEX_BINDING(IMAGE_REFLECTIONS_SET,
+	IMAGE_REFLECTIONS_TEX_BINDING
+		+ 1)) uniform samplerCubeArray u_irradianceTex;
+
+layout(TEX_BINDING(IMAGE_REFLECTIONS_SET,
+	IMAGE_REFLECTIONS_TEX_BINDING + 2)) uniform sampler2D u_integrationLut;
+
 //==============================================================================
 // Compute the cubemap texture lookup vector given the reflection vector (r)
 // the radius squared of the probe (R2) and the frag pos in sphere space (f)
@@ -83,10 +90,16 @@ vec3 computeCubemapVec(in vec3 r, in float R2, in vec3 f)
 }
 
 //==============================================================================
-vec3 readReflection(
-	in uint clusterIndex, in vec3 posVSpace, in vec3 r, in float lod)
+void readIndirectInternal(in uint clusterIndex,
+	in vec3 posVSpace,
+	in vec3 r,
+	in vec3 n,
+	in float lod,
+	out vec3 specIndirect,
+	out vec3 diffIndirect)
 {
-	vec3 color = vec3(0.0);
+	specIndirect = vec3(0.0);
+	diffIndirect = vec3(0.0);
 
 	// Check proxy
 	uvec2 cluster = u_reflectionClusters[clusterIndex];
@@ -114,15 +127,23 @@ vec3 readReflection(
 		float d = dot(f, f);
 		float factor = d / R2;
 		factor = min(factor, 1.0);
-		color = mix(c, color, factor);
-		// Equivelent: color = c * (1.0 - factor) + color * factor;
-	}
+		specIndirect = mix(c, specIndirect, factor);
+		// Same as: specIndirect = c * (1.0 - factor) + specIndirect * factor
 
-	return color;
+		// Do the same for diffuse
+		uv = computeCubemapVec(n, R2, f);
+		vec3 id = texture(u_irradianceTex, vec4(uv, cubemapIndex)).rgb;
+		diffIndirect = mix(id, diffIndirect, factor);
+	}
 }
 
 //==============================================================================
-vec3 doImageReflections(in vec3 posVSpace, in vec3 r, in float lod)
+void readIndirect(in vec3 posVSpace,
+	in vec3 r,
+	in vec3 n,
+	in float lod,
+	out vec3 specIndirect,
+	out vec3 diffIndirect)
 {
 	uint clusterIdx =
 		computeClusterIndexUsingFragCoord(u_nearClusterMagicPad2.x,
@@ -130,7 +151,9 @@ vec3 doImageReflections(in vec3 posVSpace, in vec3 r, in float lod)
 			posVSpace.z,
 			TILE_COUNT_X,
 			TILE_COUNT_Y);
-	return readReflection(clusterIdx, posVSpace, r, lod);
+
+	readIndirectInternal(
+		clusterIdx, posVSpace, r, n, lod, specIndirect, diffIndirect);
 }
 
 #endif

+ 10 - 11
shaders/Irradiance.frag.glsl

@@ -10,11 +10,13 @@
 layout(location = 0) in vec2 in_uv;
 layout(location = 0) out vec3 out_color;
 
-layout(TEX_BINDING(0, 0)) uniform samplerCube u_envTex;
+layout(TEX_BINDING(0, 0)) uniform samplerCubeArray u_envTex;
 
 layout(UBO_BINDING(0, 0)) uniform u0_
 {
-	uvec4 u_faceIdxPad3;
+	// x: The face index to render to
+	// y: The array index to read from the u_envTex
+	uvec4 u_faceIdxArrayIdxPad2;
 };
 
 const mat3 CUBE_ROTATIONS[6] = mat3[](mat3(vec3(0.000000, 0.000000, -1.000000),
@@ -41,8 +43,11 @@ const mat3 CUBE_ROTATIONS[6] = mat3[](mat3(vec3(0.000000, 0.000000, -1.000000),
 
 //==============================================================================
 // Integrate the environment map to compute the irradiance for a single fragment
-vec3 computeIrradiance(in uint face)
+void main()
 {
+	uint face = u_faceIdxArrayIdxPad2.x;
+	float texArrIdx = float(u_faceIdxArrayIdxPad2.y);
+
 	// Get the r coordinate of the current face and fragment
 	vec2 ndc = in_uv * 2.0 - 1.0;
 	vec3 ri = CUBE_ROTATIONS[face] * normalize(vec3(ndc, -1.0));
@@ -61,7 +66,7 @@ vec3 computeIrradiance(in uint face)
 				vec2 ndc = uv * 2.0 - 1.0;
 				vec3 r = CUBE_ROTATIONS[f] * normalize(vec3(ndc, -1.0));
 
-				vec3 col = texture(u_envTex, r).rgb;
+				vec3 col = texture(u_envTex, vec4(r, texArrIdx)).rgb;
 
 				float lambert = max(0.0, dot(r, ri));
 				outCol += col * lambert;
@@ -70,11 +75,5 @@ vec3 computeIrradiance(in uint face)
 		}
 	}
 
-	return outCol / weight;
-}
-
-//==============================================================================
-void main()
-{
-	out_color = computeIrradiance(u_faceIdxPad3.x);
+	out_color = outCol / weight;
 }

+ 25 - 19
shaders/Pack.glsl

@@ -113,26 +113,33 @@ struct GbufferInfo
 // Populate the G buffer
 void writeGBuffer(in GbufferInfo g, out vec4 rt0, out vec4 rt1, out vec4 rt2)
 {
-	rt0 = vec4(g.diffuse, g.subsurface);
-	rt1 = vec4(g.specular, g.emission / MAX_EMISSION);
-	rt2 = vec4(packNormal(g.normal), g.roughness, g.metallic);
+	float comp =
+		packUnorm2ToUnorm1(vec2(g.subsurface, g.emission / MAX_EMISSION));
+	rt0 = vec4(g.diffuse, comp);
+	rt1 = vec4(g.specular, g.roughness);
+	rt2 = vec4(g.normal * 0.5 + 0.5, g.metallic);
 }
 
 // Read from G-buffer
-void readNormalRoughnessMetallicFromGBuffer(
-	in sampler2D rt2, in vec2 uv, inout GbufferInfo g)
-{
-	vec4 comp = texture(rt2, uv);
-	g.normal = unpackNormal(comp.xy);
-	g.roughness = comp.z;
-	g.metallic = comp.w;
-}
+#define readSpecularRoughnessFromGBuffer(rt1_, uv_, g_)                        \
+	{                                                                          \
+		vec4 comp = texture(rt1_, uv_);                                        \
+		g_.specular = comp.xyz;                                                \
+		g_.roughness = comp.w;                                                 \
+	}
+
+// Read from G-buffer
+#define readNormalMetallicFromGBuffer(rt2_, uv_, g_)                           \
+	{                                                                          \
+		vec4 comp = texture(rt2_, uv_);                                        \
+		g_.normal = comp.xyz * 2.0 - 1.0;                                      \
+		g_.metallic = comp.w;                                                  \
+	}
 
 // Read from G-buffer
 void readNormalFromGBuffer(in sampler2D rt2, in vec2 uv, out vec3 normal)
 {
-	vec2 comp = texture(rt2, uv).rg;
-	normal = unpackNormal(comp);
+	normal = texture(rt2, uv).rgb * 2.0 - 1.0;
 }
 
 // Read from the G buffer
@@ -144,13 +151,12 @@ void readGBuffer(in sampler2D rt0,
 {
 	vec4 comp = texture(rt0, uv);
 	g.diffuse = comp.xyz;
-	g.subsurface = comp.w;
-
-	comp = texture(rt1, uv);
-	g.specular = comp.xyz;
-	g.emission = comp.w * MAX_EMISSION;
+	vec2 comp2 = unpackUnorm1ToUnorm2(comp.w);
+	g.subsurface = comp2.x;
+	g.emission = comp2.y * MAX_EMISSION;
 
-	readNormalRoughnessMetallicFromGBuffer(rt2, uv, g);
+	readSpecularRoughnessFromGBuffer(rt1, uv, g);
+	readNormalMetallicFromGBuffer(rt2, uv, g);
 }
 
 #endif

+ 22 - 13
shaders/Refl.frag.glsl

@@ -7,7 +7,8 @@
 
 // Common
 layout(TEX_BINDING(0, 0)) uniform sampler2D u_depthRt;
-layout(TEX_BINDING(0, 1)) uniform sampler2D u_msRt2;
+layout(TEX_BINDING(0, 1)) uniform sampler2D u_msRt1;
+layout(TEX_BINDING(0, 2)) uniform sampler2D u_msRt2;
 
 layout(std140, UBO_BINDING(0, 0)) uniform u0_
 {
@@ -15,6 +16,12 @@ layout(std140, UBO_BINDING(0, 0)) uniform u0_
 	mat4 u_projectionMat;
 };
 
+// SSLR
+#if SSLR_ENABLED
+layout(TEX_BINDING(0, 3)) uniform sampler2D u_isRt;
+#include "shaders/Sslr.glsl"
+#endif
+
 // IR
 #if IR_ENABLED
 #define IMAGE_REFLECTIONS_SET 0
@@ -25,16 +32,9 @@ layout(std140, UBO_BINDING(0, 0)) uniform u0_
 #undef IMAGE_REFLECTIONS_FIRST_SS_BINDING
 #endif
 
-// SSLR
-#if SSLR_ENABLED
-layout(TEX_BINDING(0, 3)) uniform sampler2D u_isRt;
-
-#include "shaders/Sslr.glsl"
-#endif
-
 // In/out
 layout(location = 0) in vec2 in_texCoord;
-layout(location = 0) out vec3 out_color;
+layout(location = 0) out vec3 out_indirectColor;
 
 void main()
 {
@@ -48,7 +48,8 @@ void main()
 		(2.0 * in_texCoord - 1.0) * u_projectionParams.xy * posVSpace.z;
 
 	GbufferInfo gbuffer;
-	readNormalRoughnessMetallicFromGBuffer(u_msRt2, in_texCoord, gbuffer);
+	readSpecularRoughnessFromGBuffer(u_msRt1, in_texCoord, gbuffer);
+	readNormalMetallicFromGBuffer(u_msRt2, in_texCoord, gbuffer);
 
 	// Compute relflection vector
 	vec3 eye = normalize(posVSpace);
@@ -79,9 +80,17 @@ void main()
 //
 #if IR_ENABLED
 	float reflLod = float(IR_MIPMAP_COUNT) * gbuffer.roughness;
-	vec3 imgRefl = doImageReflections(posVSpace, r, reflLod);
-	out_color = mix(imgRefl, out_color, sslrContribution);
+
+	vec3 specIndirect, diffIndirect;
+	readIndirect(
+		posVSpace, r, gbuffer.normal, reflLod, specIndirect, diffIndirect);
 #endif
 
-	out_color *= gbuffer.metallic;
+	// Finalize the indirect specular
+	float ndotv = dot(gbuffer.normal, -eye);
+	vec2 envBRDF = texture(u_integrationLut, vec2(gbuffer.roughness, ndotv)).xy;
+	specIndirect = specIndirect * (gbuffer.specular * envBRDF.x + envBRDF.y);
+
+	// Finalize
+	out_indirectColor = diffIndirect + specIndirect * gbuffer.metallic;
 }

+ 2 - 2
src/gr/gl/CommandBuffer.cpp

@@ -47,14 +47,14 @@ void CommandBuffer::create(CommandBufferInitHints hints)
 void CommandBuffer::flush()
 {
 	getManager().getImplementation().getRenderingThread().flushCommandBuffer(
-		this);
+		CommandBufferPtr(this));
 }
 
 //==============================================================================
 void CommandBuffer::finish()
 {
 	getManager().getImplementation().getRenderingThread().finishCommandBuffer(
-		this);
+		CommandBufferPtr(this));
 }
 
 //==============================================================================

+ 31 - 5
src/renderer/Ir.cpp

@@ -141,6 +141,10 @@ public:
 // Ir                                                                          =
 //==============================================================================
 
+//==============================================================================
+const PixelFormat Ir::IRRADIANCE_RT_PIXEL_FORMAT(
+	ComponentFormat::R8G8B8, TransformFormat::UNORM);
+
 //==============================================================================
 Ir::Ir(Renderer* r)
 	: RenderingPass(r)
@@ -221,12 +225,27 @@ Error Ir::init(const ConfigSet& config)
 	texinit.m_sampling.m_mipmapFilter = SamplingFilter::LINEAR;
 
 	m_envCubemapArr = getGrManager().newInstance<Texture>(texinit);
+
+	texinit.m_format = IRRADIANCE_RT_PIXEL_FORMAT;
 	m_irradianceCubemapArr = getGrManager().newInstance<Texture>(texinit);
+
 	m_cubemapArrMipCount = computeMaxMipmapCount(m_fbSize, m_fbSize);
 
 	// Create irradiance stuff
 	ANKI_CHECK(initIrradiance());
 
+	// Load split sum integration LUT
+	ANKI_CHECK(getResourceManager().loadResource(
+		"engine_data/SplitSumIntegration.ankitex", m_integrationLut));
+
+	SamplerInitializer sinit;
+	sinit.m_minMagFilter = SamplingFilter::LINEAR;
+	sinit.m_mipmapFilter = SamplingFilter::BASE;
+	sinit.m_minLod = 0.0;
+	sinit.m_maxLod = 1.0;
+	sinit.m_repeat = false;
+	m_integrationLutSampler = getGrManager().newInstance<Sampler>(sinit);
+
 	getGrManager().finish();
 
 	// Init the clusterer
@@ -269,6 +288,7 @@ Error Ir::initIrradiance()
 	// Create the resources
 	ResourceGroupInitializer rcInit;
 	rcInit.m_uniformBuffers[0].m_dynamic = true;
+	rcInit.m_textures[0].m_texture = m_envCubemapArr;
 
 	m_computeIrradianceResources =
 		getGrManager().newInstance<ResourceGroup>(rcInit);
@@ -594,23 +614,29 @@ Error Ir::renderReflection(
 		cmdb->generateMipmaps(m_envCubemapArr, 6 * cubemapIdx + i);
 
 		// Compute irradiance
-		/*DynamicBufferInfo dinf;
-		UVec4* faceIdx =
+		DynamicBufferInfo dinf;
+		UVec4* faceIdxArrayIdx =
 			static_cast<UVec4*>(getGrManager().allocateFrameHostVisibleMemory(
 				sizeof(UVec4), BufferUsage::UNIFORM, dinf.m_uniformBuffers[0]));
-		faceIdx->x() = i;
+		faceIdxArrayIdx->x() = i;
+		faceIdxArrayIdx->y() = cubemapIdx;
 
 		FramebufferInitializer fbinit;
 		fbinit.m_colorAttachmentsCount = 1;
 		fbinit.m_colorAttachments[0].m_texture = m_irradianceCubemapArr;
 		fbinit.m_colorAttachments[0].m_arrayIndex = cubemapIdx;
 		fbinit.m_colorAttachments[0].m_faceIndex = i;
+		fbinit.m_colorAttachments[0].m_format = IRRADIANCE_RT_PIXEL_FORMAT;
+		fbinit.m_colorAttachments[0].m_loadOperation =
+			AttachmentLoadOperation::DONT_CARE;
 		FramebufferPtr fb = getGrManager().newInstance<Framebuffer>(fbinit);
 
 		cmdb->bindFramebuffer(fb);
-		cmdb->bindResourceGroup(0, m_computeIrradianceResources, &dinf);
+		cmdb->setViewport(0, 0, m_fbSize, m_fbSize);
+		cmdb->bindResourceGroup(m_computeIrradianceResources, 0, &dinf);
 		cmdb->bindPipeline(m_computeIrradiancePpline);
-		m_r->drawQuad(cmdb);*/
+		m_r->drawQuad(cmdb);
+		cmdb->generateMipmaps(m_irradianceCubemapArr, 6 * cubemapIdx + i);
 
 		// Flush
 		for(U j = 0; j < cmdbs.getSize(); ++j)

+ 3 - 2
src/renderer/Ms.cpp

@@ -55,7 +55,7 @@ Error Ms::createRt(U32 index, U32 samples)
 		RT_PIXEL_FORMATS[1],
 		samples,
 		SamplingFilter::NEAREST,
-		1,
+		2,
 		plane.m_rt1);
 
 	m_r->createRenderTarget(m_r->getWidth(),
@@ -63,7 +63,7 @@ Error Ms::createRt(U32 index, U32 samples)
 		RT_PIXEL_FORMATS[2],
 		samples,
 		SamplingFilter::NEAREST,
-		3,
+		2,
 		plane.m_rt2);
 
 	AttachmentLoadOperation loadop = AttachmentLoadOperation::DONT_CARE;
@@ -181,6 +181,7 @@ void Ms::generateMipmaps(CommandBufferPtr& cmdb)
 {
 	U planeId = (m_r->getSamples() == 1) ? 1 : 0;
 	cmdb->generateMipmaps(m_planes[planeId].m_depthRt);
+	cmdb->generateMipmaps(m_planes[planeId].m_rt1);
 	cmdb->generateMipmaps(m_planes[planeId].m_rt2);
 }
 

+ 9 - 14
src/renderer/Refl.cpp

@@ -127,17 +127,20 @@ Error Refl::init1stPass(const ConfigSet& config)
 
 	// Create RC group
 	ResourceGroupInitializer rcInit;
-	SamplerInitializer sinit;
 
+	SamplerInitializer sinit;
 	sinit.m_minLod = 1.0;
 	sinit.m_minMagFilter = SamplingFilter::NEAREST;
 	sinit.m_mipmapFilter = SamplingFilter::NEAREST;
 	rcInit.m_textures[0].m_texture = m_r->getMs().getDepthRt();
 	rcInit.m_textures[0].m_sampler = gr.newInstance<Sampler>(sinit);
 
-	rcInit.m_textures[1].m_texture = m_r->getMs().getRt2();
+	rcInit.m_textures[1].m_texture = m_r->getMs().getRt1();
 	rcInit.m_textures[1].m_sampler = gr.newInstance<Sampler>(sinit);
 
+	rcInit.m_textures[2].m_texture = m_r->getMs().getRt2();
+	rcInit.m_textures[2].m_sampler = gr.newInstance<Sampler>(sinit);
+
 	if(m_sslrEnabled)
 	{
 		rcInit.m_textures[3].m_texture = m_r->getIs().getRt();
@@ -146,6 +149,10 @@ Error Refl::init1stPass(const ConfigSet& config)
 	if(m_irEnabled)
 	{
 		rcInit.m_textures[4].m_texture = m_ir->getEnvironmentCubemapArray();
+		rcInit.m_textures[5].m_texture = m_ir->getIrradianceCubemapArray();
+
+		rcInit.m_textures[6].m_texture = m_ir->getIntegrationLut();
+		rcInit.m_textures[6].m_sampler = m_ir->getIntegrationLutSampler();
 	}
 
 	rcInit.m_uniformBuffers[0].m_buffer = m_uniforms;
@@ -171,18 +178,6 @@ Error Refl::init1stPass(const ConfigSet& config)
 		AttachmentLoadOperation::DONT_CARE;
 	m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
 
-	// Load split sum integration LUT
-	ANKI_CHECK(getResourceManager().loadResource(
-		"engine_data/SplitSumIntegration.ankitex", m_integrationLut));
-
-	sinit = SamplerInitializer();
-	sinit.m_minMagFilter = SamplingFilter::LINEAR;
-	sinit.m_mipmapFilter = SamplingFilter::BASE;
-	sinit.m_minLod = 0.0;
-	sinit.m_maxLod = 1.0;
-	sinit.m_repeat = false;
-	m_integrationLutSampler = getGrManager().newInstance<Sampler>(sinit);
-
 	return ErrorCode::NONE;
 }
 

+ 1 - 1
testapp/Main.cpp

@@ -502,7 +502,7 @@ Error initSubsystems(int argc, char* argv[])
 	config.set("is.sm.poissonEnabled", true);
 	config.set("is.sm.resolution", 1024);
 	config.set("lf.maxFlares", 32);
-	config.set("pps.enabled", true);
+	config.set("pps.enabled", false);
 	config.set("pps.bloom.enabled", true);
 	config.set("pps.bloom.renderingQuality", 0.5);
 	config.set("pps.bloom.blurringDist", 1.0);