|
|
|
|
|
|
// return furthest near intersection in x and closest far intersection in y |
|
|
|
// if (intersections.y > intersections.x) the ray hit the box, else it miss it |
|
|
|
// Assume dir is normalize |
|
|
|
real2 BoxRayIntersect(real3 start, real3 dir, real3 boxMin, real3 boxMax) |
|
|
|
float2 BoxRayIntersect(float3 start, float3 dir, float3 boxMin, float3 boxMax) |
|
|
|
real3 invDir = 1.0 / dir; |
|
|
|
float3 invDir = 1.0 / dir; |
|
|
|
real3 firstPlaneIntersect = (boxMin - start) * invDir; |
|
|
|
real3 secondPlaneIntersect = (boxMax - start) * invDir; |
|
|
|
float3 firstPlaneIntersect = (boxMin - start) * invDir; |
|
|
|
float3 secondPlaneIntersect = (boxMax - start) * invDir; |
|
|
|
real3 closestPlane = min(firstPlaneIntersect, secondPlaneIntersect); |
|
|
|
real3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect); |
|
|
|
float3 closestPlane = min(firstPlaneIntersect, secondPlaneIntersect); |
|
|
|
float3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect); |
|
|
|
real2 intersections; |
|
|
|
float2 intersections; |
|
|
|
// Find the furthest near intersection |
|
|
|
intersections.x = max(closestPlane.x, max(closestPlane.y, closestPlane.z)); |
|
|
|
// Find the closest far intersection |
|
|
|
|
|
|
|
|
|
|
// This simplified version assume that we care about the result only when we are inside the box |
|
|
|
// Assume dir is normalize |
|
|
|
real BoxRayIntersectSimple(real3 start, real3 dir, real3 boxMin, real3 boxMax) |
|
|
|
float BoxRayIntersectSimple(float3 start, float3 dir, float3 boxMin, float3 boxMax) |
|
|
|
real3 invDir = 1.0 / dir; |
|
|
|
float3 invDir = 1.0 / dir; |
|
|
|
real3 rbmin = (boxMin - start) * invDir; |
|
|
|
real3 rbmax = (boxMax - start) * invDir; |
|
|
|
float3 rbmin = (boxMin - start) * invDir; |
|
|
|
float3 rbmax = (boxMax - start) * invDir; |
|
|
|
real3 rbminmax = (dir > 0.0) ? rbmax : rbmin; |
|
|
|
float3 rbminmax = (dir > 0.0) ? rbmax : rbmin; |
|
|
|
real2 SphereRayIntersect(real3 start, real3 dir, real radius, out bool intersect) |
|
|
|
float2 SphereRayIntersect(float3 start, float3 dir, float radius, out bool intersect) |
|
|
|
real a = dot(dir, dir); |
|
|
|
real b = dot(dir, start) * 2.0; |
|
|
|
real c = dot(start, start) - radius * radius; |
|
|
|
real discriminant = b * b - 4.0 * a * c; |
|
|
|
float a = dot(dir, dir); |
|
|
|
float b = dot(dir, start) * 2.0; |
|
|
|
float c = dot(start, start) - radius * radius; |
|
|
|
float discriminant = b * b - 4.0 * a * c; |
|
|
|
real2 intersections = real2(0.0, 0.0); |
|
|
|
float2 intersections = float2(0.0, 0.0); |
|
|
|
intersect = false; |
|
|
|
if (discriminant < 0.0 || a == 0.0) |
|
|
|
{ |
|
|
|
|
|
|
else |
|
|
|
{ |
|
|
|
real sqrtDiscriminant = sqrt(discriminant); |
|
|
|
float sqrtDiscriminant = sqrt(discriminant); |
|
|
|
intersections.x = (-b - sqrtDiscriminant) / (2.0 * a); |
|
|
|
intersections.y = (-b + sqrtDiscriminant) / (2.0 * a); |
|
|
|
intersect = true; |
|
|
|
|
|
|
// This simplified version assume that we care about the result only when we are inside the sphere |
|
|
|
// Assume Sphere is at the origin (i.e start = position - spherePosition) and dir is normalized |
|
|
|
// Ref: http://http.developer.nvidia.com/GPUGems/gpugems_ch19.html |
|
|
|
real SphereRayIntersectSimple(real3 start, real3 dir, real radius) |
|
|
|
float SphereRayIntersectSimple(float3 start, float3 dir, float radius) |
|
|
|
real b = dot(dir, start) * 2.0; |
|
|
|
real c = dot(start, start) - radius * radius; |
|
|
|
real discriminant = b * b - 4.0 * c; |
|
|
|
float b = dot(dir, start) * 2.0; |
|
|
|
float c = dot(start, start) - radius * radius; |
|
|
|
float discriminant = b * b - 4.0 * c; |
|
|
|
real3 RayPlaneIntersect(in real3 rayOrigin, in real3 rayDirection, in real3 planeOrigin, in real3 planeNormal) |
|
|
|
float3 RayPlaneIntersect(in float3 rayOrigin, in float3 rayDirection, in float3 planeOrigin, in float3 planeNormal) |
|
|
|
real dist = dot(planeNormal, planeOrigin - rayOrigin) / dot(planeNormal, rayDirection); |
|
|
|
float dist = dot(planeNormal, planeOrigin - rayOrigin) / dot(planeNormal, rayDirection); |
|
|
|
return rayOrigin + rayDirection * dist; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Box is AABB |
|
|
|
real DistancePointBox(real3 position, real3 boxMin, real3 boxMax) |
|
|
|
float DistancePointBox(float3 position, float3 boxMin, float3 boxMax) |
|
|
|
return length(max(max(position - boxMax, boxMin - position), real3(0.0, 0.0, 0.0))); |
|
|
|
return length(max(max(position - boxMax, boxMin - position), float3(0.0, 0.0, 0.0))); |
|
|
|
real3 ProjectPointOnPlane(real3 position, real3 planePosition, real3 planeNormal) |
|
|
|
float3 ProjectPointOnPlane(float3 position, float3 planePosition, float3 planeNormal) |
|
|
|
{ |
|
|
|
return position - (dot(position - planePosition, planeNormal) * planeNormal); |
|
|
|
} |
|
|
|
|
|
|
// Positive -> in front (above), negative -> behind (below). |
|
|
|
real DistanceFromPlane(real3 p, real4 plane) |
|
|
|
float DistanceFromPlane(float3 p, float3 plane) |
|
|
|
return dot(real4(p, 1.0), plane); |
|
|
|
return dot(float4(p, 1.0), plane); |
|
|
|
bool CullTriangleFrustum(real3 p0, real3 p1, real3 p2, real epsilon, real4 frustumPlanes[6], int numPlanes) |
|
|
|
bool CullTriangleFrustum(float3 p0, float3 p1, float3 p2, float epsilon, float4 frustumPlanes[6], int numPlanes) |
|
|
|
{ |
|
|
|
bool outside = false; |
|
|
|
|
|
|
|
|
|
|
// Returns 'true' if the edge of the triangle is outside of the frustum. |
|
|
|
// The edges are defined s.t. they are on the opposite side of the point with the given index. |
|
|
|
// 'epsilon' is the (negative) distance to (outside of) the frustum below which we cull the triangle. |
|
|
|
bool3 CullTriangleEdgesFrustum(real3 p0, real3 p1, real3 p2, real epsilon, real4 frustumPlanes[6], int numPlanes) |
|
|
|
bool3 CullTriangleEdgesFrustum(float3 p0, float3 p1, float3 p2, float epsilon, float4 frustumPlanes[6], int numPlanes) |
|
|
|
{ |
|
|
|
bool3 edgesOutside = false; |
|
|
|
|
|
|
|
|
|
|
// Returns 'true' if a triangle defined by 3 vertices is back-facing. |
|
|
|
// 'epsilon' is the (negative) value of dot(N, V) below which we cull the triangle. |
|
|
|
// 'winding' can be used to change the order: pass 1 for (p0 -> p1 -> p2), or -1 for (p0 -> p2 -> p1). |
|
|
|
bool CullTriangleBackFace(real3 p0, real3 p1, real3 p2, real epsilon, real3 viewPos, real winding) |
|
|
|
bool CullTriangleBackFace(float3 p0, float3 p1, float3 p2, float epsilon, float3 viewPos, float winding) |
|
|
|
real3 edge1 = p1 - p0; |
|
|
|
real3 edge2 = p2 - p0; |
|
|
|
float3 edge1 = p1 - p0; |
|
|
|
float3 edge2 = p2 - p0; |
|
|
|
real3 N = cross(edge1, edge2); |
|
|
|
real3 V = viewPos - p0; |
|
|
|
real NdotV = dot(N, V) * winding; |
|
|
|
float3 N = cross(edge1, edge2); |
|
|
|
float3 V = viewPos - p0; |
|
|
|
float NdotV = dot(N, V) * winding; |
|
|
|
|
|
|
|
// Optimize: |
|
|
|
// NdotV / (length(N) * length(V)) < Epsilon |
|
|
|