浏览代码

Removing lut from SSAO

Panagiotis Christopoulos Charitos 9 年之前
父节点
当前提交
a62b2c03da
共有 4 个文件被更改,包括 76 次插入145 次删除
  1. 9 17
      shaders/Ssao.frag.glsl
  2. 36 6
      src/anki/gr/gl/TextureImpl.cpp
  3. 31 119
      src/anki/renderer/Ssao.cpp
  4. 0 3
      src/anki/renderer/Ssao.h

+ 9 - 17
shaders/Ssao.frag.glsl

@@ -8,10 +8,12 @@
 #include "shaders/Pack.glsl"
 #include "shaders/Functions.glsl"
 
+const vec3 KERNEL[KERNEL_SIZE] = KERNEL_ARRAY; // This will be appended in C++
+
 const float RANGE_CHECK_RADIUS = RADIUS * 2.0;
 
 // Initial is 1.0 but the bigger it is the more darker the SSAO factor gets
-const float DARKNESS_MULTIPLIER = 1.0;
+const float DARKNESS_MULTIPLIER = 1.5;
 
 // The algorithm will chose the number of samples depending on the distance
 const float MAX_DISTANCE = 40.0;
@@ -29,7 +31,6 @@ 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, 3)) uniform sampler2DArray u_hemisphereLut;
 
 // Get normal
 vec3 readNormal(in vec2 uv)
@@ -45,7 +46,6 @@ 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;
-	// return normalize(noise * 2.0 - 1.0);
 	return noise;
 }
 
@@ -73,26 +73,18 @@ void main(void)
 	vec3 origin = readPosition(in_texCoords);
 
 	vec3 normal = readNormal(in_texCoords);
-	vec3 randRadius = readRandom(in_texCoords);
-
-	float theta = atan(normal.y, normal.x); // [-pi, pi]
-	// Now move theta to [0, 2*pi]. Adding 2*pi gives the same angle. Then fmod to move back to [0, 2*pi]
-	theta = mod(theta + 2.0 * PI, 2.0 * PI);
-
-	float phi = acos(normal.z / 1.0); // [0, PI]
+	vec3 rvec = readRandom(in_texCoords);
 
-	vec2 lutCoords;
-	lutCoords.x = theta / (2.0 * PI);
-	lutCoords.y = phi / PI;
-	lutCoords = clamp(lutCoords, 0.0, 1.0);
+	vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
+	vec3 bitangent = cross(normal, tangent);
+	mat3 tbn = mat3(tangent, bitangent, normal);
 
 	// Iterate kernel
 	float factor = 0.0;
 	for(uint i = 0U; i < KERNEL_SIZE; ++i)
 	{
-		vec3 hemispherePoint = texture(u_hemisphereLut, vec3(lutCoords, float(i))).xyz;
-		hemispherePoint = normalize(hemispherePoint);
-		hemispherePoint = hemispherePoint * randRadius + origin;
+		vec3 hemispherePoint = tbn * KERNEL[i];
+		hemispherePoint = hemispherePoint * RADIUS + origin;
 
 		// project sample position:
 		vec4 projHemiPoint = projectPerspective(

+ 36 - 6
src/anki/gr/gl/TextureImpl.cpp

@@ -77,18 +77,48 @@ static void convertTextureInformation(
 #endif
 	case ComponentFormat::R8:
 		format = GL_R;
-		internalFormat = GL_R8;
-		type = GL_UNSIGNED_BYTE;
+
+		if(pf.m_transform == TransformFormat::UNORM)
+		{
+			internalFormat = GL_R8;
+			type = GL_UNSIGNED_BYTE;
+		}
+		else
+		{
+			ANKI_ASSERT(pf.m_transform == TransformFormat::SNORM);
+			internalFormat = GL_R8_SNORM;
+			type = GL_BYTE;
+		}
 		break;
 	case ComponentFormat::R8G8B8:
 		format = GL_RGB;
-		internalFormat = GL_RGB8;
-		type = GL_UNSIGNED_BYTE;
+
+		if(pf.m_transform == TransformFormat::UNORM)
+		{
+			internalFormat = GL_RGB8;
+			type = GL_UNSIGNED_BYTE;
+		}
+		else
+		{
+			ANKI_ASSERT(pf.m_transform == TransformFormat::SNORM);
+			internalFormat = GL_RGB8_SNORM;
+			type = GL_BYTE;
+		}
 		break;
 	case ComponentFormat::R8G8B8A8:
 		format = GL_RGBA;
-		internalFormat = GL_RGBA8;
-		type = GL_UNSIGNED_BYTE;
+
+		if(pf.m_transform == TransformFormat::UNORM)
+		{
+			internalFormat = GL_RGBA8;
+			type = GL_UNSIGNED_BYTE;
+		}
+		else
+		{
+			ANKI_ASSERT(pf.m_transform == TransformFormat::SNORM);
+			internalFormat = GL_RGBA8_SNORM;
+			type = GL_BYTE;
+		}
 		break;
 	case ComponentFormat::R32G32:
 		if(pf.m_transform == TransformFormat::FLOAT)

+ 31 - 119
src/anki/renderer/Ssao.cpp

@@ -15,8 +15,8 @@
 namespace anki
 {
 
-const U NOISE_TEX_SIZE = 4;
-const U KERNEL_SIZE = 16;
+const U NOISE_TEX_SIZE = 8;
+const U KERNEL_SIZE = 8;
 const F32 HEMISPHERE_RADIUS = 1.1; // In game units
 
 template<typename TVec>
@@ -37,126 +37,25 @@ static void genHemisphere(TVec* ANKI_RESTRICT arr, TVec* ANKI_RESTRICT arrEnd)
 	} while(++arr != arrEnd);
 }
 
-static void genNoise(Vec4* ANKI_RESTRICT arr, Vec4* ANKI_RESTRICT 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(0.2f, HEMISPHERE_RADIUS), randRange(0.2f, HEMISPHERE_RADIUS), randRange(0.2f, HEMISPHERE_RADIUS));
+		Vec3 v(randRange(-1.0f, 1.0f), randRange(-1.0f, 1.0f), 0.0f);
+		v.normalize();
 
-		*arr = Vec4(v, 0.0f);
+		(*arr)[0] = v[0] * MAX_I8;
+		(*arr)[1] = v[1] * MAX_I8;
+		(*arr)[2] = v[2] * MAX_I8;
+		(*arr)[3] = 0;
 	} while(++arr != arrEnd);
 }
 
 const PixelFormat Ssao::RT_PIXEL_FORMAT(ComponentFormat::R8, TransformFormat::UNORM);
 
