forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			158 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			158 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | // Linearly Transformed Cosines | ||
|  | // https://eheitzresearch.wordpress.com/415-2/ | ||
|  | 
 | ||
|  | const float LUT_SIZE = 64.0; | ||
|  | const float LUT_SCALE = (LUT_SIZE - 1.0) / LUT_SIZE; | ||
|  | const float LUT_BIAS = 0.5 / LUT_SIZE; | ||
|  | 
 | ||
|  | vec3 L0; | ||
|  | vec3 L1; | ||
|  | vec3 L2; | ||
|  | vec3 L3; | ||
|  | vec3 L4; | ||
|  | 
 | ||
|  | float integrateEdge(vec3 v1, vec3 v2) { | ||
|  | 	float cosTheta = dot(v1, v2); | ||
|  | 	float theta = acos(cosTheta);     | ||
|  | 	float res = cross(v1, v2).z * ((theta > 0.001) ? theta / sin(theta) : 1.0); | ||
|  | 	return res; | ||
|  | } | ||
|  | 
 | ||
|  | int clipQuadToHorizon(/*inout vec3 L[5], out int n*/) { | ||
|  | 	int n = 0; | ||
|  | 	// Detect clipping config | ||
|  | 	int config = 0; | ||
|  | 	if (L0.z > 0.0) config += 1; | ||
|  | 	if (L1.z > 0.0) config += 2; | ||
|  | 	if (L2.z > 0.0) config += 4; | ||
|  | 	if (L3.z > 0.0) config += 8; | ||
|  | 
 | ||
|  | 	// Clip | ||
|  | 	if (config == 0) { | ||
|  | 		// Clip all | ||
|  | 	} | ||
|  | 	else if (config == 1) { // V1 clip V2 V3 V4 | ||
|  | 		n = 3; | ||
|  | 		L1 = -L1.z * L0 + L0.z * L1; | ||
|  | 		L2 = -L3.z * L0 + L0.z * L3; | ||
|  | 	} | ||
|  | 	else if (config == 2) { // V2 clip V1 V3 V4 | ||
|  | 		n = 3; | ||
|  | 		L0 = -L0.z * L1 + L1.z * L0; | ||
|  | 		L2 = -L2.z * L1 + L1.z * L2; | ||
|  | 	} | ||
|  | 	else if (config == 3) { // V1 V2 clip V3 V4 | ||
|  | 		n = 4; | ||
|  | 		L2 = -L2.z * L1 + L1.z * L2; | ||
|  | 		L3 = -L3.z * L0 + L0.z * L3; | ||
|  | 	} | ||
|  | 	else if (config == 4) { // V3 clip V1 V2 V4 | ||
|  | 		n = 3; | ||
|  | 		L0 = -L3.z * L2 + L2.z * L3; | ||
|  | 		L1 = -L1.z * L2 + L2.z * L1; | ||
|  | 	} | ||
|  | 	else if (config == 5) { // V1 V3 clip V2 V4) impossible | ||
|  | 		n = 0; | ||
|  | 	} | ||
|  | 	else if (config == 6) { // V2 V3 clip V1 V4 | ||
|  | 		n = 4; | ||
|  | 		L0 = -L0.z * L1 + L1.z * L0; | ||
|  | 		L3 = -L3.z * L2 + L2.z * L3; | ||
|  | 	} | ||
|  | 	else if (config == 7) { // V1 V2 V3 clip V4 | ||
|  | 		n = 5; | ||
|  | 		L4 = -L3.z * L0 + L0.z * L3; | ||
|  | 		L3 = -L3.z * L2 + L2.z * L3; | ||
|  | 	} | ||
|  | 	else if (config == 8) { // V4 clip V1 V2 V3 | ||
|  | 		n = 3; | ||
|  | 		L0 = -L0.z * L3 + L3.z * L0; | ||
|  | 		L1 = -L2.z * L3 + L3.z * L2; | ||
|  | 		L2 =  L3; | ||
|  | 	} | ||
|  | 	else if (config == 9) { // V1 V4 clip V2 V3 | ||
|  | 		n = 4; | ||
|  | 		L1 = -L1.z * L0 + L0.z * L1; | ||
|  | 		L2 = -L2.z * L3 + L3.z * L2; | ||
|  | 	} | ||
|  | 	else if (config == 10) { // V2 V4 clip V1 V3) impossible | ||
|  | 		n = 0; | ||
|  | 	} | ||
|  | 	else if (config == 11) { // V1 V2 V4 clip V3 | ||
|  | 		n = 5; | ||
|  | 		L4 = L3; | ||
|  | 		L3 = -L2.z * L3 + L3.z * L2; | ||
|  | 		L2 = -L2.z * L1 + L1.z * L2; | ||
|  | 	} | ||
|  | 	else if (config == 12) { // V3 V4 clip V1 V2 | ||
|  | 		n = 4; | ||
|  | 		L1 = -L1.z * L2 + L2.z * L1; | ||
|  | 		L0 = -L0.z * L3 + L3.z * L0; | ||
|  | 	} | ||
|  | 	else if (config == 13) { // V1 V3 V4 clip V2 | ||
|  | 		n = 5; | ||
|  | 		L4 = L3; | ||
|  | 		L3 = L2; | ||
|  | 		L2 = -L1.z * L2 + L2.z * L1; | ||
|  | 		L1 = -L1.z * L0 + L0.z * L1; | ||
|  | 	} | ||
|  | 	else if (config == 14) { // V2 V3 V4 clip V1 | ||
|  | 		n = 5; | ||
|  | 		L4 = -L0.z * L3 + L3.z * L0; | ||
|  | 		L0 = -L0.z * L1 + L1.z * L0; | ||
|  | 	} | ||
|  | 	else if (config == 15) { // V1 V2 V3 V4 | ||
|  | 		n = 4; | ||
|  | 	} | ||
|  | 	 | ||
|  | 	if (n == 3) L3 = L0; | ||
|  | 	if (n == 4) L4 = L0; | ||
|  | 	return n; | ||
|  | } | ||
|  | 
 | ||
