Browse Source

SSAO additions

Panagiotis Christopoulos Charitos 9 years ago
parent
commit
5dd4f51dae
2 changed files with 33 additions and 70 deletions
  1. 19 40
      shaders/Ssao.frag.glsl
  2. 14 30
      src/anki/renderer/Ssao.cpp

+ 19 - 40
shaders/Ssao.frag.glsl

@@ -7,15 +7,11 @@
 #include "shaders/Common.glsl"
 #include "shaders/Pack.glsl"
 #include "shaders/Functions.glsl"
-#include "shaders/RendererCommonUniforms.glsl"
 
-const vec3 KERNEL[KERNEL_SIZE] = KERNEL_ARRAY; // This will be appended in C++
-
-// Radius in game units
-const float RADIUS = 1.1;
+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 = 2.0;
+const float DARKNESS_MULTIPLIER = 1.0;
 
 // The algorithm will chose the number of samples depending on the distance
 const float MAX_DISTANCE = 40.0;
@@ -76,16 +72,8 @@ void main(void)
 {
 	vec3 origin = readPosition(in_texCoords);
 
-	// Chose the number of samples dynamicaly
-	float sampleCountf = max(1.0 + origin.z / MAX_DISTANCE, 0.0) * float(KERNEL_SIZE);
-	uint sampleCount = uint(sampleCountf);
-
 	vec3 normal = readNormal(in_texCoords);
-	vec3 rvec = readRandom(in_texCoords);
-
-	vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
-	vec3 bitangent = cross(normal, tangent);
-	mat3 tbn = mat3(tangent, bitangent, normal);
+	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]
@@ -100,39 +88,30 @@ void main(void)
 
 	// Iterate kernel
 	float factor = 0.0;
-	for(uint i = 0U; i < sampleCount; ++i)
+	for(uint i = 0U; i < KERNEL_SIZE; ++i)
 	{
-#if 0
-		// get position
-		vec3 sample_ = tbn * KERNEL[i];
-		sample_ = sample_ * RADIUS + origin;
-#else
-		vec3 sample_ = texture(u_hemisphereLut, vec3(lutCoords, float(i))).xyz;
-		sample_ = normalize(sample_);
-		sample_ = sample_ * RADIUS + origin;
-#endif
+		vec3 hemispherePoint = texture(u_hemisphereLut, vec3(lutCoords, float(i))).xyz;
+		hemispherePoint = normalize(hemispherePoint);
+		hemispherePoint = hemispherePoint * randRadius + origin;
 
 		// project sample position:
-		vec4 offset = projectPerspective(
-			vec4(sample_, 1.0), u_projectionMat.x, u_projectionMat.y, u_projectionMat.z, u_projectionMat.w);
-		offset.xy = offset.xy / (2.0 * offset.w) + 0.5; // persp div & to NDC -> [0, 1]
+		vec4 projHemiPoint = projectPerspective(
+			vec4(hemispherePoint, 1.0), u_projectionMat.x, u_projectionMat.y, u_projectionMat.z, u_projectionMat.w);
+		projHemiPoint.xy = projHemiPoint.xy / (2.0 * projHemiPoint.w) + 0.5; // persp div & to NDC -> [0, 1]
 
 		// get sample depth:
-		float sampleDepth = readZ(offset.xy);
+		float sampleZ = readZ(projHemiPoint.xy);
 
-		// range check & accumulate:
-		const float ADVANCE = DARKNESS_MULTIPLIER / sampleCountf;
+		// Range check
+		float rangeCheck = abs(origin.z - sampleZ) / RANGE_CHECK_RADIUS;
+		rangeCheck = 1.0 - clamp(rangeCheck, 0.0, 1.0);
 
-#if 0
-		float rangeCheck =
-			abs(origin.z - sampleDepth) * (1.0 / (RADIUS * 10.0));
-		rangeCheck = 1.0 - rangeCheck;
+		// Accumulate
+		const float ADVANCE = DARKNESS_MULTIPLIER / float(KERNEL_SIZE);
+		float f = ceil(sampleZ - hemispherePoint.z);
+		f = clamp(f, 0.0, 1.0) * ADVANCE;
 
-		factor += clamp(sampleDepth - sample_.z, 0.0, ADVANCE) * rangeCheck;
-#else
-		float rangeCheck = abs(origin.z - sampleDepth) < RADIUS ? 1.0 : 0.0;
-		factor += (sampleDepth > sample_.z ? ADVANCE : 0.0) * rangeCheck;
-#endif
+		factor += f * rangeCheck;
 	}
 
 	out_color = 1.0 - factor;

