73 lines
2.7 KiB
HLSL
73 lines
2.7 KiB
HLSL
|
|
static const float PI = 3.14159265359;
|
||
|
|
static const float TAU = PI * 2;
|
||
|
|
static const float maxFloat = 3.402823466e+38;
|
||
|
|
|
||
|
|
// Remap a value from one range to another
|
||
|
|
float remap(float v, float minOld, float maxOld, float minNew, float maxNew) {
|
||
|
|
return saturate(minNew + (v-minOld) * (maxNew - minNew) / (maxOld-minOld));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remap the components of a vector from one range to another
|
||
|
|
float4 remap(float4 v, float minOld, float maxOld, float minNew, float maxNew) {
|
||
|
|
return saturate(minNew + (v-minOld) * (maxNew - minNew) / (maxOld-minOld));//
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remap a float value (with a known mininum and maximum) to a value between 0 and 1
|
||
|
|
float remap01(float v, float minOld, float maxOld) {
|
||
|
|
return saturate((v-minOld) / (maxOld-minOld));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remap a float2 value (with a known mininum and maximum) to a value between 0 and 1
|
||
|
|
float2 remap01(float2 v, float2 minOld, float2 maxOld) {
|
||
|
|
return saturate((v-minOld) / (maxOld-minOld));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Smooth minimum of two values, controlled by smoothing factor k
|
||
|
|
// When k = 0, this behaves identically to min(a, b)
|
||
|
|
float smoothMin(float a, float b, float k) {
|
||
|
|
k = max(0, k);
|
||
|
|
// https://www.iquilezles.org/www/articles/smin/smin.htm
|
||
|
|
float h = max(0, min(1, (b - a + k) / (2 * k)));
|
||
|
|
return a * h + b * (1 - h) - k * h * (1 - h);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Smooth maximum of two values, controlled by smoothing factor k
|
||
|
|
// When k = 0, this behaves identically to max(a, b)
|
||
|
|
float smoothMax(float a, float b, float k) {
|
||
|
|
k = min(0, -k);
|
||
|
|
float h = max(0, min(1, (b - a + k) / (2 * k)));
|
||
|
|
return a * h + b * (1 - h) - k * h * (1 - h);
|
||
|
|
}
|
||
|
|
|
||
|
|
float Blend(float startHeight, float blendDst, float height) {
|
||
|
|
return smoothstep(startHeight - blendDst / 2, startHeight + blendDst / 2, height);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// Returns vector (dstToSphere, dstThroughSphere)
|
||
|
|
// If ray origin is inside sphere, dstToSphere = 0
|
||
|
|
// If ray misses sphere, dstToSphere = maxValue; dstThroughSphere = 0
|
||
|
|
float2 raySphere(float3 sphereCentre, float sphereRadius, float3 rayOrigin, float3 rayDir) {
|
||
|
|
float3 offset = rayOrigin - sphereCentre;
|
||
|
|
float a = 1; // Set to dot(rayDir, rayDir) if rayDir might not be normalized
|
||
|
|
float b = 2 * dot(offset, rayDir);
|
||
|
|
float c = dot (offset, offset) - sphereRadius * sphereRadius;
|
||
|
|
float d = b * b - 4 * a * c; // Discriminant from quadratic formula
|
||
|
|
|
||
|
|
// Number of intersections: 0 when d < 0; 1 when d = 0; 2 when d > 0
|
||
|
|
if (d > 0) {
|
||
|
|
float s = sqrt(d);
|
||
|
|
float dstToSphereNear = max(0, (-b - s) / (2 * a));
|
||
|
|
float dstToSphereFar = (-b + s) / (2 * a);
|
||
|
|
|
||
|
|
// Ignore intersections that occur behind the ray
|
||
|
|
if (dstToSphereFar >= 0) {
|
||
|
|
return float2(dstToSphereNear, dstToSphereFar - dstToSphereNear);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// Ray did not intersect sphere
|
||
|
|
return float2(maxFloat, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|