16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 07:49:19 +02:00
Files
maszyna/betterRenderer/shaders/manul/forward_plus/primitives.hlsli
2025-04-15 01:32:56 +02:00

259 lines
7.8 KiB
HLSL

// Partially stolen from https://www.3dgep.com/forward-plus/
#ifndef FORWARD_PLUS_PRIMITIVES_HLSLI
#define FORWARD_PLUS_PRIMITIVES_HLSLI
/* ---------------------------------------------------------------------------------------------- */
/* Plane */
/* ---------------------------------------------------------------------------------------------- */
struct Plane
{
float3 N; // Plane normal.
float d; // Distance to origin.
};
// Compute a plane from 3 noncollinear points that form a triangle.
// This equation assumes a right-handed (counter-clockwise winding order)
// coordinate system to determine the direction of the plane normal.
Plane ComputePlane( float3 p0, float3 p1, float3 p2 )
{
Plane plane;
float3 v0 = p1 - p0;
float3 v2 = p2 - p0;
plane.N = normalize( cross( v0, v2 ) );
// Compute the distance to the origin using p0.
plane.d = dot( plane.N, p0 );
return plane;
}
// Check to see if a point is fully behind (inside the negative halfspace of) a plane.
bool PointInsidePlane( float3 p, Plane plane )
{
return dot( plane.N, p ) - plane.d < 0;
}
/* ---------------------------------------------------------------------------------------------- */
/* Frustum */
/* ---------------------------------------------------------------------------------------------- */
struct ConeFrustum
{
float3 m_origin;
float m_cos_angle;
float3 m_direction;
float m_sin_angle;
float m_cos_angle_sqr;
float m_inv_sin_angle;
};
ConeFrustum ComputeConeFrustum(in float3 origin, in float3 direction, in float cos_angle) {
ConeFrustum cone;
cone.m_origin = origin;
cone.m_direction = direction;
cone.m_cos_angle = cos_angle;
cone.m_cos_angle_sqr = cos_angle * cos_angle;
cone.m_sin_angle = sqrt(1. - saturate(cone.m_cos_angle_sqr));
cone.m_inv_sin_angle = 1. / cone.m_sin_angle;
return cone;
}
// Four planes of a view frustum (in view space).
// The planes are:
// * Left,
// * Right,
// * Top,
// * Bottom.
// The back and/or front planes can be computed from depth values in the
// light culling compute shader.
struct Frustum
{
Plane planes[4]; // left, right, top, bottom frustum planes.
float3 m_view_ray;
float m_tan_frustum_angle;
};
/* ---------------------------------------------------------------------------------------------- */
/* Sphere */
/* ---------------------------------------------------------------------------------------------- */
struct Sphere
{
float3 m_origin; // Center point.
float m_radius; // Radius.
};
// Check to see if a sphere is fully behind (inside the negative halfspace of) a plane.
// Source: Real-time collision detection, Christer Ericson (2005)
bool SphereInsidePlane( Sphere sphere, Plane plane )
{
return dot( plane.N, sphere.m_origin ) - plane.d < -sphere.m_radius;
}
// Check to see of a light is partially contained within the frustum.
bool SphereInsideFrustum( Sphere sphere, Frustum frustum, float zNear, float zFar )
{
bool result = true;
// First check depth
// Note: Here, the view vector points in the -Z axis so the
// far depth value will be approaching -infinity.
if ( sphere.m_origin.z - sphere.m_radius > zNear || sphere.m_origin.z + sphere.m_radius < zFar )
{
result = false;
}
// Then check frustum planes
for ( int i = 0; i < 4 && result; ++i )
{
if ( SphereInsidePlane( sphere, frustum.planes[i] ) )
{
result = false;
}
}
return result;
}
/* ---------------------------------------------------------------------------------------------- */
/* Cone */
/* ---------------------------------------------------------------------------------------------- */
struct Cone
{
float3 T; // Cone tip.
float h; // Height of the cone.
float3 d; // Direction of the cone.
float r; // bottom radius of the cone.
};
// Check to see if a cone if fully behind (inside the negative halfspace of) a plane.
// Source: Real-time collision detection, Christer Ericson (2005)
bool ConeInsidePlane( Cone cone, Plane plane )
{
// Compute the farthest point on the end of the cone to the positive space of the plane.
float3 m = cross( cross( plane.N, cone.d ), cone.d );
float3 Q = cone.T + cone.d * cone.h - m * cone.r;
// The cone is in the negative halfspace of the plane if both
// the tip of the cone and the farthest point on the end of the cone to the
// positive halfspace of the plane are both inside the negative halfspace
// of the plane.
return PointInsidePlane( cone.T, plane ) && PointInsidePlane( Q, plane );
}
bool ConeInsideFrustum( Cone cone, Frustum frustum, float zNear, float zFar )
{
bool result = true;
Plane nearPlane = { float3( 0, 0, -1 ), -zNear };
Plane farPlane = { float3( 0, 0, 1 ), zFar };
// First check the near and far clipping planes.
if ( ConeInsidePlane( cone, nearPlane ) || ConeInsidePlane( cone, farPlane ) )
{
result = false;
}
// Then check frustum planes
for ( int i = 0; i < 4 && result; ++i )
{
if ( ConeInsidePlane( cone, frustum.planes[i] ) )
{
result = false;
}
}
return result;
}
/* ---------------------------------------------------------------------------------------------- */
/* AABB */
/* ---------------------------------------------------------------------------------------------- */
struct Aabb {
float3 min;
float3 max;
};
float3 GetAabbCorner( Aabb aabb, float4x4 transform, uint index ) {
float3 t = float3(
( index & 1 ) ? 1. : 0.,
( index & 2 ) ? 1. : 0.,
( index & 4 ) ? 1. : 0. );
return mul(
transform,
float4( ( 1. - t ) * aabb.min + t * aabb.max, 1. ) ).xyz;
}
bool AabbInsidePlane( Aabb aabb, float4x4 transform, Plane plane ) {
bool result = true;
for( uint i = 0; i < 8 && result; ++i ) {
result = PointInsidePlane( GetAabbCorner( aabb, transform, i ), plane );
}
return result;
}
bool AabbInsideFrustum( Aabb aabb, float4x4 transform, Frustum frustum, float zNear, float zFar )
{
bool result = true;
Plane nearPlane = { float3( 0, 0, -1 ), -zNear };
Plane farPlane = { float3( 0, 0, 1 ), zFar };
// First check the near and far clipping planes.
if ( AabbInsidePlane( aabb, transform, nearPlane ) || AabbInsidePlane( aabb, transform, farPlane ) )
{
result = false;
}
// Then check frustum planes
for ( int i = 0; i < 4 && result; ++i )
{
if ( AabbInsidePlane( aabb, transform, frustum.planes[i] ) )
{
result = false;
}
}
return result;
}
bool DoQueryInfiniteCone(in Sphere sphere, in ConeFrustum cone)
{
float3 U = cone.m_origin - (sphere.m_radius * cone.m_inv_sin_angle) * cone.m_direction;
float3 CmU = sphere.m_origin - U;
float AdCmU = dot(cone.m_direction, CmU);
if (AdCmU > 0.)
{
float sqrLengthCmU = dot(CmU, CmU);
if (AdCmU * AdCmU >= sqrLengthCmU * cone.m_cos_angle_sqr)
{
float3 CmV = sphere.m_origin - cone.m_origin;
float AdCmV = dot(cone.m_direction, CmV);
if (AdCmV < -sphere.m_radius)
{
return false;
}
float rSinAngle = sphere.m_radius * cone.m_sin_angle;
if (AdCmV >= -rSinAngle)
{
return true;
}
float sqrLengthCmV = dot(CmV, CmV);
return sqrLengthCmV <= sphere.m_radius * sphere.m_radius;
}
}
return false;
}
#endif