68 lines
1.7 KiB
Plaintext
68 lines
1.7 KiB
Plaintext
#include <metal_stdlib>
|
|
using namespace metal;
|
|
|
|
// Fractal Pyramid — bradjamesgrant
|
|
// MSL port of fractal_pyramid.vk.glsl.
|
|
|
|
struct ShadertoyUBO {
|
|
float iTime;
|
|
float2 iResolution;
|
|
};
|
|
|
|
struct PassthroughVOut {
|
|
float4 pos [[position]];
|
|
float2 uv;
|
|
};
|
|
|
|
static float3 palette(float d) {
|
|
return mix(float3(0.2, 0.7, 0.9), float3(1.0, 0.0, 1.0), d);
|
|
}
|
|
|
|
static float2 rotate(float2 p, float a) {
|
|
float c = cos(a);
|
|
float s = sin(a);
|
|
return p * float2x2(c, s, -s, c);
|
|
}
|
|
|
|
static float mapScene(float3 p, float iTime) {
|
|
for (int i = 0; i < 8; ++i) {
|
|
float t = iTime * 0.2;
|
|
p.xz = rotate(p.xz, t);
|
|
p.xy = rotate(p.xy, t * 1.89);
|
|
p.xz = abs(p.xz);
|
|
p.xz -= 0.5;
|
|
}
|
|
return dot(sign(p), p) / 5.0;
|
|
}
|
|
|
|
static float4 rm(float3 ro, float3 rd, float iTime) {
|
|
float t = 0.0;
|
|
float3 col = float3(0.0);
|
|
float d = 1.0;
|
|
for (int i = 0; i < 64; ++i) {
|
|
float3 p = ro + rd * t;
|
|
d = mapScene(p, iTime) * 0.5;
|
|
if (d < 0.02) break;
|
|
if (d > 100.0) break;
|
|
col += palette(length(p) * 0.1) / (400.0 * d);
|
|
t += d;
|
|
}
|
|
return float4(col, 1.0 / (d * 100.0));
|
|
}
|
|
|
|
fragment float4 fractal_pyramid_fs(PassthroughVOut in [[stage_in]],
|
|
constant ShadertoyUBO& U [[buffer(0)]]) {
|
|
float2 fragCoord = in.uv * U.iResolution;
|
|
float2 uv = (fragCoord - (U.iResolution * 0.5)) / U.iResolution.x;
|
|
float3 ro = float3(0.0, 0.0, -50.0);
|
|
ro.xz = rotate(ro.xz, U.iTime);
|
|
float3 cf = normalize(-ro);
|
|
float3 cs = normalize(cross(cf, float3(0.0, 1.0, 0.0)));
|
|
float3 cu = normalize(cross(cf, cs));
|
|
|
|
float3 uuv = ro + cf * 3.0 + uv.x * cs + uv.y * cu;
|
|
float3 rd = normalize(uuv - ro);
|
|
|
|
return rm(ro, rd, U.iTime);
|
|
}
|