mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-01-14 23:11:06 +00:00
176 lines
4.2 KiB
PHP
176 lines
4.2 KiB
PHP
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
|
|
|
mat3 transpose(mat3 v) {
|
|
mat3 tmp;
|
|
tmp[0] = vec3(v[0].x, v[1].x, v[2].x);
|
|
tmp[1] = vec3(v[0].y, v[1].y, v[2].y);
|
|
tmp[2] = vec3(v[0].z, v[1].z, v[2].z);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
void ClipQuadToHorizon(inout vec3 L[5], out int n) {
|
|
// detect clipping config
|
|
int config = 0;
|
|
if (L[0].z > 0.0) config += 1;
|
|
if (L[1].z > 0.0) config += 2;
|
|
if (L[2].z > 0.0) config += 4;
|
|
if (L[3].z > 0.0) config += 8;
|
|
config = 15;
|
|
|
|
// clip
|
|
n = 0;
|
|
|
|
if (config == 0)
|
|
{
|
|
// clip all
|
|
}
|
|
else if (config == 1) // V1 clip V2 V3 V4
|
|
{
|
|
n = 3;
|
|
L[1] = -L[1].z * L[0] + L[0].z * L[1];
|
|
L[2] = -L[3].z * L[0] + L[0].z * L[3];
|
|
}
|
|
else if (config == 2) // V2 clip V1 V3 V4
|
|
{
|
|
n = 3;
|
|
L[0] = -L[0].z * L[1] + L[1].z * L[0];
|
|
L[2] = -L[2].z * L[1] + L[1].z * L[2];
|
|
}
|
|
else if (config == 3) // V1 V2 clip V3 V4
|
|
{
|
|
n = 4;
|
|
L[2] = -L[2].z * L[1] + L[1].z * L[2];
|
|
L[3] = -L[3].z * L[0] + L[0].z * L[3];
|
|
}
|
|
else if (config == 4) // V3 clip V1 V2 V4
|
|
{
|
|
n = 3;
|
|
L[0] = -L[3].z * L[2] + L[2].z * L[3];
|
|
L[1] = -L[1].z * L[2] + L[2].z * L[1];
|
|
}
|
|
else if (config == 5) // V1 V3 clip V2 V4) impossible
|
|
{
|
|
n = 0;
|
|
}
|
|
else if (config == 6) // V2 V3 clip V1 V4
|
|
{
|
|
n = 4;
|
|
L[0] = -L[0].z * L[1] + L[1].z * L[0];
|
|
L[3] = -L[3].z * L[2] + L[2].z * L[3];
|
|
}
|
|
else if (config == 7) // V1 V2 V3 clip V4
|
|
{
|
|
n = 5;
|
|
L[4] = -L[3].z * L[0] + L[0].z * L[3];
|
|
L[3] = -L[3].z * L[2] + L[2].z * L[3];
|
|
}
|
|
else if (config == 8) // V4 clip V1 V2 V3
|
|
{
|
|
n = 3;
|
|
L[0] = -L[0].z * L[3] + L[3].z * L[0];
|
|
L[1] = -L[2].z * L[3] + L[3].z * L[2];
|
|
L[2] = L[3];
|
|
}
|
|
else if (config == 9) // V1 V4 clip V2 V3
|
|
{
|
|
n = 4;
|
|
L[1] = -L[1].z * L[0] + L[0].z * L[1];
|
|
L[2] = -L[2].z * L[3] + L[3].z * L[2];
|
|
}
|
|
else if (config == 10) // V2 V4 clip V1 V3) impossible
|
|
{
|
|
n = 0;
|
|
}
|
|
else if (config == 11) // V1 V2 V4 clip V3
|
|
{
|
|
n = 5;
|
|
L[4] = L[3];
|
|
L[3] = -L[2].z * L[3] + L[3].z * L[2];
|
|
L[2] = -L[2].z * L[1] + L[1].z * L[2];
|
|
}
|
|
else if (config == 12) // V3 V4 clip V1 V2
|
|
{
|
|
n = 4;
|
|
L[1] = -L[1].z * L[2] + L[2].z * L[1];
|
|
L[0] = -L[0].z * L[3] + L[3].z * L[0];
|
|
}
|
|
else if (config == 13) // V1 V3 V4 clip V2
|
|
{
|
|
n = 5;
|
|
L[4] = L[3];
|
|
L[3] = L[2];
|
|
L[2] = -L[1].z * L[2] + L[2].z * L[1];
|
|
L[1] = -L[1].z * L[0] + L[0].z * L[1];
|
|
}
|
|
else if (config == 14) // V2 V3 V4 clip V1
|
|
{
|
|
n = 5;
|
|
L[4] = -L[0].z * L[3] + L[3].z * L[0];
|
|
L[0] = -L[0].z * L[1] + L[1].z * L[0];
|
|
}
|
|
else if (config == 15) // V1 V2 V3 V4
|
|
{
|
|
n = 4;
|
|
}
|
|
|
|
if (n == 3)
|
|
L[3] = L[0];
|
|
if (n == 4)
|
|
L[4] = L[0];
|
|
}
|
|
|
|
// https://eheitzresearch.wordpress.com/415-2/
|
|
float IntegrateEdge(vec3 v1, vec3 v2) {
|
|
float cosTheta = dot(v1, v2);
|
|
float theta = acos(cosTheta);
|
|
return cross(v1, v2).z * ((theta > 0.001) ? theta/sin(theta) : 4.0);
|
|
}
|
|
|
|
vec3 LTC_Evaluate(vec3 N, vec3 V, vec3 P, mat3 Minv, vec3 points[4]) {
|
|
// construct orthonormal basis around N
|
|
vec3 T1, T2;
|
|
T1 = normalize(V - N*dot(V, N));
|
|
T2 = cross(N, T1);
|
|
|
|
// rotate area light in (T1, T2, N) basis
|
|
Minv = Minv * transpose(mat3(T1, T2, N));
|
|
|
|
// polygon (allocate 5 vertices for clipping)
|
|
vec3 L[5];
|
|
L[0] = Minv * (points[0] - P);
|
|
L[1] = Minv * (points[1] - P);
|
|
L[2] = Minv * (points[2] - P);
|
|
L[3] = Minv * (points[3] - P);
|
|
|
|
int n;
|
|
ClipQuadToHorizon(L, n);
|
|
|
|
if (n == 0)
|
|
return vec3(0, 0, 0);
|
|
|
|
// project onto sphere
|
|
L[0] = normalize(L[0]);
|
|
L[1] = normalize(L[1]);
|
|
L[2] = normalize(L[2]);
|
|
L[3] = normalize(L[3]);
|
|
L[4] = normalize(L[4]);
|
|
|
|
// integrate
|
|
float sum = 0.0;
|
|
|
|
sum += IntegrateEdge(L[0], L[1]);
|
|
sum += IntegrateEdge(L[1], L[2]);
|
|
sum += IntegrateEdge(L[2], L[3]);
|
|
if (n >= 4)
|
|
sum += IntegrateEdge(L[3], L[4]);
|
|
if (n == 5)
|
|
sum += IntegrateEdge(L[4], L[0]);
|
|
|
|
sum = max(0.0, sum);
|
|
|
|
vec3 Lo_i = vec3(sum, sum, sum);
|
|
|
|
return Lo_i;
|
|
}
|