Browse Source

Change the method of the irradiance calculation

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
000c6b1359

+ 18 - 2
shaders/Functions.glsl

@@ -262,7 +262,7 @@ Vec3 gammaCorrection(Vec3 gamma, Vec3 col)
 }
 }
 
 
 // Can use 0.15 for sharpenFactor
 // Can use 0.15 for sharpenFactor
-Vec3 readSharpen(sampler2D tex, Vec2 uv, F32 sharpenFactor, bool detailed)
+Vec3 readSharpen(sampler2D tex, Vec2 uv, F32 sharpenFactor, Bool detailed)
 {
 {
 	Vec3 col = textureLod(tex, uv, 0.0).rgb;
 	Vec3 col = textureLod(tex, uv, 0.0).rgb;
 
 
@@ -333,9 +333,25 @@ Vec3 heatmap(F32 factor)
 	}
 	}
 }
 }
 
 
-bool incorrectColor(Vec3 c)
+Bool incorrectColor(Vec3 c)
 {
 {
 	return isnan(c.x) || isnan(c.y) || isnan(c.z) || isinf(c.x) || isinf(c.y) || isinf(c.z);
 	return isnan(c.x) || isnan(c.y) || isnan(c.z) || isinf(c.x) || isinf(c.y) || isinf(c.z);
 }
 }
 
 
+F32 areaElement(F32 x, F32 y)
+{
+	return atan(x * y, sqrt(x * x + y * y + 1.0));
+}
+
+/// Compute the solid angle of a cube. Solid angle is the area of a sphere when projected into a cubemap. It's also the
+/// delta omega (dω) in the irradiance integral and other integrals that operate in a sphere.
+/// http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/
+F32 cubeCoordSolidAngle(Vec2 norm, F32 cubeFaceSize)
+{
+	Vec2 invSize = Vec2(1.0 / cubeFaceSize);
+	Vec2 v0 = norm - invSize;
+	Vec2 v1 = norm + invSize;
+	return areaElement(v0.x, v0.y) - areaElement(v0.x, v1.y) - areaElement(v1.x, v0.y) + areaElement(v1.x, v1.y);
+}
+
 #endif
 #endif

+ 4 - 4
shaders/GBufferCommonTessc.glsl

@@ -143,7 +143,7 @@ F32 calcEdgeTessLevel(in Vec3 n0, in Vec3 n1, in F32 maxTessLevel)
 }*/
 }*/
 
 
 // Given the face positions in NDC caclulate if the face is front facing or not
 // Given the face positions in NDC caclulate if the face is front facing or not
-bool isFaceFrontFacing(in Vec2 posNdc[3])
+Bool isFaceFrontFacing(in Vec2 posNdc[3])
 {
 {
 	Vec2 a = posNdc[1] - posNdc[0];
 	Vec2 a = posNdc[1] - posNdc[0];
 	Vec2 b = posNdc[2] - posNdc[1];
 	Vec2 b = posNdc[2] - posNdc[1];
@@ -152,7 +152,7 @@ bool isFaceFrontFacing(in Vec2 posNdc[3])
 }
 }
 
 
 // Check if a single NDC position is outside the clip space
 // Check if a single NDC position is outside the clip space
-bool posOutsideClipSpace(in Vec2 posNdc)
+Bool posOutsideClipSpace(in Vec2 posNdc)
 {
 {
 	bvec2 compa = lessThan(posNdc, Vec2(-1.0));
 	bvec2 compa = lessThan(posNdc, Vec2(-1.0));
 	bvec2 compb = greaterThan(posNdc, Vec2(1.0));
 	bvec2 compb = greaterThan(posNdc, Vec2(1.0));
@@ -160,13 +160,13 @@ bool posOutsideClipSpace(in Vec2 posNdc)
 }
 }
 
 
 // Check if a face in NDC is outside the clip space
 // Check if a face in NDC is outside the clip space
-bool isFaceOutsideClipSpace(in Vec2 posNdc[3])
+Bool isFaceOutsideClipSpace(in Vec2 posNdc[3])
 {
 {
 	return any(bvec3(posOutsideClipSpace(posNdc[0]), posOutsideClipSpace(posNdc[1]), posOutsideClipSpace(posNdc[2])));
 	return any(bvec3(posOutsideClipSpace(posNdc[0]), posOutsideClipSpace(posNdc[1]), posOutsideClipSpace(posNdc[2])));
 }
 }
 
 
 // Check if a face is visible
 // Check if a face is visible