-void Ssao::createHemisphereLut()
-{
-	constexpr F64 PI = getPi<F64>();
-	constexpr F64 MIN_ANGLE = PI / 8.0;
-
-	// Compute the hemisphere
-	Array<DVec3, KERNEL_SIZE> kernel;
-	genHemisphere(&kernel[0], &kernel[0] + KERNEL_SIZE);
-
-	constexpr U LUT_TEX_SIZE_X = 2.0 * PI / MIN_ANGLE;
-	constexpr U LUT_TEX_SIZE_Y = PI / MIN_ANGLE;
-	constexpr U LUT_TEX_LAYERS = KERNEL_SIZE;
-
-	Array<Array2d<Vec4, LUT_TEX_SIZE_Y, LUT_TEX_SIZE_X>, LUT_TEX_LAYERS> lutTexData;
-	memset(&lutTexData[0][0][0], 0, sizeof(lutTexData));
-
-	U countX = 0;
-	U countY = 0;
-	U totalCount = 0;
-	(void)totalCount;
-	for(F64 theta = 0.0; theta < 2.0 * PI; theta += MIN_ANGLE)
-	{
-		countY = 0;
-		for(F64 phi = 0.0; phi < PI; phi += MIN_ANGLE)
-		{
-			// Compute the normal from the spherical coordinates
-			DVec3 normal;
-			normal.x() = cos(theta) * sin(phi);
-			normal.y() = sin(theta) * sin(phi);
-			normal.z() = cos(phi);
-			normal.normalize();
-
-			// Compute a tangent & bitangent
-			DVec3 bitangent(0.01, 1.0, 0.01);
-			bitangent.normalize();
-
-			DVec3 tangent = bitangent.cross(normal);
-			tangent.normalize();
-
-			bitangent = normal.cross(tangent);
-
-			// Set the TBN matrix
-			DMat3 rot;
-			rot.setColumns(tangent, bitangent, normal);
-
-			for(U k = 0; k < KERNEL_SIZE; ++k)
-			{
-				DVec3 rotVec = rot * kernel[k];
-
-				lutTexData[k][countY][countX] = Vec4(rotVec.x(), rotVec.y(), rotVec.z(), 0.0);
-
-				++totalCount;
-			}
-
-			++countY;
-		}
-
-		++countX;
-	}
-
-	ANKI_ASSERT(totalCount == (LUT_TEX_SIZE_Y * LUT_TEX_SIZE_X * LUT_TEX_LAYERS));
-
-	// Create the texture
-	TextureInitInfo tinit;
-	tinit.m_usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::UPLOAD;
-	tinit.m_width = LUT_TEX_SIZE_X;
-	tinit.m_height = LUT_TEX_SIZE_Y;
-	tinit.m_depth = 1;
-	tinit.m_layerCount = LUT_TEX_LAYERS;
-	tinit.m_type = TextureType::_2D_ARRAY;
-	tinit.m_format = PixelFormat(ComponentFormat::R32G32B32A32, TransformFormat::FLOAT);
-	tinit.m_mipmapsCount = 1;
-	tinit.m_sampling.m_minMagFilter = SamplingFilter::LINEAR;
-	tinit.m_sampling.m_repeat = false;
-
-	m_hemisphereLut = getGrManager().newInstance<Texture>(tinit);
-
-	CommandBufferInitInfo cmdbinit;
-	cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH;
-	CommandBufferPtr cmdb = getGrManager().newInstance<CommandBuffer>(cmdbinit);
-
-	for(U i = 0; i < LUT_TEX_LAYERS; ++i)
-	{
-		cmdb->setTextureSurfaceBarrier(
-			m_hemisphereLut, TextureUsageBit::NONE, TextureUsageBit::UPLOAD, TextureSurfaceInfo(0, 0, 0, i));
-	}
-
-	for(U i = 0; i < LUT_TEX_LAYERS; ++i)
-	{
-		cmdb->uploadTextureSurfaceCopyData(
-			m_hemisphereLut, TextureSurfaceInfo(0, 0, 0, i), &lutTexData[i][0][0], sizeof(lutTexData[i]));
-	}
-
-	for(U i = 0; i < LUT_TEX_LAYERS; ++i)
-	{
-		cmdb->setTextureSurfaceBarrier(m_hemisphereLut,
-			TextureUsageBit::UPLOAD,
-			TextureUsageBit::SAMPLED_FRAGMENT,
-			TextureSurfaceInfo(0, 0, 0, i));
-	}
-
-	cmdb->flush();
-}
-
 Error Ssao::createFb(FramebufferPtr& fb, TexturePtr& rt)
 {
 	// Set to bilinear because the blurring techniques take advantage of that
@@ -209,14 +108,14 @@ Error Ssao::initInternal(const ConfigSet& config)
 	tinit.m_depth = 1;
 	tinit.m_layerCount = 1;
 	tinit.m_type = TextureType::_2D;
-	tinit.m_format = PixelFormat(ComponentFormat::R32G32B32A32, TransformFormat::FLOAT);
+	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);
 
