aboutsummaryrefslogtreecommitdiff
path: root/assets/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'assets/shaders')
-rw-r--r--assets/shaders/equirect_to_cubemap.slang4
-rw-r--r--assets/shaders/geodesic.slang71
-rw-r--r--assets/shaders/grid.slang2
-rw-r--r--assets/shaders/skybox.slang2
-rw-r--r--assets/shaders/sphere.slang2
-rw-r--r--assets/shaders/textured_quad.slang4
-rw-r--r--assets/shaders/vk_pipeline_test.slang4
7 files changed, 47 insertions, 42 deletions
diff --git a/assets/shaders/equirect_to_cubemap.slang b/assets/shaders/equirect_to_cubemap.slang
index 510e6b0..5b4caff 100644
--- a/assets/shaders/equirect_to_cubemap.slang
+++ b/assets/shaders/equirect_to_cubemap.slang
@@ -1,7 +1,7 @@
-// Equirectangular HDRI -> cubemap face projection. NOTE: the OpenGL path uses the
+// equirectangular HDRI -> cubemap face projection. NOTE: the OpenGL path uses the
// hand-written assets/shaders/EquirectToCubemap.glsl instead; this Slang version
// feeds the Vulkan cubemap bake (vulkan_cubemap.cpp), which binds the view /
-// projection as a $Globals UBO. Kept as loose `uniform` globals (not a
+// projection as a $Globals UBO. kept as loose `uniform` globals (not a
// ConstantBuffer) so both paths bind them the same way.
uniform float4x4 u_projection;
diff --git a/assets/shaders/geodesic.slang b/assets/shaders/geodesic.slang
index eb536c9..937674e 100644
--- a/assets/shaders/geodesic.slang
+++ b/assets/shaders/geodesic.slang
@@ -1,8 +1,8 @@
-// Ray-traced Schwarzschild black hole: back-traces one null geodesic per pixel
+// ray-traced Schwarzschild black hole: back-traces one null geodesic per pixel
// through curved spacetime, shading the accretion disk, the lensed HDRI
-// background, and placed objects. Runs as a full-screen fragment pass. Uniforms
+// background, and placed objects. runs as a full-screen fragment pass. uniforms
// live in ConstantBuffers (UBOs) driven through the RHI; the HDRI is a cubemap
-// sampler. See docs/physics.md for the maths.
+// sampler. see docs/physics.md for the maths.
struct VSInput { float2 position : POSITION; float2 texCoord : TEXCOORD0; };
struct VSOutput { float4 position : SV_Position; float2 texCoord : TEXCOORD0; };
@@ -61,7 +61,7 @@ ConstantBuffer<Simulation> sim;
SamplerCube u_HDRIEnvironment;
-// Schwarzschild radius of Sgr A* (metres). Geometric units with c = G = 1 are
+// Schwarzschild radius of Sgr A* (metres). geometric units with c = G = 1 are
// used throughout the geodesic integration; the black-hole mass is M = r_s / 2.
static const float SagA_rs = 1.269e10;
static const float D_LAMBDA = 1e7;
@@ -69,7 +69,7 @@ static const float ESCAPE_R = 1e30;
static const float R_ISCO = 3.0 * SagA_rs; // innermost stable circular orbit (6M)
static const float R_PHOTON = 1.5 * SagA_rs; // photon sphere (3M)
-static const float FLUX_PEAK = 0.0569; // peak of the r^-3(1-sqrt(r_in/r)) profile (at r/r_in ~ 1.36)
+static const float FLUX_PEAK = 0.0569; // peak of the r^-3(1-sqrt(r_in/r)) profile (~r/r_in 1.36); worked it out once, now it's just the normaliser
static const int DEFAULT_MAX_STEPS_MOVING = 12000;
static const int DEFAULT_MAX_STEPS_STATIC = 8000;
@@ -78,8 +78,8 @@ static const float DEFAULT_EARLY_EXIT_DISTANCE = 2e12;
static const float MIN_STEP_SIZE = 1e6;
static const float MAX_STEP_SIZE = 2e10;
-// Display mapping for the (relative) Novikov-Thorne flux -> visible colour.
-// The RADIAL PROFILE is physical; the absolute temperature scale is a display
+// display mapping for the (relative) Novikov-Thorne flux -> visible colour.
+// the RADIAL PROFILE is physical; the absolute temperature scale is a display
// choice (a real Sgr A* disk is far cooler / redder than this).
struct Hit
@@ -91,6 +91,7 @@ struct Hit
float hash(float3 p)
{
+ // magic primes, don't ask — they just scramble bits into a clean 0..1 hash
p = frac(p * float3(0.1031, 0.1030, 0.0973));
p += dot(p, p.yxz + 33.33);
return frac((p.x + p.y) * p.z);
@@ -129,8 +130,10 @@ float fbm(float3 x, int octaves)
return v;
}
-// Planckian-locus blackbody colour (Tanner Helland approximation), T in Kelvin.
-// Returns an sRGB-ish chromaticity normalised so the brightest channel ~ 1.
+// blackbody colour along the Planckian locus, T in Kelvin. it's Tanner Helland's
+// curve fit and the coefficients below are pure magic-number soup — idk exactly
+// how they were derived, so like just trust them. returns an sRGB-ish
+// chromaticity normalised so the brightest channel ~ 1.
float3 Blackbody(float T)
{
T = clamp(T, 1000.0, 40000.0);
@@ -149,11 +152,11 @@ float3 Blackbody(float T)
return c;
}
-// Emission from the thin accretion disk at an equatorial crossing point P, seen
-// along the (backward-traced) ray direction rayDir. Combines a Novikov-Thorne
+// emission from the thin accretion disk at an equatorial crossing point P, seen
+// along the (backward-traced) ray direction rayDir. combines a Novikov-Thorne
// temperature profile with the full gravitational + Doppler redshift.
// g = sqrt(1 - 3M/r) / (1 - beta . nhat) (verified: g -> sqrt(1/2) at ISCO)
-// Brightness follows relativistic beaming (I_obs = g^4 I_emit); colour follows
+// brightness follows relativistic beaming (I_obs = g^4 I_emit); colour follows
// the redshifted blackbody at T_obs = g * T_emit.
float3 DiskEmission(float3 P, float3 rayDir, out float outG, out float outTemit)
{
@@ -171,7 +174,7 @@ float3 DiskEmission(float3 P, float3 rayDir, out float outG, out float outTemit)
float Tn = pow(flux / FLUX_PEAK, 0.25); // normalised temperature, peak ~ 1
float Temit = disk.u_temperature * Tn;
- // Keplerian orbit (prograde about +Y). Locally-measured orbital speed for a
+ // Keplerian orbit (prograde about +Y). locally-measured orbital speed for a
// Schwarzschild circular geodesic: v = sqrt( M / (r - 2M) ) = 0.5 c at ISCO.
float3 rhat = normalize(float3(P.x, 0.0, P.z));
float3 phiHat = normalize(cross(float3(0.0, 1.0, 0.0), rhat));
@@ -184,17 +187,17 @@ float3 DiskEmission(float3 P, float3 rayDir, out float outG, out float outTemit)
float Tobs = g * Temit;
float3 colour = Blackbody(Tobs);
- // Physical bolometric intensity is ~ T_emit^4 * g^4, an enormous dynamic
- // range. The g^4 relativistic beaming (the physical asymmetry) is kept; the
+ // physical bolometric intensity is ~ T_emit^4 * g^4, an enormous dynamic
+ // range. the g^4 relativistic beaming (the physical asymmetry) is kept; the
// radial falloff is display-compressed (Tn^2) so the colour gradient across
// the disk stays visible instead of collapsing to a thin saturated ring.
float bright = pow(Tn, 2.0) * pow(g, 4.0);
- // Soft inner/outer edges (disks have no hard rim); also tames rim aliasing.
+ // soft inner/outer edges (disks have no hard rim); also tames rim aliasing.
float edge = smoothstep(rin, rin * 1.12, rc) * (1.0 - smoothstep(rout * 0.88, rout, rc));
bright *= edge;
- // Optional turbulence overlay (disk.u_turbulence = strength; 0 = smooth).
+ // optional turbulence overlay (disk.u_turbulence = strength; 0 = smooth).
if (disk.u_turbulence > 0.0)
{
float ang = sim.u_time * 0.3 / sqrt(xr);
@@ -304,13 +307,13 @@ void RK4Step(inout Ray ray, float dL)
float CalculateAdaptiveStepSize(Ray ray, float baseStepSize)
{
- // Step proportional to the distance from the photon sphere: near-flat space
+ // step proportional to the distance from the photon sphere: near-flat space
// far from the hole is crossed in a few huge steps, while the sharply curved
- // region near the photon sphere is resolved with tiny ones. This keeps the
+ // region near the photon sphere is resolved with tiny ones. this keeps the
// integration accurate near the hole regardless of how far the camera is.
float step = 0.02 * max(ray.r - R_PHOTON, 0.0);
- // Slow down when near the disk plane (within its radial extent) so the thin
+ // slow down when near the disk plane (within its radial extent) so the thin
// slab is never stepped over -- otherwise grazing rays leak through it.
float rc = length(float2(ray.x, ray.z));
if (rc < disk.u_outer_radius * 3.0 && abs(ray.y) < disk.u_thickness * 8.0)
@@ -319,12 +322,14 @@ float CalculateAdaptiveStepSize(Ray ray, float baseStepSize)
return clamp(step, MIN_STEP_SIZE, MAX_STEP_SIZE);
}
+// Narkowicz's ACES filmic tonemap. the constants are just The Numbers everyone
+// copies — idk the derivation, but it squashes HDR radiance into a nice 0..1 curve.
float3 ACESFilm(float3 x)
{
return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0);
}
-// A jet-ish false-colour ramp (blue -> cyan -> green -> yellow -> red) for the
+// a jet-ish false-colour ramp (blue -> cyan -> green -> yellow -> red) for the
// observable export channels. t is expected in [0, 1].
float3 Falsecolor(float t)
{
@@ -334,8 +339,8 @@ float3 Falsecolor(float t)
1.5 - abs(4.0 * t - 1.0)), 0.0, 1.0);
}
-// Trace one primary ray for the given image UV and return its linear,
-// pre-tone-map radiance. Called once per sub-sample by fragmentMain.
+// trace one primary ray for the given image UV and return its linear,
+// pre-tone-map radiance. called once per sub-sample by fragmentMain.
float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool outHitDisk)
{
outG = 0.0; outTemit = 0.0; outHitDisk = false;
@@ -371,9 +376,9 @@ float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool
RK4Step(ray, stepSize);
float3 newPos = float3(ray.x, ray.y, ray.z);
- // Opaque disk of small half-thickness H (a slab about the midplane y=0).
- // The ray hits when it first crosses the midplane OR enters the slab
- // while grazing along it. Real (nonzero) thickness stops the zero-height
+ // opaque disk of small half-thickness H (a slab about the midplane y=0).
+ // the ray hits when it first crosses the midplane OR enters the slab
+ // while grazing along it. real (nonzero) thickness stops the zero-height
// edge-on "razor" from aliasing into a beam streaking across the frame.
{
float H = disk.u_thickness;
@@ -397,13 +402,13 @@ float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool
if (i % objectCheckInterval == 0 && InterceptObject(ray, hit)) { hitObject = true; break; }
- // Principled escape: once outbound in near-flat spacetime (r >> r_s) the
+ // principled escape: once outbound in near-flat spacetime (r >> r_s) the
// ray direction no longer changes, so stop and read the background.
if (ray.dr > 0.0 && ray.r > 50.0 * SagA_rs) break;
}
- // Escape direction + environment mip LOD from the ray's angular divergence.
- // Computed UNCONDITIONALLY (before the branch) so ddx/ddy are valid; strongly
+ // escape direction + environment mip LOD from the ray's angular divergence.
+ // computed UNCONDITIONALLY (before the branch) so ddx/ddy are valid; strongly
// lensed background rays diverge fast, so they read a blurred cubemap mip and
// the starfield stops aliasing into a fan along the equatorial plane.
float3 rayDir = normalize(float3(ray.x, ray.y, ray.z) - cam.u_cam_pos);
@@ -438,14 +443,14 @@ float3 TracePixel(float2 texCoord, out float outG, out float outTemit, out bool
[shader("fragment")]
float4 fragmentMain(VSOutput input) : SV_Target
{
- // Moving frame: one sample for responsiveness. Settled frame: rotated-grid
+ // moving frame: one sample for responsiveness. settled frame: rotated-grid
// 4x supersampling (the 4-rook pattern gives 4 distinct sub-pixel positions
// on BOTH axes, far better on the near-horizontal lensed edges than an
- // ordered grid). Radiance is averaged before tone-mapping; ddx/ddy give the
+ // ordered grid). radiance is averaged before tone-mapping; ddx/ddy give the
// resolution-correct per-pixel UV footprint.
- // Observable export channels: the chosen scalar quantity, either as a raw
+ // observable export channels: the chosen scalar quantity, either as a raw
// float (u_raw_output: value in RGB, validity mask in A) or false-coloured.
- // Channel 0 is the normal colour image.
+ // channel 0 is the normal colour image.
if (cam.u_output_channel != 0)
{
float g, Temit; bool hitDisk;
diff --git a/assets/shaders/grid.slang b/assets/shaders/grid.slang
index 8dc4362..13aa349 100644
--- a/assets/shaders/grid.slang
+++ b/assets/shaders/grid.slang
@@ -1,4 +1,4 @@
-// Reference grid on the XZ plane. Uniforms live in a ConstantBuffer (UBO) so both
+// reference grid on the XZ plane. uniforms live in a ConstantBuffer (UBO) so both
// backends drive it through the same RHI path (bind a uniform buffer at binding 0).
struct Grid
{
diff --git a/assets/shaders/skybox.slang b/assets/shaders/skybox.slang
index f7aeb50..ae7634c 100644
--- a/assets/shaders/skybox.slang
+++ b/assets/shaders/skybox.slang
@@ -1,4 +1,4 @@
-// Full-screen skybox cube. View/projection in a ConstantBuffer (UBO, binding 0)
+// full-screen skybox cube. view/projection in a ConstantBuffer (UBO, binding 0)
// so both backends drive it through the RHI; the cubemap is a sampler at binding 1.
struct Skybox
{
diff --git a/assets/shaders/sphere.slang b/assets/shaders/sphere.slang
index 41badde..2c547e6 100644
--- a/assets/shaders/sphere.slang
+++ b/assets/shaders/sphere.slang
@@ -1,4 +1,4 @@
-// Lit sphere (Blinn-Phong + HDRI ambient + selection rim). Uniforms in a
+// lit sphere (Blinn-Phong + HDRI ambient + selection rim). uniforms in a
// ConstantBuffer (UBO, binding 0) so both backends drive it through the RHI;
// the environment cubemap is a separate sampler at binding 1.
struct Sphere
diff --git a/assets/shaders/textured_quad.slang b/assets/shaders/textured_quad.slang
index b72db81..9ff81fd 100644
--- a/assets/shaders/textured_quad.slang
+++ b/assets/shaders/textured_quad.slang
@@ -1,5 +1,5 @@
-// Full-screen textured quad: samples one 2D texture straight to the target.
-// Used to blit an off-screen colour buffer to the swapchain.
+// full-screen textured quad: samples one 2D texture straight to the target.
+// used to blit an off-screen colour buffer to the swapchain.
struct VSInput { float2 position : POSITION; float2 texCoord : TEXCOORD0; };
struct VSOutput { float4 position : SV_Position; float2 texCoord : TEXCOORD0; };
diff --git a/assets/shaders/vk_pipeline_test.slang b/assets/shaders/vk_pipeline_test.slang
index 453fcd3..c644d7c 100644
--- a/assets/shaders/vk_pipeline_test.slang
+++ b/assets/shaders/vk_pipeline_test.slang
@@ -1,5 +1,5 @@
-// Minimal shader used only to verify the Vulkan graphics-pipeline path (SPIR-V
-// module -> pipeline -> draw -> read-back). Draws a full-screen gradient triangle
+// minimal shader used only to verify the Vulkan graphics-pipeline path (SPIR-V
+// module -> pipeline -> draw -> read-back). draws a full-screen gradient triangle
// from the vertex id, so it needs no vertex buffer, UBO, or sampler.
struct VSOutput { float4 position : SV_Position; float3 color : COLOR0; };