-bool isFaceVisible(in Mat4 mvp)
+Bool isFaceVisible(in Mat4 mvp)
 {
 {
 	// Calculate clip positions
 	// Calculate clip positions
 	Vec2 clip[3];
 	Vec2 clip[3];

+ 8 - 11
shaders/Irradiance.ankiprog

@@ -20,8 +20,6 @@ http://www.anki3d.org/LICENSE
 
 
 			<source><![CDATA[
 			<source><![CDATA[
 // Compute the irradiance given an environment map
 // Compute the irradiance given an environment map
-// It's almost the same as http://www.codinglabs.net/article_physically_based_rendering.aspx
-// It's more bright though
 
 
 #include <shaders/Functions.glsl>
 #include <shaders/Functions.glsl>
 
 
@@ -47,31 +45,30 @@ void main()
 	Vec3 ri = getCubemapDirection(UV_TO_NDC(in_uv), face);
 	Vec3 ri = getCubemapDirection(UV_TO_NDC(in_uv), face);
 
 
 	Vec3 outCol = Vec3(0.0);
 	Vec3 outCol = Vec3(0.0);
-	F32 weight = EPSILON;
 
 
 	// For all the faces and texels of the environment map calculate a color sum
 	// For all the faces and texels of the environment map calculate a color sum
-	for(U32 f = 0u; f < 6u; ++f)
+	ANKI_LOOP for(U32 f = 0u; f < 6u; ++f)
 	{
 	{
-		for(U32 i = 0u; i < ENV_TEX_TILE_SIZE; ++i)
+		ANKI_LOOP for(U32 i = 0u; i < ENV_TEX_TILE_SIZE; ++i)
 		{
 		{
-			for(U32 j = 0u; j < ENV_TEX_TILE_SIZE; ++j)
+			ANKI_LOOP for(U32 j = 0u; j < ENV_TEX_TILE_SIZE; ++j)
 			{
 			{
 				Vec2 uv = Vec2(j, i) / F32(ENV_TEX_TILE_SIZE);
 				Vec2 uv = Vec2(j, i) / F32(ENV_TEX_TILE_SIZE);
-				Vec3 r = getCubemapDirection(UV_TO_NDC(uv), f);
+				Vec2 ndc = UV_TO_NDC(uv);
 
 
+				Vec3 r = getCubemapDirection(ndc, f);
 				F32 lambert = dot(r, ri);
 				F32 lambert = dot(r, ri);
+				
 				if(lambert > 0.0)
 				if(lambert > 0.0)
 				{
 				{
 					Vec3 col = textureLod(u_envTex, Vec4(r, texArrIdx), ENV_TEX_MIP).rgb;
 					Vec3 col = textureLod(u_envTex, Vec4(r, texArrIdx), ENV_TEX_MIP).rgb;
-
-					outCol += col * lambert;
-					weight += lambert;
+					outCol += col * lambert * cubeCoordSolidAngle(ndc, F32(ENV_TEX_TILE_SIZE));
 				}
 				}
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	out_color = outCol / weight * PI;
+	out_color = outCol / PI;
 }
 }
 			]]></source>
 			]]></source>
 		</shader>
 		</shader>

+ 4 - 4
shaders/Reflections.ankiprog

@@ -119,7 +119,7 @@ Vec4 doSslr(Vec3 r, Vec3 n, Vec3 viewPos, Vec2 uv, F32 depth, F32 roughness)
 	U32 step = STEPS_ARR[l * 2u + j];
 	U32 step = STEPS_ARR[l * 2u + j];
 	
 	
 	// Iterate
 	// Iterate
-	bool found = false;
+	Bool found = false;
 	Vec3 raySample;
 	Vec3 raySample;
 	ANKI_LOOP for(U32 iterations = 0u; iterations < MAX_STEPS; ++iterations)
 	ANKI_LOOP for(U32 iterations = 0u; iterations < MAX_STEPS; ++iterations)
 	{
 	{
@@ -133,7 +133,7 @@ Vec4 doSslr(Vec3 r, Vec3 n, Vec3 viewPos, Vec2 uv, F32 depth, F32 roughness)
 
 
 		F32 depth = textureLod(u_hizRt, raySample.xy, 0.0).r;
 		F32 depth = textureLod(u_hizRt, raySample.xy, 0.0).r;
 
 
-		bool hit = raySample.z - depth >= 0.0;
+		Bool hit = raySample.z - depth >= 0.0;
 		if(!hit)
 		if(!hit)
 		{
 		{
 			step += stepSkip;
 			step += stepSkip;
@@ -309,9 +309,9 @@ void main()
 	storePixel.y = fixedInvocationId.y;
 	storePixel.y = fixedInvocationId.y;
 
 
 #if VARIANT == 0
 #if VARIANT == 0
-	bool pickRightNeighbour = (fixedInvocationId.y & 1) == 1;
+	Bool pickRightNeighbour = (fixedInvocationId.y & 1) == 1;
 #else
 #else
-	bool pickRightNeighbour = (fixedInvocationId.y & 1) == 0;
+	Bool pickRightNeighbour = (fixedInvocationId.y & 1) == 0;
 #endif
 #endif
 	I32 xOffset = (pickRightNeighbour) ? 1 : -1;
 	I32 xOffset = (pickRightNeighbour) ? 1 : -1;
 	
 	

+ 1 - 1
shaders/SceneDebug.ankiprog

@@ -74,7 +74,7 @@ void main()
 #if DITHERED_DEPTH_TEST == 1
 #if DITHERED_DEPTH_TEST == 1
 	Vec2 uv = gl_FragCoord.xy / Vec2(textureSize(u_depthRt, 0));
 	Vec2 uv = gl_FragCoord.xy / Vec2(textureSize(u_depthRt, 0));
 	F32 depthRef = textureLod(u_depthRt, uv, 0.0).r;
 	F32 depthRef = textureLod(u_depthRt, uv, 0.0).r;
-	bool depthTestFailed = gl_FragCoord.z >= depthRef;
+	Bool depthTestFailed = gl_FragCoord.z >= depthRef;
 	IVec2 fragCoordi = IVec2(gl_FragCoord.xy);
 	IVec2 fragCoordi = IVec2(gl_FragCoord.xy);
 	if(depthTestFailed && ((fragCoordi.x + fragCoordi.y) % 8) != 0)
 	if(depthTestFailed && ((fragCoordi.x + fragCoordi.y) % 8) != 0)
 	{
 	{

+ 2 - 0
src/anki/gr/ShaderCompiler.cpp

@@ -89,6 +89,8 @@ static const char* SHADER_HEADER = R"(#version 450 core
 #define Mat4 mat4
 #define Mat4 mat4
 #define Mat3x4 mat3x4
 #define Mat3x4 mat3x4
 
 
+#define Bool bool
+
 %s)";
 %s)";
 
 
 static EShLanguage ankiToGlslangShaderType(ShaderType shaderType)
 static EShLanguage ankiToGlslangShaderType(ShaderType shaderType)