#define STEPS 250 struct BlackHoleProperties { float Mass; // Mass of the Black Hole. float EventHorizon; // Black Hole Radius, Mass * 2 }; // Position of Blackhole assumed to be at the Origin bool CrossedEventHorizon(float3 RayPos, BlackHoleProperties BHP) { if (length(RayPos) <= BHP.EventHorizon) { return true; } return false; } float Cross2(float3 A, float3 B) { return pow((A.y * B.z) - (A.z * B.y), 2) + pow((A.z * B.x) - (A.x * B.z), 2) + pow((A.x * B.y) - (A.y * B.x), 2); } float3 GravityForce(float3 RayPos, float3 RayDir, BlackHoleProperties BHP) { RayDir = normalize(RayDir); float DistToSingularity = length(RayPos); float SquareDistance = DistToSingularity * DistToSingularity + 0.0001; // Prevent Divide by Zero float3 SingularityToPos = normalize(RayPos); return (-3.0 * BHP.Mass) / SquareDistance * Cross2(SingularityToPos, RayDir) * SingularityToPos; } void BlackHole(inout float4 Color, inout float Mask, inout float3 Dir, float3 CameraPosition, BlackHoleProperties BHP) { float3 RayPos = CameraPosition; float3 RayDir = Dir; float3 PrevPos; //Begin Ray Marching for (int i = 0; i < STEPS; i++) { if (CrossedEventHorizon(RayPos, BHP)) { Mask = 0; break; } PrevPos = RayPos; RayPos += RayDir + GravityForce(RayPos, RayDir, BHP); RayDir = normalize(RayPos - PrevPos); } Dir = RayDir; }