Browse Source

Add some code to compute irradiance in SH

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
2545752e27
1 changed files with 130 additions and 0 deletions
  1. 130 0
      programs/IrradianceSH.ankiprog

+ 130 - 0
programs/IrradianceSH.ankiprog

@@ -0,0 +1,130 @@
+<!-- 
+Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+All rights reserved.
+Code licensed under the BSD License.
+http://www.anki3d.org/LICENSE
+-->
+<shaderProgram>
+	<shaders>
+		<shader type="comp">
+			<inputs>
+				<input name="WORKGROUP_SIZE" type="uvec2" const="1"/>
+			</inputs>
+
+			<source><![CDATA[
+#include "shaders/Functions.glsl"
+
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+
+layout(ANKI_UBO_BINDING(0, 0)) uniform u0_
+{
+	vec4 u_layerPad3;
+};
+#define u_layer u_layerPad3.x
+
+layout(ANKI_TEX_BINDING(0, 0)) uniform samplerCubeArray u_envTex;
+
+#define SHCoefficients vec4
+#define y00 x // Y l=0 m=0
+#define y1n1 y // Y l=1 m=-1
+#define y10 z  // Y l=1 m=0
+#define y11 w  // Y l=1 m=1
+
+layout(std140, ANKI_SS_BINDING(0, 0)) writeonly buffer _s0
+{
+	vec4 u_SHr;
+	vec4 u_SHg;
+	vec4 u_SHb;
+};
+
+shared SHCoefficients s_scratch[3][WORKGROUP_SIZE.y * WORKGROUP_SIZE.x];
+
+SHCoefficients computeSHCoeffiecients(vec3 dir)
+{
+	const float A = 0.282095;
+	const float B = 0.488603;
+
+	SHCoefficients sh;
+	sh.y00 = A;
+	sh.y1n1 = B * dir.y;
+	sh.y10 = B * dir.z;
+	sh.y11 = B * dir.x;
+	return sh;
+}
+
+// Resolve the cube faces
+void initPass()
+{
+	vec2 ndc = UV_TO_NDC(vec2(gl_LocalInvocationID.xy) / vec2(WORKGROUP_SIZE));
+
+	SHCoefficients SHr = SHCoefficients(0.0);
+	SHCoefficients SHg = SHCoefficients(0.0);
+	SHCoefficients SHb = SHCoefficients(0.0);
+
+	float weight = EPSILON;
+
+	ANKI_LOOP for(uint face = 0u; face < 6u; ++face)
+	{
+		vec3 direction = getCubemapDirection(ndc, face);
+
+		SHCoefficients sh = computeSHCoeffiecients(direction);
+		
+		float lambert = max(0.0, dot(r, ri));
+		weight += lambert;
+
+		vec3 rgb = textureLod(u_envTex, vec4(direction, u_layer), 0.0).rgb;
+		rgb *= lambert;
+
+		SHr += rgb.r * sh;
+		SHg += rgb.g * sh;
+		SHb += rgb.b * sh;
+	}
+
+	uint idx = gl_LocalInvocationID.y * WORKGROUP_SIZE.x + gl_LocalInvocationID.x;
+	s_scratch[0][idx] = SHr / weight * PI;
+	s_scratch[1][idx] = SHg / weight * PI;
+	s_scratch[2][idx] = SHb / weight * PI;
+
+	memoryBarrierShared();
+	barrier();
+}
+
+// Reduce the result to a single vec4 per color component
+void reducePasses()
+{
+	// Gather the results into one
+	for(uint s = WORKGROUP_SIZE / 2u; s > 0u; s >>= 1u)
+	{
+		if(gl_LocalInvocationIndex < s)
+		{
+			s_scratch[0][gl_LocalInvocationIndex] += s_scratch[0][gl_LocalInvocationIndex + s];
+			s_scratch[1][gl_LocalInvocationIndex] += s_scratch[1][gl_LocalInvocationIndex + s];
+			s_scratch[2][gl_LocalInvocationIndex] += s_scratch[2][gl_LocalInvocationIndex + s];
+		}
+
+		memoryBarrierShared();
+		barrier();
+	}
+}
+
+// Compute the final result
+void resolvePass()
+{
+	if(gl_LocalInvocationIndex == 0)
+	{
+		u_SHr = s_scratch[0][0];
+		u_SHg = s_scratch[1][0];
+		u_SHb = s_scratch[2][0];
+	}
+}
+
+void main()
+{
+	initPass();
+	reducePasses();
+	resolvePass();
+}
+			]]></source>
+		</shader>
+	</shaders>
+</shaderProgram>