|  | float ltcEvaluate(vec3 N, vec3 V, float dotNV, vec3 P, mat3 Minv, vec3 points0, vec3 points1, vec3 points2, vec3 points3) { | ||
|  | 	// Construct orthonormal basis around N | ||
|  | 	vec3 T1, T2; | ||
|  | 	T1 = normalize(V - N * dotNV); | ||
|  | 	T2 = cross(N, T1); | ||
|  | 
 | ||
|  | 	// Rotate area light in (T1, T2, R) basis | ||
|  | 	Minv = Minv * transpose(mat3(T1, T2, N)); | ||
|  | 
 | ||
|  | 	// Polygon (allocate 5 vertices for clipping) | ||
|  | 	// vec3 L[5]; | ||
|  | 	L0 = Minv * (points0 - P); | ||
|  | 	L1 = Minv * (points1 - P); | ||
|  | 	L2 = Minv * (points2 - P); | ||
|  | 	L3 = Minv * (points3 - P); | ||
|  | 	L4 = vec3(0.0); | ||
|  | 
 | ||
|  | 	// int n; | ||
|  | 	int n = clipQuadToHorizon(/*L, n*/); | ||
|  | 	 | ||
|  | 	if (n == 0) return 0.0; | ||
|  | 
 | ||
|  | 	// Project onto sphere | ||
|  | 	L0 = normalize(L0); | ||
|  | 	L1 = normalize(L1); | ||
|  | 	L2 = normalize(L2); | ||
|  | 	L3 = normalize(L3); | ||
|  | 	L4 = normalize(L4); | ||
|  | 
 | ||
|  | 	// Integrate | ||
|  | 	float sum = 0.0; | ||
|  | 
 | ||
|  | 	sum += integrateEdge(L0, L1); | ||
|  | 	sum += integrateEdge(L1, L2); | ||
|  | 	sum += integrateEdge(L2, L3); | ||
|  | 	 | ||
|  | 	if (n >= 4) sum += integrateEdge(L3, L4); | ||
|  | 	if (n == 5) sum += integrateEdge(L4, L0); | ||
|  | 
 | ||
|  | #ifdef _TwoSidedAreaLight | ||
|  | 	return abs(sum); | ||
|  | #else | ||
|  | 	return max(0.0, -sum); | ||
|  | #endif | ||
|  | } |