-	Array<Vec4, NOISE_TEX_SIZE * NOISE_TEX_SIZE> noise;
+	Array<Array<I8, 4>, NOISE_TEX_SIZE * NOISE_TEX_SIZE> noise;
 	genNoise(&noise[0], &noise[0] + noise.getSize());
 
 	CommandBufferInitInfo cmdbInit;
@@ -234,6 +133,24 @@ Error Ssao::initInternal(const ConfigSet& config)
 
 	cmdb->flush();
 
+	//
+	// Kernel
+	//
+	StringAuto kernelStr(getAllocator());
+	Array<Vec3, KERNEL_SIZE> kernel;
+
+	genHemisphere(kernel.begin(), kernel.end());
+	kernelStr.create("vec3[](");
+	for(U i = 0; i < kernel.size(); i++)
+	{
+		StringAuto tmp(getAllocator());
+
+		tmp.sprintf(
+			"vec3(%f, %f, %f) %s", kernel[i].x(), kernel[i].y(), kernel[i].z(), (i != kernel.size() - 1) ? ", " : ")");
+
+		kernelStr.append(tmp);
+	}
+
 	//
 	// Shaders
 	//
@@ -256,11 +173,13 @@ Error Ssao::initInternal(const ConfigSet& config)
 				"#define WIDTH %u\n"
 				"#define HEIGHT %u\n"
 				"#define KERNEL_SIZE %u\n"
+				"#define KERNEL_ARRAY %s\n"
 				"#define RADIUS float(%f)\n",
 		NOISE_TEX_SIZE,
 		m_width,
 		m_height,
 		KERNEL_SIZE,
+		&kernelStr[0],
 		HEMISPHERE_RADIUS);
 
 	ANKI_CHECK(getResourceManager().loadResourceToCache(m_ssaoFrag, "shaders/Ssao.frag.glsl", pps.toCString(), "r_"));
@@ -301,11 +220,6 @@ Error Ssao::initInternal(const ConfigSet& config)
 
 	m_vblurPpline = getGrManager().newInstance<Pipeline>(ppinit);
 
-	//
-	// Lookup texture
-	//
-	createHemisphereLut();
-
 	//
 	// Resource groups
 	//
@@ -324,8 +238,6 @@ Error Ssao::initInternal(const ConfigSet& config)
 
 	rcinit.m_textures[2].m_texture = m_noiseTex;
 
-	rcinit.m_textures[3].m_texture = m_hemisphereLut;
-
 	rcinit.m_uniformBuffers[0].m_uploadedMemory = true;
 	rcinit.m_uniformBuffers[0].m_usage = BufferUsageBit::UNIFORM_FRAGMENT;
 	m_rcFirst = gr.newInstance<ResourceGroup>(rcinit);

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

@@ -57,7 +57,6 @@ private:
 	PipelinePtr m_vblurPpline;
 
 	TexturePtr m_noiseTex;
-	TexturePtr m_hemisphereLut;
 
 	ResourceGroupPtr m_rcFirst;
 	ResourceGroupPtr m_hblurRc;
@@ -65,8 +64,6 @@ private:
 
 	ANKI_USE_RESULT Error createFb(FramebufferPtr& fb, TexturePtr& rt);
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
-
-	void createHemisphereLut();
 };
 /// @}