You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

107 lines
3.2 KiB

// I am not sure why exactly, by a lower epsilon generates ray that even if they give a valid result with ray tracing
// nuke the performance. Changing the epsilon from 1e-6 to 1e-5 seems to solve the issue.
#define PLANE_INTERSECTION_EPSILON 1e-5
bool IntersectPlane(float3 ray_origin, float3 ray_dir, float3 pos, float3 normal, out float t)
{
t = -1.0f;
float denom = dot(normal, ray_dir);
if (abs(denom) > PLANE_INTERSECTION_EPSILON)
{
float3 d = pos - ray_origin;
t = dot(d, normal) / denom;
return (t >= 0);
}
return false;
}
struct SphQuad
{
float3 o, x, y, z;
float z0, z0sq;
float x0, y0, y0sq;
float x1, y1, y1sq;
float b0, b1, b0sq, k;
float S;
};
void SphQuadInit(float3 s, float3 ex, float3 ey, float3 o, out SphQuad squad)
{
squad.o = o;
float exl = length(ex);
float eyl = length(ey);
// compute local reference system 'R'
squad.x = ex / exl;
squad.y = ey / eyl;
squad.z = cross(squad.x, squad.y);
// compute rectangle coords in local reference system
float3 d = s - o;
squad.z0 = dot(d, squad.z);
// flip 'z' to make it point against 'Q'
if (squad.z0 > 0.0f) {
squad.z = -squad.z;
squad.z0 = -squad.z0;
}
squad.z0sq = squad.z0 * squad.z0;
squad.x0 = dot(d, squad.x);
squad.y0 = dot(d, squad.y);
squad.x1 = squad.x0 + exl;
squad.y1 = squad.y0 + eyl;
squad.y0sq = squad.y0 * squad.y0;
squad.y1sq = squad.y1 * squad.y1;
// create vectors to four vertices
float3 v00 = float3(squad.x0, squad.y0, squad.z0);
float3 v01 = float3(squad.x0, squad.y1, squad.z0);
float3 v10 = float3(squad.x1, squad.y0, squad.z0);
float3 v11 = float3(squad.x1, squad.y1, squad.z0);
// compute normals to edges
float3 n0 = normalize(cross(v00, v10));
float3 n1 = normalize(cross(v10, v11));
float3 n2 = normalize(cross(v11, v01));
float3 n3 = normalize(cross(v01, v00));
// compute internal angles (gamma_i)
float g0 = FastACos(-dot(n0, n1));
float g1 = FastACos(-dot(n1, n2));
float g2 = FastACos(-dot(n2, n3));
float g3 = FastACos(-dot(n3, n0));
// compute predefined constants
squad.b0 = n0.z;
squad.b1 = n2.z;
squad.b0sq = squad.b0 * squad.b0;
squad.k = 2.0f * PI - g2 - g3;
// compute solid angle from internal angles
squad.S = g0 + g1 - squad.k;
}
float3 SphQuadSample(SphQuad squad, float u, float v)
{
// 1. compute 'cu'
float au = u * squad.S + squad.k;
float fu = (cos(au) * squad.b0 - squad.b1) / sin(au);
float cu = 1.0f / sqrt(fu*fu + squad.b0sq) * (fu > 0.0f ? 1.0f : -1.0f);
cu = clamp(cu, -1.0f, 1.0f); // avoid NaNs
// 2. compute 'xu'
float xu = -(cu * squad.z0) / sqrt(1.0f - cu * cu);
xu = clamp(xu, squad.x0, squad.x1); // avoid Infs
// 3. compute 'yv'
float d = sqrt(xu * xu + squad.z0sq);
float h0 = squad.y0 / sqrt(d*d + squad.y0sq);
float h1 = squad.y1 / sqrt(d*d + squad.y1sq);
float hv = h0 + v * (h1 - h0), hv2 = hv * hv;
float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrt(1.0f - hv2) : squad.y1;
// 4. transform (xu, yv, z0) to world coords
return squad.o + xu*squad.x + yv*squad.y + squad.z0*squad.z;
}