+ 14 - 30
src/anki/renderer/Ssao.cpp

@@ -17,6 +17,7 @@ namespace anki
 
 const U NOISE_TEX_SIZE = 4;
 const U KERNEL_SIZE = 16;
+const F32 HEMISPHERE_RADIUS = 1.1; // In game units
 
 template<typename TVec>
 static void genHemisphere(TVec* ANKI_RESTRICT arr, TVec* ANKI_RESTRICT arrEnd)
@@ -28,7 +29,7 @@ static void genHemisphere(TVec* ANKI_RESTRICT arr, TVec* ANKI_RESTRICT arrEnd)
 		// Calculate the normal
 		arr->x() = randRange(-1.0, 1.0);
 		arr->y() = randRange(-1.0, 1.0);
-		arr->z() = randRange(0.0, 1.0);
+		arr->z() = randRange(0.1, 1.0);
 		arr->normalize();
 
 		// Adjust the length
@@ -43,8 +44,9 @@ static void genNoise(Vec4* ANKI_RESTRICT arr, Vec4* ANKI_RESTRICT arrEnd)
 	do
 	{
 		// Calculate the normal
-		Vec3 v(randRange(-1.0f, 1.0f), randRange(-1.0f, 1.0f), 0.0f);
-		v.normalize();
+		Vec3 v(
+			randRange(0.2f, HEMISPHERE_RADIUS), randRange(0.2f, HEMISPHERE_RADIUS), randRange(0.2f, HEMISPHERE_RADIUS));
+
 		*arr = Vec4(v, 0.0f);
 	} while(++arr != arrEnd);
 }
@@ -65,13 +67,15 @@ void Ssao::createHemisphereLut()
 	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));
 
-	UVec3 counts(0u);
+	U countX = 0;
+	U countY = 0;
 	U totalCount = 0;
 	(void)totalCount;
 	for(F64 theta = 0.0; theta < 2.0 * PI; theta += MIN_ANGLE)
 	{
-		counts.y() = 0;
+		countY = 0;
 		for(F64 phi = 0.0; phi < PI; phi += MIN_ANGLE)
 		{
 			// Compute the normal from the spherical coordinates
@@ -94,21 +98,19 @@ void Ssao::createHemisphereLut()
 			DMat3 rot;
 			rot.setColumns(tangent, bitangent, normal);
 
-			counts.z() = 0;
 			for(U k = 0; k < KERNEL_SIZE; ++k)
 			{
 				DVec3 rotVec = rot * kernel[k];
 
-				lutTexData[counts.z()][counts.y()][counts.x()] = Vec4(rotVec.x(), rotVec.y(), rotVec.z(), 0.0);
+				lutTexData[k][countY][countX] = Vec4(rotVec.x(), rotVec.y(), rotVec.z(), 0.0);
 
-				++counts.z();
 				++totalCount;
 			}
 
-			++counts.y();
+			++countY;
 		}
 
-		++counts.x();
+		++countX;
 	}
 
 	ANKI_ASSERT(totalCount == (LUT_TEX_SIZE_Y * LUT_TEX_SIZE_X * LUT_TEX_LAYERS));
@@ -232,24 +234,6 @@ 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
 	//
@@ -272,12 +256,12 @@ 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_"));