From ef37a7a2e6992d1674cc3d0e1915bff3cf1803f6 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 4 May 2026 12:35:58 +0200 Subject: [PATCH] Porta tots els shaders a Vulkan i Metal --- shaders/_common/passthrough.vert.msl | 2 +- shaders/_common/passthrough.vert.spv | Bin 1452 -> 1388 bytes shaders/_common/passthrough.vk.glsl | 3 +- .../cineshader_lava/cineshader_lava.frag.msl | 75 ++ .../cineshader_lava/cineshader_lava.frag.spv | Bin 0 -> 6968 bytes .../cineshader_lava/cineshader_lava.vk.glsl | 77 ++ shaders/creation/creation.frag.msl | 42 + shaders/creation/creation.frag.spv | Bin 0 -> 3732 bytes shaders/creation/creation.vk.glsl | 45 + shaders/cube_lines/cube_lines.frag.msl | 452 ++++++++++ shaders/cube_lines/cube_lines.frag.spv | Bin 0 -> 59412 bytes shaders/cube_lines/cube_lines.vk.glsl | 782 ++++++++++++++++++ shaders/dbz/dbz.frag.msl | 127 +++ shaders/dbz/dbz.frag.spv | Bin 0 -> 14872 bytes shaders/dbz/dbz.vk.glsl | 127 +++ .../fractal_pyramid/fractal_pyramid.frag.msl | 67 ++ .../fractal_pyramid/fractal_pyramid.frag.spv | Bin 0 -> 6728 bytes .../fractal_pyramid/fractal_pyramid.vk.glsl | 71 ++ .../just_another_cube.frag.msl | 89 ++ .../just_another_cube.frag.spv | Bin 0 -> 6808 bytes .../just_another_cube.vk.glsl | 88 ++ shaders/octograms/octograms.frag.msl | 95 +++ shaders/octograms/octograms.frag.spv | Bin 0 -> 11152 bytes shaders/octograms/octograms.vk.glsl | 109 +++ shaders/remember/remember.frag.msl | 64 ++ shaders/remember/remember.frag.spv | Bin 0 -> 6616 bytes shaders/remember/remember.vk.glsl | 61 ++ shaders/seascape/seascape.frag.msl | 181 ++++ shaders/seascape/seascape.frag.spv | Bin 0 -> 19556 bytes shaders/seascape/seascape.vk.glsl | 200 +++++ .../shader_art_coding_introduction.frag.msl | 47 ++ .../shader_art_coding_introduction.frag.spv | Bin 0 -> 3712 bytes .../shader_art_coding_introduction.vk.glsl | 50 ++ shaders/test/test.frag.spv | Bin 2836 -> 2836 bytes shaders/test/test.vk.glsl | 11 +- shaders/water/water.frag.msl | 40 + shaders/water/water.frag.spv | Bin 0 -> 3796 bytes shaders/water/water.vk.glsl | 45 + 38 files changed, 2942 insertions(+), 8 deletions(-) create mode 100644 shaders/cineshader_lava/cineshader_lava.frag.msl create mode 100644 shaders/cineshader_lava/cineshader_lava.frag.spv create mode 100644 shaders/cineshader_lava/cineshader_lava.vk.glsl create mode 100644 shaders/creation/creation.frag.msl create mode 100644 shaders/creation/creation.frag.spv create mode 100644 shaders/creation/creation.vk.glsl create mode 100644 shaders/cube_lines/cube_lines.frag.msl create mode 100644 shaders/cube_lines/cube_lines.frag.spv create mode 100644 shaders/cube_lines/cube_lines.vk.glsl create mode 100644 shaders/dbz/dbz.frag.msl create mode 100644 shaders/dbz/dbz.frag.spv create mode 100644 shaders/dbz/dbz.vk.glsl create mode 100644 shaders/fractal_pyramid/fractal_pyramid.frag.msl create mode 100644 shaders/fractal_pyramid/fractal_pyramid.frag.spv create mode 100644 shaders/fractal_pyramid/fractal_pyramid.vk.glsl create mode 100644 shaders/just_another_cube/just_another_cube.frag.msl create mode 100644 shaders/just_another_cube/just_another_cube.frag.spv create mode 100644 shaders/just_another_cube/just_another_cube.vk.glsl create mode 100644 shaders/octograms/octograms.frag.msl create mode 100644 shaders/octograms/octograms.frag.spv create mode 100644 shaders/octograms/octograms.vk.glsl create mode 100644 shaders/remember/remember.frag.msl create mode 100644 shaders/remember/remember.frag.spv create mode 100644 shaders/remember/remember.vk.glsl create mode 100644 shaders/seascape/seascape.frag.msl create mode 100644 shaders/seascape/seascape.frag.spv create mode 100644 shaders/seascape/seascape.vk.glsl create mode 100644 shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.msl create mode 100644 shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.spv create mode 100644 shaders/shader_art_coding_introduction/shader_art_coding_introduction.vk.glsl create mode 100644 shaders/water/water.frag.msl create mode 100644 shaders/water/water.frag.spv create mode 100644 shaders/water/water.vk.glsl diff --git a/shaders/_common/passthrough.vert.msl b/shaders/_common/passthrough.vert.msl index f596d75..8b9d90b 100644 --- a/shaders/_common/passthrough.vert.msl +++ b/shaders/_common/passthrough.vert.msl @@ -14,6 +14,6 @@ vertex PassthroughVOut passthrough_vs(uint vid [[vertex_id]]) { PassthroughVOut out; float2 pos = positions[vid]; out.uv = pos * 0.5 + 0.5; - out.pos = float4(pos.x, -pos.y, 0.0, 1.0); + out.pos = float4(pos, 0.0, 1.0); return out; } diff --git a/shaders/_common/passthrough.vert.spv b/shaders/_common/passthrough.vert.spv index 6c189086af5c2d61025d62cb168a0f0e4aaca856..2998023fab089de8c262681b1d87c56880d16c74 100644 GIT binary patch delta 185 zcmZ3({f3K|nMs+Qfq{{Mn}L_Xa3k+^W<@pz1_mu41_5mb76uSs8_a94R{-+$C#$l& zuCWEOfEpPzftVAB0~uJsDs`Y@KngCV3l(Do(g8qSNMw;RMLSR#U5M2pG(<^-kRV--%ToZ*_(y?d&a%T4(aCP&(neJEni$@fG>Pk_Q%y}6BZ#=i@ z72JB~S;OtgK diff --git a/shaders/_common/passthrough.vk.glsl b/shaders/_common/passthrough.vk.glsl index cf192c2..2b07bf3 100644 --- a/shaders/_common/passthrough.vk.glsl +++ b/shaders/_common/passthrough.vk.glsl @@ -2,7 +2,6 @@ // Shared fullscreen-triangle vertex shader for the SDL3 GPU backend. // Emits vUV in Shadertoy convention: (0,0) bottom-left, (1,1) top-right. -// Y flipped in NDC because Vulkan/Metal point Y down by default. layout(location = 0) out vec2 vUV; @@ -14,5 +13,5 @@ void main() { ); vec2 pos = positions[gl_VertexIndex]; vUV = pos * 0.5 + 0.5; - gl_Position = vec4(pos.x, -pos.y, 0.0, 1.0); + gl_Position = vec4(pos, 0.0, 1.0); } diff --git a/shaders/cineshader_lava/cineshader_lava.frag.msl b/shaders/cineshader_lava/cineshader_lava.frag.msl new file mode 100644 index 0000000..4f48672 --- /dev/null +++ b/shaders/cineshader_lava/cineshader_lava.frag.msl @@ -0,0 +1,75 @@ +#include +using namespace metal; + +// Cineshader Lava — edankwan +// MSL port of cineshader_lava.vk.glsl. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +static float opSmoothUnion(float d1, float d2, float k) { + float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0); + return mix(d2, d1, h) - k * h * (1.0 - h); +} + +static float sdSphere(float3 p, float s) { + return length(p) - s; +} + +static float map(float3 p, float iTime) { + float d = 2.0; + for (int i = 0; i < 16; i++) { + float fi = float(i); + float time = iTime * (fract(fi * 412.531 + 0.513) - 0.5) * 2.0; + d = opSmoothUnion( + sdSphere(p + sin(time + fi * float3(52.5126, 64.62744, 632.25)) * float3(2.0, 2.0, 0.8), + mix(0.5, 1.0, fract(fi * 412.531 + 0.5124))), + d, + 0.4 + ); + } + return d; +} + +static float3 calcNormal(float3 p, float iTime) { + const float h = 1e-5; + const float2 k = float2(1, -1); + return normalize(k.xyy * map(p + k.xyy * h, iTime) + + k.yyx * map(p + k.yyx * h, iTime) + + k.yxy * map(p + k.yxy * h, iTime) + + k.xxx * map(p + k.xxx * h, iTime)); +} + +fragment float4 cineshader_lava_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float2 uv = fragCoord / U.iResolution; + + float3 rayOri = float3((uv - 0.5) * float2(U.iResolution.x / U.iResolution.y, 1.0) * 6.0, 3.0); + float3 rayDir = float3(0.0, 0.0, -1.0); + + float depth = 0.0; + float3 p = float3(0.0); + + for (int i = 0; i < 64; i++) { + p = rayOri + rayDir * depth; + float dist = map(p, U.iTime); + depth += dist; + if (dist < 1e-6) { break; } + } + + depth = min(6.0, depth); + float3 n = calcNormal(p, U.iTime); + float b = max(0.0, dot(n, float3(0.577))); + float3 col = (0.5 + 0.5 * cos((b + U.iTime * 3.0) + uv.xyx * 2.0 + float3(0, 2, 4))) * (0.85 + b * 0.35); + col *= exp(-depth * 0.15); + + return float4(col, 1.0 - (depth - 0.5) / 2.0); +} diff --git a/shaders/cineshader_lava/cineshader_lava.frag.spv b/shaders/cineshader_lava/cineshader_lava.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..27b656117a40c60f7fe0aba48341be88802b799a GIT binary patch literal 6968 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 +using namespace metal; + +// Creation by Silexars — Danguafer +// MSL port of creation.vk.glsl. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +fragment float4 creation_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float t = U.iTime; + float2 r = U.iResolution; + + float3 c = float3(0.0); + float l = 0.0; + float z = t; + for (int i = 0; i < 3; i++) { + float2 p = fragCoord / r; + float2 uv = p; + p -= 0.5; + p.x *= r.x / r.y; + z += 0.07; + l = length(p); + float invl = (l > 0.0) ? (1.0 / l) : 0.0; + uv += p * invl * (sin(z) + 1.0) * abs(sin(l * 9.0 - z - z)); + float2 m = fract(uv) - 0.5; + float denom = length(m); + if (denom < 1e-6) denom = 1e-6; + c[i] = 0.01 / denom; + } + float L = (l > 0.0) ? l : 1.0; + return float4(c / L, t); +} diff --git a/shaders/creation/creation.frag.spv b/shaders/creation/creation.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..fcd4cfe8f9e2b8e8c7ad2a83b04f28a5d275a80d GIT binary patch literal 3732 zcmZ9OXLD6m6oyYo0U z?&v(#xp{27fAfx=Ta1{O)TV*P%ui+}b!cU%w=}HdHu5dfM4UVgK($m&l3z)xOJ*k> zojo00T^*fAd-_I3dd9{tm5V*)(r~e-zcgCx8!t^3jhmH=D-HLRC;IaN^+e?R*3)So zJzU4}q29sby2*hZ`z8mr?Msq+{xsqn80{TAQYlwP!E$r&bCuEll&eh^qWdzu1bsQh z4arjUsq?-4#nJJ~r89@SFqu$&%8N^g?cj3C*Cof%rQu1nl1=lB^gDVr`F&db<7Scf0Yzv(ftGTiC}Ov_A9nnbU+e$DZaaK$|1K5nEp~;d-tzl0+j+??#$JvtAT@}6wO1g1=C4E>YfbHk(e^Vg;@5)R$08!v z<@ilt>zel%+B&W)_O~6(cgS_@1{AdT^lR@)t^aJEVOlTpk6^DqclSWp>4Qq94uyR# z&2MT8`vUeayKn9cn-z-kT3w%W()QlO`o96YNB6E@+j}Ipi!*j_-VZ;y zKVj<8#(L(yp~&?f_+Ik%y_{{lZ$auNR}SWch)wD)q-?&T}Q-$K`=&m7nDb;gK*1+j$7_oP1NxsrpW3;;RUu|9AlwETY@EKRFW1Hto$X#E*644AwVm%1 znJ?n@=i>YgiMRt`eeTD+gNV8E&cU-jgt&)%{UW&9R^39Yu7d|dOrpB z?5|}tj)LWmAja#Hi+Oc`t=C9Ldmck-5bNqQryVUHJ)Q>3{Y($FZ=e@M1`PK=a{qjCzqV_4U`NsMVwPVkx!R|R? z&w!1&!+yN8XAxuMBj$Oqvx_;s0CrB^ZGAEC7s2}6N7Q=>Y)ySp?`5!ikF$OSEO!ox zm{-B}^xih0dl2K~Bjz=5KBgDjIQdxX>)=?c{^0vE-hW?=iS_n_U9*1sIFlmcTXUb< z0~u$mGu9^;@#n#E@eWI1XQJHBYP^NRh}~D; zJK%OC-txO(xn?9{u7ZvEA^VM(0vjjqdD`a+dI~Y834IN5A5r5yurb}#(0?6~3vnj$ z?<3~wcP1;*H;`q>3MA^?%=i<;INJ{pbNzz51(vJHaUW*f40JdDy3Ry@gqUx 0.0) ? (1.0 / l) : 0.0; + uv += p * invl * (sin(z) + 1.0) * abs(sin(l * 9.0 - z - z)); + vec2 m = mod(uv, 1.0) - 0.5; + float denom = length(m); + if (denom < 1e-6) denom = 1e-6; + c[i] = 0.01 / denom; + } + float L = (l > 0.0) ? l : 1.0; + fragColor = vec4(c / L, t); +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/cube_lines/cube_lines.frag.msl b/shaders/cube_lines/cube_lines.frag.msl new file mode 100644 index 0000000..1b63517 --- /dev/null +++ b/shaders/cube_lines/cube_lines.frag.msl @@ -0,0 +1,452 @@ +#include +using namespace metal; + +// Cube lines — Danil +// MSL port of cube_lines.vk.glsl. The original Shadertoy is ~780 lines and +// uses every GLSL trick (mat3 chains, arrays, fwidth-based AA, swap macros). +// +// Notes on compromises in this port: +// - fcos() in the GLSL uses fwidth() with a fallback that depends on +// iResolution.y. To avoid threading iResolution through ~10 helpers, this +// port uses the simpler `fcos = cos` path (equivalent to defining AA_ALL +// in the original). Edges may be slightly less smooth than the Vulkan/GL +// versions; cosmetic only. +// - Optional Shadertoy defines (ANIM_SHAPE, ANIM_COLOR, ROTATION_SPEED, +// CAMERA_*, USE_COLOR, AA_*, ONLY_BOX, etc.) are left at their defaults +// just like the .vk.glsl ships them. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +constant float ROTATION_SPEED = 0.8999; +constant float tshift = 53.0; +constant float FDIST = 0.7; +constant float PI = 3.1415926; +constant float3 BOXDIMS = float3(0.75, 0.75, 1.25); +constant float IOR = 1.33; + +static float3x3 rotx(float a) { + float s = sin(a), c = cos(a); + return float3x3(float3(1.0, 0.0, 0.0), float3(0.0, c, s), float3(0.0, -s, c)); +} +static float3x3 roty(float a) { + float s = sin(a), c = cos(a); + return float3x3(float3(c, 0.0, s), float3(0.0, 1.0, 0.0), float3(-s, 0.0, c)); +} +static float3x3 rotz(float a) { + float s = sin(a), c = cos(a); + return float3x3(float3(c, s, 0.0), float3(-s, c, 0.0), float3(0.0, 0.0, 1.0)); +} + +static float3 fcos(float3 x) { return cos(x); } + +static float3 getColor(float3 p) { + p = abs(p); + p *= 1.25; + p = 0.5 * p / dot(p, p); + + float t = 0.13 * length(p); + float3 col = float3(0.3, 0.4, 0.5); + col += 0.12 * fcos(6.28318 * t * 1.0 + float3(0.0, 0.8, 1.1)); + col += 0.11 * fcos(6.28318 * t * 3.1 + float3(0.3, 0.4, 0.1)); + col += 0.10 * fcos(6.28318 * t * 5.1 + float3(0.1, 0.7, 1.1)); + col += 0.10 * fcos(6.28318 * t * 17.1 + float3(0.2, 0.6, 0.7)); + col += 0.10 * fcos(6.28318 * t * 31.1 + float3(0.1, 0.6, 0.7)); + col += 0.10 * fcos(6.28318 * t * 65.1 + float3(0.0, 0.5, 0.8)); + col += 0.10 * fcos(6.28318 * t * 115.1 + float3(0.1, 0.4, 0.7)); + col += 0.10 * fcos(6.28318 * t * 265.1 + float3(1.1, 1.4, 2.7)); + col = clamp(col, 0.0, 1.0); + return col; +} + +static void calcColor(float3 ro, float3 rd, float3 nor, float d, float len, int idx, + bool si, float td, + thread float4& colx, thread float4& colsi) { + float3 pos = ro + rd * d; + float a = 1.0 - smoothstep(len - 0.15 * 0.5, len + 0.00001, length(pos)); + float3 col = getColor(pos); + colx = float4(col, a); + if (si) { + pos = ro + rd * td; + float ta = 1.0 - smoothstep(len - 0.15 * 0.5, len + 0.00001, length(pos)); + col = getColor(pos); + colsi = float4(col, ta); + } +} + +static bool iBilinearPatch(float3 ro, float3 rd, float4 ps, float4 ph, float sz, + thread float& t, thread float3& norm, + thread bool& si, thread float& tsi, thread float3& normsi, + thread float& fade, thread float& fadesi) { + float3 va = float3(0.0, 0.0, ph.x + ph.w - ph.y - ph.z); + float3 vb = float3(0.0, ps.w - ps.y, ph.z - ph.x); + float3 vc = float3(ps.z - ps.x, 0.0, ph.y - ph.x); + float3 vd = float3(ps.xy, ph.x); + t = -1.0; + tsi = -1.0; + si = false; + fade = 1.0; + fadesi = 1.0; + norm = float3(0.0, 1.0, 0.0); + normsi = float3(0.0, 1.0, 0.0); + + float tmp = 1.0 / (vb.y * vc.x); + float a = 0.0, b = 0.0, c = 0.0; + float d = va.z * tmp; + float e = 0.0, f = 0.0; + float g = (vc.z * vb.y - vd.y * va.z) * tmp; + float h = (vb.z * vc.x - va.z * vd.x) * tmp; + float i = -1.0; + float j = (vd.x * vd.y * va.z + vd.z * vb.y * vc.x) * tmp - (vd.y * vb.z * vc.x + vd.x * vc.z * vb.y) * tmp; + + float p = dot(float3(a, b, c), rd.xzy * rd.xzy) + dot(float3(d, e, f), rd.xzy * rd.zyx); + float q = dot(float3(2.0, 2.0, 2.0) * ro.xzy * rd.xyz, float3(a, b, c)) + dot(ro.xzz * rd.zxy, float3(d, d, e)) + + dot(ro.yyx * rd.zxy, float3(e, f, f)) + dot(float3(g, h, i), rd.xzy); + float r = dot(float3(a, b, c), ro.xzy * ro.xzy) + dot(float3(d, e, f), ro.xzy * ro.zyx) + dot(float3(g, h, i), ro.xzy) + j; + + if (abs(p) < 0.000001) { + float tt = -r / q; + if (tt <= 0.0) return false; + t = tt; + float3 pos = ro + t * rd; + if (length(pos) > sz) return false; + float3 grad = float3(2.0) * pos.xzy * float3(a, b, c) + pos.zxz * float3(d, d, e) + pos.yyx * float3(f, e, f) + float3(g, h, i); + norm = -normalize(grad); + return true; + } else { + float sq = q * q - 4.0 * p * r; + if (sq < 0.0) return false; + float s = sqrt(sq); + float t0 = (-q + s) / (2.0 * p); + float t1 = (-q - s) / (2.0 * p); + float tt1 = min(t0 < 0.0 ? t1 : t0, t1 < 0.0 ? t0 : t1); + float tt2 = max(t0 > 0.0 ? t1 : t0, t1 > 0.0 ? t0 : t1); + float tt0 = tt1; + if (tt0 <= 0.0) return false; + float3 pos = ro + tt0 * rd; + bool ru = step(sz, length(pos)) > 0.5; + if (ru) { + tt0 = tt2; + pos = ro + tt0 * rd; + } + if (tt0 <= 0.0) return false; + bool ru2 = step(sz, length(pos)) > 0.5; + if (ru2) return false; + + if ((tt2 > 0.0) && (!ru) && !(step(sz, length(ro + tt2 * rd)) > 0.5)) { + si = true; + fadesi = s; + tsi = tt2; + float3 tpos = ro + tsi * rd; + float3 tgrad = float3(2.0) * tpos.xzy * float3(a, b, c) + tpos.zxz * float3(d, d, e) + + tpos.yyx * float3(f, e, f) + float3(g, h, i); + normsi = -normalize(tgrad); + } + + fade = s; + t = tt0; + float3 grad = float3(2.0) * pos.xzy * float3(a, b, c) + pos.zxz * float3(d, d, e) + pos.yyx * float3(f, e, f) + float3(g, h, i); + norm = -normalize(grad); + return true; + } +} + +static float dot2(float3 v) { return dot(v, v); } + +static float segShadow(float3 ro, float3 rd, float3 pa, float sh) { + float dm = dot(rd.yz, rd.yz); + float k1 = (ro.x - pa.x) * dm; + float k2 = (ro.x + pa.x) * dm; + float2 k5 = (ro.yz + pa.yz) * dm; + float k3 = dot(ro.yz + pa.yz, rd.yz); + float2 k4 = (pa.yz + pa.yz) * rd.yz; + float2 k6 = (pa.yz + pa.yz) * dm; + + for (int i = 0; i < 4; i++) { + float2 s = float2(i & 1, i >> 1); + float t = dot(s, k4) - k3; + if (t > 0.0) { + sh = min(sh, dot2(float3(clamp(-rd.x * t, k1, k2), k5 - k6 * s) + rd * t) / (t * t)); + } + } + return sh; +} + +static float boxSoftShadow(float3 ro, float3 rd, float3 rad, float sk) { + rd += 0.0001 * (1.0 - abs(sign(rd))); + float3 rdd = rd; + float3 roo = ro; + + float3 m = 1.0 / rdd; + float3 n = m * roo; + float3 k = abs(m) * rad; + + float3 t1 = -n - k; + float3 t2 = -n + k; + + float tN = max(max(t1.x, t1.y), t1.z); + float tF = min(min(t2.x, t2.y), t2.z); + + if (tN < tF && tF > 0.0) return 0.0; + + float sh = 1.0; + sh = segShadow(roo.xyz, rdd.xyz, rad.xyz, sh); + sh = segShadow(roo.yzx, rdd.yzx, rad.yzx, sh); + sh = segShadow(roo.zxy, rdd.zxy, rad.zxy, sh); + sh = clamp(sk * sqrt(sh), 0.0, 1.0); + return sh * sh * (3.0 - 2.0 * sh); +} + +static float boxRay(float3 ro, float3 rd, float3 r, thread float3& nn, bool entering) { + rd += 0.0001 * (1.0 - abs(sign(rd))); + float3 dr = 1.0 / rd; + float3 n = ro * dr; + float3 k = r * abs(dr); + + float3 pin = -k - n; + float3 pout = k - n; + float tin = max(pin.x, max(pin.y, pin.z)); + float tout = min(pout.x, min(pout.y, pout.z)); + if (tin > tout) return -1.0; + if (entering) { + nn = -sign(rd) * step(pin.zxy, pin.xyz) * step(pin.yzx, pin.xyz); + } else { + nn = sign(rd) * step(pout.xyz, pout.zxy) * step(pout.xyz, pout.yzx); + } + return entering ? tin : tout; +} + +static float3 bgcol(float3 rd) { + return mix(float3(0.01), float3(0.336, 0.458, 0.668), 1.0 - pow(abs(rd.z + 0.25), 1.3)); +} + +static float3 background(float3 ro, float3 rd, float3 l_dir, thread float& alpha) { + float t = (-BOXDIMS.z - ro.z) / rd.z; + alpha = 0.0; + float3 bgc = bgcol(rd); + if (t < 0.0) return bgc; + float2 uv = ro.xy + t * rd.xy; + float shad = boxSoftShadow((ro + t * rd), normalize(l_dir + float3(0.0, 0.0, 1.0)) * rotz(PI * 0.65), BOXDIMS, 1.5); + float aofac = smoothstep(-0.95, 0.75, length(abs(uv) - min(abs(uv), float2(0.45)))); + aofac = min(aofac, smoothstep(-0.65, 1.0, shad)); + float lght = max(dot(normalize(ro + t * rd + float3(0.0, -0.0, -5.0)), normalize(l_dir - float3(0.0, 0.0, 1.0)) * rotz(PI * 0.65)), 0.0); + float3 col = mix(float3(0.4), float3(0.71, 0.772, 0.895), lght * lght * aofac + 0.05) * aofac; + alpha = 1.0 - smoothstep(7.0, 10.0, length(uv)); + return mix(col * length(col) * 0.8, bgc, smoothstep(7.0, 10.0, length(uv))); +} + +static float4 insides(float3 ro, float3 rd, float3 nor_c, float3 l_dir, thread float& tout) { + tout = -1.0; + + float pi = 3.1415926; + + if (abs(nor_c.x) > 0.5) { + rd = rd.xzy * nor_c.x; + ro = ro.xzy * nor_c.x; + } else if (abs(nor_c.z) > 0.5) { + l_dir = l_dir * roty(pi); + rd = rd.yxz * nor_c.z; + ro = ro.yxz * nor_c.z; + } else if (abs(nor_c.y) > 0.5) { + l_dir = l_dir * rotz(-pi * 0.5); + rd = rd * nor_c.y; + ro = ro * nor_c.y; + } + + const float curvature = 0.5; + float bil_size = 1.0; + float4 ps = float4(-bil_size, -bil_size, bil_size, bil_size) * curvature; + float4 ph = float4(-bil_size, bil_size, bil_size, -bil_size) * curvature; + + float4 colx[3] = { float4(0.0), float4(0.0), float4(0.0) }; + float3 dx[3] = { float3(-1.0), float3(-1.0), float3(-1.0) }; + float4 colxsi[3] = { float4(0.0), float4(0.0), float4(0.0) }; + int order[3] = { 0, 1, 2 }; + + for (int i = 0; i < 3; i++) { + if (abs(nor_c.x) > 0.5) { + ro = ro * rotz(-pi * (1.0 / 3.0)); + rd = rd * rotz(-pi * (1.0 / 3.0)); + } else if (abs(nor_c.z) > 0.5) { + ro = ro * rotz(pi * (1.0 / 3.0)); + rd = rd * rotz(pi * (1.0 / 3.0)); + } else if (abs(nor_c.y) > 0.5) { + ro = ro * rotx(pi * (1.0 / 3.0)); + rd = rd * rotx(pi * (1.0 / 3.0)); + } + float3 normnew; + float tnew; + bool si; + float tsi; + float3 normsi; + float fade; + float fadesi; + + if (iBilinearPatch(ro, rd, ps, ph, bil_size, tnew, normnew, si, tsi, normsi, fade, fadesi)) { + if (tnew > 0.0) { + float4 tcol, tcolsi; + calcColor(ro, rd, normnew, tnew, bil_size, i, si, tsi, tcol, tcolsi); + if (tcol.a > 0.0) { + dx[i] = float3(tnew, float(si), tsi); + + float dif = clamp(dot(normnew, l_dir), 0.0, 1.0); + float amb = clamp(0.5 + 0.5 * dot(normnew, l_dir), 0.0, 1.0); + + { + float3 shad = float3(0.32, 0.43, 0.54) * amb + float3(1.0, 0.9, 0.7) * dif; + const float3 tcr = float3(1.0, 0.21, 0.11); + float ta = clamp(length(tcol.rgb), 0.0, 1.0); + tcol = clamp(tcol * tcol * 2.0, 0.0, 1.0); + float4 tvalx = float4(tcol.rgb * shad * 1.4 + 3.0 * (tcr * tcol.rgb) * clamp(1.0 - (amb + dif), 0.0, 1.0), min(tcol.a, ta)); + tvalx.rgb = clamp(2.0 * tvalx.rgb * tvalx.rgb, 0.0, 1.0); + tvalx *= min(fade * 5.0, 1.0); + colx[i] = tvalx; + } + if (si) { + dif = clamp(dot(normsi, l_dir), 0.0, 1.0); + amb = clamp(0.5 + 0.5 * dot(normsi, l_dir), 0.0, 1.0); + float3 shad = float3(0.32, 0.43, 0.54) * amb + float3(1.0, 0.9, 0.7) * dif; + const float3 tcr = float3(1.0, 0.21, 0.11); + float ta = clamp(length(tcolsi.rgb), 0.0, 1.0); + tcolsi = clamp(tcolsi * tcolsi * 2.0, 0.0, 1.0); + float4 tvalx = float4(tcolsi.rgb * shad + 3.0 * (tcr * tcolsi.rgb) * clamp(1.0 - (amb + dif), 0.0, 1.0), min(tcolsi.a, ta)); + tvalx.rgb = clamp(2.0 * tvalx.rgb * tvalx.rgb, 0.0, 1.0); + tvalx.rgb *= min(fadesi * 5.0, 1.0); + colxsi[i] = tvalx; + } + } + } + } + } + + // sort by dx[*].x descending (3 passes of bubble sort like the GLSL) + if (dx[0].x < dx[1].x) { float3 tv = dx[0]; dx[0] = dx[1]; dx[1] = tv; int ti = order[0]; order[0] = order[1]; order[1] = ti; } + if (dx[1].x < dx[2].x) { float3 tv = dx[1]; dx[1] = dx[2]; dx[2] = tv; int ti = order[1]; order[1] = order[2]; order[2] = ti; } + if (dx[0].x < dx[1].x) { float3 tv = dx[0]; dx[0] = dx[1]; dx[1] = tv; int ti = order[0]; order[0] = order[1]; order[1] = ti; } + + tout = max(max(dx[0].x, dx[1].x), dx[2].x); + + float a = 1.0; + if (dx[0].y < 0.5) { + a = colx[order[0]].a; + } + + bool rul[3] = { + ((dx[0].y > 0.5) && (dx[1].x <= 0.0)), + ((dx[1].y > 0.5) && (dx[0].x > dx[1].z)), + ((dx[2].y > 0.5) && (dx[1].x > dx[2].z)) + }; + for (int k = 0; k < 3; k++) { + if (rul[k]) { + float4 tcolxsi = colxsi[order[k]]; + float4 tcolx = colx[order[k]]; + float4 tvalx = mix(tcolxsi, tcolx, tcolx.a); + float4 tvalx2 = mix(float4(0.0), tvalx, max(tcolx.a, tcolxsi.a)); + colx[order[k]] = tvalx2; + } + } + + float a1 = (dx[1].y < 0.5) ? colx[order[1]].a : ((dx[1].z > dx[0].x) ? colx[order[1]].a : 1.0); + float a2 = (dx[2].y < 0.5) ? colx[order[2]].a : ((dx[2].z > dx[1].x) ? colx[order[2]].a : 1.0); + float3 col = mix(mix(colx[order[0]].rgb, colx[order[1]].rgb, a1), colx[order[2]].rgb, a2); + a = max(max(a, a1), a2); + return float4(col, a); +} + +fragment float4 cube_lines_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float iTime = U.iTime; + + float3 l_dir = normalize(float3(0.0, 1.0, 0.0)); + l_dir = l_dir * rotz(0.5); + float mouseY = PI * 0.49 - smoothstep(0.0, 8.5, fmod((iTime + tshift) * 0.33, 25.0)) + * (1.0 - smoothstep(14.0, 24.0, fmod((iTime + tshift) * 0.33, 25.0))) * 0.55 * PI; + float mouseX = -2.0 * PI - 0.25 * (iTime * ROTATION_SPEED + tshift); + + float3 eye = 4.0 * float3(cos(mouseX) * cos(mouseY), sin(mouseX) * cos(mouseY), sin(mouseY)); + float3 w = normalize(-eye); + float3 up = float3(0.0, 0.0, 1.0); + float3 u = normalize(cross(w, up)); + float3 v = cross(u, w); + + float4 tot = float4(0.0); + float2 uv = (fragCoord - 0.5 * U.iResolution) / U.iResolution.x; + float3 rd = normalize(w * FDIST + uv.x * u + uv.y * v); + + float3 ni; + float t = boxRay(eye, rd, BOXDIMS, ni, true); + float3 ro = eye + t * rd; + float2 coords = ro.xy * ni.z / BOXDIMS.xy + ro.yz * ni.x / BOXDIMS.yz + ro.zx * ni.y / BOXDIMS.zx; + float fadeborders = (1.0 - smoothstep(0.915, 1.05, abs(coords.x))) * (1.0 - smoothstep(0.915, 1.05, abs(coords.y))); + + if (t > 0.0) { + float3 col = float3(0.0); + float R0 = (IOR - 1.0) / (IOR + 1.0); + R0 *= R0; + + float2 theta = float2(0.0); + float3 n = float3(cos(theta.x) * sin(theta.y), sin(theta.x) * sin(theta.y), cos(theta.y)); + + float3 nr = n.zxy * ni.x + n.yzx * ni.y + n.xyz * ni.z; + float3 rdr = reflect(rd, nr); + float talpha; + float3 reflcol = background(ro, rdr, l_dir, talpha); + + float3 rd2 = refract(rd, nr, 1.0 / IOR); + + float accum = 1.0; + float3 no2 = ni; + float3 ro_refr = ro; + + float4 colo[2] = { float4(0.0), float4(0.0) }; + + for (int j = 0; j < 2; j++) { + float tb; + float2 coords2 = ro_refr.xy * no2.z + ro_refr.yz * no2.x + ro_refr.zx * no2.y; + float3 eye2 = float3(coords2, -1.0); + float3 rd2trans = rd2.yzx * no2.x + rd2.zxy * no2.y + rd2.xyz * no2.z; + + rd2trans.z = -rd2trans.z; + float4 internalcol = insides(eye2, rd2trans, no2, l_dir, tb); + if (tb > 0.0) { + internalcol.rgb *= accum; + colo[j] = internalcol; + } + + if ((tb <= 0.0) || (internalcol.a < 1.0)) { + float tout = boxRay(ro_refr, rd2, BOXDIMS, no2, false); + no2 = n.zyx * no2.x + n.xzy * no2.y + n.yxz * no2.z; + float3 rout = ro_refr + tout * rd2; + float3 rdout = refract(rd2, -no2, IOR); + float fresnel2 = R0 + (1.0 - R0) * pow(1.0 - dot(rdout, no2), 1.3); + rd2 = reflect(rd2, -no2); + + ro_refr = rout; + ro_refr.z = max(ro_refr.z, -0.999); + + accum *= fresnel2; + } + } + float fresnel = R0 + (1.0 - R0) * pow(1.0 - dot(-rd, nr), 5.0); + col = mix(mix(colo[1].rgb * colo[1].a, colo[0].rgb, colo[0].a) * fadeborders, reflcol, pow(fresnel, 1.5)); + col = clamp(col, 0.0, 1.0); + + float cineshader_alpha = clamp(0.15 * dot(eye, ro), 0.0, 1.0); + tot += float4(col, cineshader_alpha); + } else { + float alpha; + tot += float4(background(eye, rd, l_dir, alpha), 0.15); + } + + float4 outColor = tot; + outColor.rgb = clamp(outColor.rgb, 0.0, 1.0); + return outColor; +} diff --git a/shaders/cube_lines/cube_lines.frag.spv b/shaders/cube_lines/cube_lines.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..14aa383e8d1de0ae6092dfc00cf9a70ac03fb52b GIT binary patch literal 59412 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 literal 0 HcmV?d00001 diff --git a/shaders/cube_lines/cube_lines.vk.glsl b/shaders/cube_lines/cube_lines.vk.glsl new file mode 100644 index 0000000..55aaddf --- /dev/null +++ b/shaders/cube_lines/cube_lines.vk.glsl @@ -0,0 +1,782 @@ +#version 450 + +// Name: Cube lines +// Author: Danil +// URL: https://www.shadertoy.com/view/NslGRN + +layout(location = 0) in vec2 vUV; +layout(location = 0) out vec4 FragColor; + +layout(set = 3, binding = 0) uniform ShadertoyUBO { + float iTime; + vec2 iResolution; +}; + + +// Note: Original shader uses iChannel0 for background blending (optional feature) +// Since we don't support texture channels, that line is commented out +// The shader works perfectly without it in default mode + +// Created by Danil (2021+) https://cohost.org/arugl +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. +// self https://www.shadertoy.com/view/NslGRN + + +// --defines for "DESKTOP WALLPAPERS" that use this shader-- +// comment or uncomment every define to make it work (add or remove "//" before #define) + + +// this shadertoy use ALPHA, NO_ALPHA set alpha to 1, BG_ALPHA set background as alpha +// iChannel0 used as background if alpha ignored by wallpaper-app +//#define NO_ALPHA +//#define BG_ALPHA +//#define SHADOW_ALPHA +//#define ONLY_BOX + + +// save PERFORMANCE by disabling shadow +//#define NO_SHADOW + + +// static CAMERA position, 0.49 on top, 0.001 horizontal +//#define CAMERA_POS 0.049 + + +// speed of ROTATION +#define ROTATION_SPEED 0.8999 + + +// static SHAPE form, default 0.5 +//#define STATIC_SHAPE 0.15 + + +// static SCALE far/close to camera, 2.0 is default, exampe 0.5 or 10.0 +//#define CAMERA_FAR 0.1 + + +// ANIMATION shape change +//#define ANIM_SHAPE + + +// ANIMATION color change +//#define ANIM_COLOR + + +// custom COLOR, and change those const values +//#define USE_COLOR +const vec3 color_blue=vec3(0.5,0.65,0.8); +const vec3 color_red=vec3(0.99,0.2,0.1); + + +// use 4xAA for cube only (set 2-4-etc level of AA) +//#define AA_CUBE 4 + +// use 4xAA for everything - derivative filtering will not be used, look fcos2 +// this is very slow - DO NOT USE +//#define AA_ALL 4 + + + +// --shader code-- + +// Layers sorted and support transparency and self-intersection-transparency +// Antialiasing is only dFd. (with some dFd fixes around edges) + +// using iq's intersectors: https://iquilezles.org/articles/intersectors +// using https://www.shadertoy.com/view/ltKBzG +// using https://www.shadertoy.com/view/tsVXzh +// using https://www.shadertoy.com/view/WlffDn +// using https://www.shadertoy.com/view/WslGz4 + +#define tshift 53. + +// reflect back side +//#define backside_refl + +// Camera with mouse +// #define MOUSE_control (disabled - no iMouse support) + +// min(iFrame,0) does not speedup compilation in ANGLE +#define ANGLE_loops 0 + + +// this shader discover Nvidia bug with arrays https://www.shadertoy.com/view/NslGR4 +// use DEBUG with BUG, BUG trigger that bug and one layer will be white on Nvidia in OpenGL +//#define DEBUG +//#define BUG + +#define FDIST 0.7 +#define PI 3.1415926 +#define GROUNDSPACING 0.5 +#define GROUNDGRID 0.05 +#define BOXDIMS vec3(0.75, 0.75, 1.25) + +#define IOR 1.33 + +mat3 rotx(float a){float s = sin(a);float c = cos(a);return mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, c, s), vec3(0.0, -s, c)); } +mat3 roty(float a){float s = sin(a);float c = cos(a);return mat3(vec3(c, 0.0, s), vec3(0.0, 1.0, 0.0), vec3(-s, 0.0, c));} +mat3 rotz(float a){float s = sin(a);float c = cos(a);return mat3(vec3(c, s, 0.0), vec3(-s, c, 0.0), vec3(0.0, 0.0, 1.0 ));} + +vec3 fcos1(vec3 x) { + vec3 w = fwidth(x); + //if((length(w)==0.))return vec3(0.); // dFd fix2 + //w*=0.; //test + float lw=length(w); + if((lw==0.)||isnan(lw)||isinf(lw)){vec3 tc=vec3(0.); for(int i=0;i<8;i++)tc+=cos(x+x*float(i-4)*(0.01*400./iResolution.y));return tc/8.;} + + return cos(x) * smoothstep(3.14 * 2.0, 0.0, w); +} + +vec3 fcos2( vec3 x){return cos(x);} +vec3 fcos( vec3 x){ +#ifdef AA_ALL + return fcos2(x); +#else + return fcos1(x); +#endif +} + +vec3 getColor(vec3 p) +{ + // dFd fix, dFd broken on borders, but it fix only top level dFd, self intersection has border + //if (length(p) > 0.99)return vec3(0.); + p = abs(p); + + p *= 01.25; + p = 0.5 * p / dot(p, p); +#ifdef ANIM_COLOR + p+=0.072*iTime; +#endif + + float t = (0.13) * length(p); + vec3 col = vec3(0.3, 0.4, 0.5); + col += 0.12 * fcos(6.28318 * t * 1.0 + vec3(0.0, 0.8, 1.1)); + col += 0.11 * fcos(6.28318 * t * 3.1 + vec3(0.3, 0.4, 0.1)); + col += 0.10 * fcos(6.28318 * t * 5.1 + vec3(0.1, 0.7, 1.1)); + col += 0.10 * fcos(6.28318 * t * 17.1 + vec3(0.2, 0.6, 0.7)); + col += 0.10 * fcos(6.28318 * t * 31.1 + vec3(0.1, 0.6, 0.7)); + col += 0.10 * fcos(6.28318 * t * 65.1 + vec3(0.0, 0.5, 0.8)); + col += 0.10 * fcos(6.28318 * t * 115.1 + vec3(0.1, 0.4, 0.7)); + col += 0.10 * fcos(6.28318 * t * 265.1 + vec3(1.1, 1.4, 2.7)); + col = clamp(col, 0., 1.); + + return col; +} + +void calcColor(vec3 ro, vec3 rd, vec3 nor, float d, float len, int idx, bool si, float td, out vec4 colx, + out vec4 colsi) +{ + + vec3 pos = (ro + rd * d); +#ifdef DEBUG + float a = 1. - smoothstep(len - 0.15, len + 0.00001, length(pos)); + if (idx == 0)colx = vec4(1., 0., 0., a); + if (idx == 1)colx = vec4(0., 1., 0., a); + if (idx == 2)colx = vec4(0., 0., 1., a); + if (si) + { + pos = (ro + rd * td); + float ta = 1. - smoothstep(len - 0.15, len + 0.00001, length(pos)); + if (idx == 0)colsi = vec4(1., 0., 0., ta); + if (idx == 1)colsi = vec4(0., 1., 0., ta); + if (idx == 2)colsi = vec4(0., 0., 1., ta); + } +#else + float a = 1. - smoothstep(len - 0.15*0.5, len + 0.00001, length(pos)); + //a=1.; + vec3 col = getColor(pos); + colx = vec4(col, a); + if (si) + { + pos = (ro + rd * td); + float ta = 1. - smoothstep(len - 0.15*0.5, len + 0.00001, length(pos)); + //ta=1.; + col = getColor(pos); + colsi = vec4(col, ta); + } +#endif +} + +// xSI is self intersect data, fade to fix dFd on edges +bool iBilinearPatch(in vec3 ro, in vec3 rd, in vec4 ps, in vec4 ph, in float sz, out float t, out vec3 norm, + out bool si, out float tsi, out vec3 normsi, out float fade, out float fadesi) +{ + vec3 va = vec3(0.0, 0.0, ph.x + ph.w - ph.y - ph.z); + vec3 vb = vec3(0.0, ps.w - ps.y, ph.z - ph.x); + vec3 vc = vec3(ps.z - ps.x, 0.0, ph.y - ph.x); + vec3 vd = vec3(ps.xy, ph.x); + t = -1.; + tsi = -1.; + si = false; + fade = 1.; + fadesi = 1.; + norm=vec3(0.,1.,0.);normsi=vec3(0.,1.,0.); + + float tmp = 1.0 / (vb.y * vc.x); + float a = 0.0; + float b = 0.0; + float c = 0.0; + float d = va.z * tmp; + float e = 0.0; + float f = 0.0; + float g = (vc.z * vb.y - vd.y * va.z) * tmp; + float h = (vb.z * vc.x - va.z * vd.x) * tmp; + float i = -1.0; + float j = (vd.x * vd.y * va.z + vd.z * vb.y * vc.x) * tmp - (vd.y * vb.z * vc.x + vd.x * vc.z * vb.y) * tmp; + + float p = dot(vec3(a, b, c), rd.xzy * rd.xzy) + dot(vec3(d, e, f), rd.xzy * rd.zyx); + float q = dot(vec3(2.0, 2.0, 2.0) * ro.xzy * rd.xyz, vec3(a, b, c)) + dot(ro.xzz * rd.zxy, vec3(d, d, e)) + + dot(ro.yyx * rd.zxy, vec3(e, f, f)) + dot(vec3(g, h, i), rd.xzy); + float r = + dot(vec3(a, b, c), ro.xzy * ro.xzy) + dot(vec3(d, e, f), ro.xzy * ro.zyx) + dot(vec3(g, h, i), ro.xzy) + j; + + if (abs(p) < 0.000001) + { + float tt = -r / q; + if (tt <= 0.) + return false; + t = tt; + // normal + + vec3 pos = ro + t * rd; + if(length(pos)>sz)return false; + vec3 grad = + vec3(2.0) * pos.xzy * vec3(a, b, c) + pos.zxz * vec3(d, d, e) + pos.yyx * vec3(f, e, f) + vec3(g, h, i); + norm = -normalize(grad); + return true; + } + else + { + float sq = q * q - 4.0 * p * r; + if (sq < 0.0) + { + return false; + } + else + { + float s = sqrt(sq); + float t0 = (-q + s) / (2.0 * p); + float t1 = (-q - s) / (2.0 * p); + float tt1 = min(t0 < 0.0 ? t1 : t0, t1 < 0.0 ? t0 : t1); + float tt2 = max(t0 > 0.0 ? t1 : t0, t1 > 0.0 ? t0 : t1); + float tt0 = tt1; + if (tt0 <= 0.) + return false; + vec3 pos = ro + tt0 * rd; + // black border on end of circle and self intersection with alpha come because dFd + // uncomment this to see or rename fcos2 to fcos + //sz+=0.3; + bool ru = step(sz, length(pos)) > 0.5; + if (ru) + { + tt0 = tt2; + pos = ro + tt0 * rd; + } + if (tt0 <= 0.) + return false; + bool ru2 = step(sz, length(pos)) > 0.5; + if (ru2) + return false; + + // self intersect + if ((tt2 > 0.) && ((!ru)) && !(step(sz, length(ro + tt2 * rd)) > 0.5)) + { + si = true; + fadesi=s; + tsi = tt2; + vec3 tpos = ro + tsi * rd; + // normal + vec3 tgrad = vec3(2.0) * tpos.xzy * vec3(a, b, c) + tpos.zxz * vec3(d, d, e) + + tpos.yyx * vec3(f, e, f) + vec3(g, h, i); + normsi = -normalize(tgrad); + } + + fade=s; + t = tt0; + // normal + vec3 grad = + vec3(2.0) * pos.xzy * vec3(a, b, c) + pos.zxz * vec3(d, d, e) + pos.yyx * vec3(f, e, f) + vec3(g, h, i); + norm = -normalize(grad); + + return true; + } + } +} + +float dot2( in vec3 v ) { return dot(v,v); } + +float segShadow( in vec3 ro, in vec3 rd, in vec3 pa, float sh ) +{ + float dm = dot(rd.yz,rd.yz); + float k1 = (ro.x-pa.x)*dm; + float k2 = (ro.x+pa.x)*dm; + vec2 k5 = (ro.yz+pa.yz)*dm; + float k3 = dot(ro.yz+pa.yz,rd.yz); + vec2 k4 = (pa.yz+pa.yz)*rd.yz; + vec2 k6 = (pa.yz+pa.yz)*dm; + + for( int i=0; i<4 + ANGLE_loops; i++ ) + { + vec2 s = vec2(i&1,i>>1); + float t = dot(s,k4) - k3; + + if( t>0.0 ) + sh = min(sh,dot2(vec3(clamp(-rd.x*t,k1,k2),k5-k6*s)+rd*t)/(t*t)); + } + return sh; +} + +float boxSoftShadow( in vec3 ro, in vec3 rd, in vec3 rad, in float sk ) +{ + rd += 0.0001 * (1.0 - abs(sign(rd))); + vec3 rdd = rd; + vec3 roo = ro; + + vec3 m = 1.0/rdd; + vec3 n = m*roo; + vec3 k = abs(m)*rad; + + vec3 t1 = -n - k; + vec3 t2 = -n + k; + + float tN = max( max( t1.x, t1.y ), t1.z ); + float tF = min( min( t2.x, t2.y ), t2.z ); + + if( tN0.0) return 0.0; + + float sh = 1.0; + sh = segShadow( roo.xyz, rdd.xyz, rad.xyz, sh ); + sh = segShadow( roo.yzx, rdd.yzx, rad.yzx, sh ); + sh = segShadow( roo.zxy, rdd.zxy, rad.zxy, sh ); + sh = clamp(sk*sqrt(sh),0.0,1.0); + return sh*sh*(3.0-2.0*sh); +} + +float box(in vec3 ro, in vec3 rd, in vec3 r, out vec3 nn, bool entering) +{ + rd += 0.0001 * (1.0 - abs(sign(rd))); + vec3 dr = 1.0 / rd; + vec3 n = ro * dr; + vec3 k = r * abs(dr); + + vec3 pin = -k - n; + vec3 pout = k - n; + float tin = max(pin.x, max(pin.y, pin.z)); + float tout = min(pout.x, min(pout.y, pout.z)); + if (tin > tout) + return -1.; + if (entering) + { + nn = -sign(rd) * step(pin.zxy, pin.xyz) * step(pin.yzx, pin.xyz); + } + else + { + nn = sign(rd) * step(pout.xyz, pout.zxy) * step(pout.xyz, pout.yzx); + } + return entering ? tin : tout; +} + +vec3 bgcol(in vec3 rd) +{ + return mix(vec3(0.01), vec3(0.336, 0.458, .668), 1. - pow(abs(rd.z+0.25), 1.3)); +} + +vec3 background(in vec3 ro, in vec3 rd , vec3 l_dir, out float alpha) +{ +#ifdef ONLY_BOX +alpha=0.; +return vec3(0.01); +#endif + float t = (-BOXDIMS.z - ro.z) / rd.z; + alpha=0.; + vec3 bgc = bgcol(rd); + if (t < 0.) + return bgc; + vec2 uv = ro.xy + t * rd.xy; +#ifdef NO_SHADOW + float shad=1.; +#else + float shad = boxSoftShadow((ro + t * rd), normalize(l_dir+vec3(0.,0.,1.))*rotz(PI*0.65) , BOXDIMS, 1.5); +#endif + float aofac = smoothstep(-0.95, .75, length(abs(uv) - min(abs(uv), vec2(0.45)))); + aofac = min(aofac,smoothstep(-0.65, 1., shad)); + float lght=max(dot(normalize(ro + t * rd+vec3(0.,-0.,-5.)), normalize(l_dir-vec3(0.,0.,1.))*rotz(PI*0.65)), 0.0); + vec3 col = mix(vec3(0.4), vec3(.71,.772,0.895), lght*lght* aofac+ 0.05) * aofac; + alpha=1.-smoothstep(7.,10.,length(uv)); +#ifdef SHADOW_ALPHA + //alpha=clamp(alpha*max(lght*lght*0.95,(1.-aofac)*1.25),0.,1.); + alpha=clamp(alpha*(1.-aofac)*1.25,0.,1.); +#endif + return mix(col*length(col)*0.8,bgc,smoothstep(7.,10.,length(uv))); +} + +#define swap(a,b) tv=a;a=b;b=tv + +vec4 insides(vec3 ro, vec3 rd, vec3 nor_c, vec3 l_dir, out float tout) +{ + tout = -1.; + vec3 trd=rd; + + vec3 col = vec3(0.); + + float pi = 3.1415926; + + if (abs(nor_c.x) > 0.5) + { + rd = rd.xzy * nor_c.x; + ro = ro.xzy * nor_c.x; + } + else if (abs(nor_c.z) > 0.5) + { + l_dir *= roty(pi); + rd = rd.yxz * nor_c.z; + ro = ro.yxz * nor_c.z; + } + else if (abs(nor_c.y) > 0.5) + { + l_dir *= rotz(-pi * 0.5); + rd = rd * nor_c.y; + ro = ro * nor_c.y; + } + +#ifdef ANIM_SHAPE + float curvature = (0.001+1.5-1.5*smoothstep(0.,8.5,mod((iTime+tshift)*0.44,20.))*(1.-smoothstep(10.,18.5,mod((iTime+tshift)*0.44,20.)))); + // curvature(to not const above) make compilation on Angle 15+ sec +#else +#ifdef STATIC_SHAPE + const float curvature = STATIC_SHAPE; +#else + const float curvature = .5; +#endif +#endif + float bil_size = 1.; + vec4 ps = vec4(-bil_size, -bil_size, bil_size, bil_size) * curvature; + vec4 ph = vec4(-bil_size, bil_size, bil_size, -bil_size) * curvature; + + vec4 [3]colx=vec4[3](vec4(0.),vec4(0.),vec4(0.)); + vec3 [3]dx=vec3[3](vec3(-1.),vec3(-1.),vec3(-1.)); + vec4 [3]colxsi=vec4[3](vec4(0.),vec4(0.),vec4(0.)); + int [3]order=int[3](0,1,2); + + for (int i = 0; i < 3 + ANGLE_loops; i++) + { + if (abs(nor_c.x) > 0.5) + { + ro *= rotz(-pi * (1. / float(3))); + rd *= rotz(-pi * (1. / float(3))); + } + else if (abs(nor_c.z) > 0.5) + { + ro *= rotz(pi * (1. / float(3))); + rd *= rotz(pi * (1. / float(3))); + } + else if (abs(nor_c.y) > 0.5) + { + ro *= rotx(pi * (1. / float(3))); + rd *= rotx(pi * (1. / float(3))); + } + vec3 normnew; + float tnew; + bool si; + float tsi; + vec3 normsi; + float fade; + float fadesi; + + if (iBilinearPatch(ro, rd, ps, ph, bil_size, tnew, normnew, si, tsi, normsi, fade, fadesi)) + { + if (tnew > 0.) + { + vec4 tcol, tcolsi; + calcColor(ro, rd, normnew, tnew, bil_size, i, si, tsi, tcol, tcolsi); + if (tcol.a > 0.0) + { + { + vec3 tvalx = vec3(tnew, float(si), tsi); + dx[i]=tvalx; + } +#ifdef DEBUG + colx[i]=tcol; + if (si)colxsi[i]=tcolsi; +#else + + float dif = clamp(dot(normnew, l_dir), 0.0, 1.0); + float amb = clamp(0.5 + 0.5 * dot(normnew, l_dir), 0.0, 1.0); + + { +#ifdef USE_COLOR + vec3 shad = 0.57 * color_blue * amb + 1.5*color_blue.bgr * dif; + const vec3 tcr = color_red; +#else + vec3 shad = vec3(0.32, 0.43, 0.54) * amb + vec3(1.0, 0.9, 0.7) * dif; + const vec3 tcr = vec3(1.,0.21,0.11); +#endif + float ta = clamp(length(tcol.rgb),0.,1.); + tcol=clamp(tcol*tcol*2.,0.,1.); + vec4 tvalx = + vec4((tcol.rgb*shad*1.4 + 3.*(tcr*tcol.rgb)*clamp(1.-(amb+dif),0.,1.)), min(tcol.a,ta)); + tvalx.rgb=clamp(2.*tvalx.rgb*tvalx.rgb,0.,1.); + tvalx*=(min(fade*5.,1.)); + colx[i]=tvalx; + } + if (si) + { + dif = clamp(dot(normsi, l_dir), 0.0, 1.0); + amb = clamp(0.5 + 0.5 * dot(normsi, l_dir), 0.0, 1.0); + { +#ifdef USE_COLOR + vec3 shad = 0.57 * color_blue * amb + 1.5*color_blue.bgr * dif; + const vec3 tcr = color_red; +#else + vec3 shad = vec3(0.32, 0.43, 0.54) * amb + vec3(1.0, 0.9, 0.7) * dif; + const vec3 tcr = vec3(1.,0.21,0.11); +#endif + float ta = clamp(length(tcolsi.rgb),0.,1.); + tcolsi=clamp(tcolsi*tcolsi*2.,0.,1.); + vec4 tvalx = + vec4(tcolsi.rgb * shad + 3.*(tcr*tcolsi.rgb)*clamp(1.-(amb+dif),0.,1.), min(tcolsi.a,ta)); + tvalx.rgb=clamp(2.*tvalx.rgb*tvalx.rgb,0.,1.); + tvalx.rgb*=(min(fadesi*5.,1.)); + colxsi[i]=tvalx; + } + } +#endif + } + } + } + } + // transparency logic and layers sorting + float a = 1.; + if (dx[0].x < dx[1].x){{vec3 swap(dx[0], dx[1]);}{int swap(order[0], order[1]);}} + if (dx[1].x < dx[2].x){{vec3 swap(dx[1], dx[2]);}{int swap(order[1], order[2]);}} + if (dx[0].x < dx[1].x){{vec3 swap(dx[0], dx[1]);}{int swap(order[0], order[1]);}} + + tout = max(max(dx[0].x, dx[1].x), dx[2].x); + + if (dx[0].y < 0.5) + { + a=colx[order[0]].a; + } + +#if !(defined(DEBUG)&&defined(BUG)) + + // self intersection + bool [3] rul= bool[3]( + ((dx[0].y > 0.5) && (dx[1].x <= 0.)), + ((dx[1].y > 0.5) && (dx[0].x > dx[1].z)), + ((dx[2].y > 0.5) && (dx[1].x > dx[2].z)) + ); + for(int k=0;k<3;k++){ + if(rul[k]){ + vec4 tcolxsi = vec4(0.); + tcolxsi=colxsi[order[k]]; + vec4 tcolx = vec4(0.); + tcolx=colx[order[k]]; + + vec4 tvalx = mix(tcolxsi, tcolx, tcolx.a); + colx[order[k]]=tvalx; + + vec4 tvalx2 = mix(vec4(0.), tvalx, max(tcolx.a, tcolxsi.a)); + colx[order[k]]=tvalx2; + } + } + +#endif + + float a1 = (dx[1].y < 0.5) ? colx[order[1]].a : ((dx[1].z > dx[0].x) ? colx[order[1]].a : 1.); + float a2 = (dx[2].y < 0.5) ? colx[order[2]].a : ((dx[2].z > dx[1].x) ? colx[order[2]].a : 1.); + col = mix(mix(colx[order[0]].rgb, colx[order[1]].rgb, a1), colx[order[2]].rgb, a2); + a = max(max(a, a1), a2); + return vec4(col, a); +} + +void mainImage(out vec4 fragColor, in vec2 fragCoord) +{ + float osc = 0.5; + vec3 l_dir = normalize(vec3(0., 1., 0.)); + l_dir *= rotz(0.5); + float mouseY = 1.0 * 0.5 * PI; + // Note: MOUSE_control disabled (no iMouse support) + // #ifdef MOUSE_control + // mouseY = (1.0 - 1.15 * iMouse.y / iResolution.y) * 0.5 * PI; + // if(iMouse.y < 1.) + // #endif +#ifdef CAMERA_POS + mouseY = PI*CAMERA_POS; +#else + mouseY = PI*0.49 - smoothstep(0.,8.5,mod((iTime+tshift)*0.33,25.))*(1.-smoothstep(14.,24.0,mod((iTime+tshift)*0.33,25.))) * 0.55 * PI; +#endif +#ifdef ROTATION_SPEED + float mouseX = -2.*PI-0.25*(iTime*ROTATION_SPEED+tshift); +#else + float mouseX = -2.*PI-0.25*(iTime+tshift); +#endif + // Note: MOUSE_control disabled (no iMouse support) + // #ifdef MOUSE_control + // mouseX+=-(iMouse.x / iResolution.x) * 2. * PI; + // #endif + +#ifdef CAMERA_FAR + vec3 eye = (2. + CAMERA_FAR) * vec3(cos(mouseX) * cos(mouseY), sin(mouseX) * cos(mouseY), sin(mouseY)); +#else + vec3 eye = 4. * vec3(cos(mouseX) * cos(mouseY), sin(mouseX) * cos(mouseY), sin(mouseY)); +#endif + vec3 w = normalize(-eye); + vec3 up = vec3(0., 0., 1.); + vec3 u = normalize(cross(w, up)); + vec3 v = cross(u, w); + + vec4 tot=vec4(0.); +#if defined(AA_CUBE)||defined(AA_ALL) +#ifdef AA_CUBE + const int AA = AA_CUBE; +#else + const int AA = AA_ALL; +#endif + vec3 incol_once=vec3(0.); + bool in_once=false; + vec4 incolbg_once=vec4(0.); + bool bg_in_once=false; + vec4 outcolbg_once=vec4(0.); + bool bg_out_once=false; + for( int mx=0; mx 0.) + { + float ang = -iTime * 0.33; + vec3 col = vec3(0.); +#ifdef AA_CUBE + if(in_once)col=incol_once; + else{ + in_once=true; +#endif + float R0 = (IOR - 1.) / (IOR + 1.); + R0 *= R0; + + vec2 theta = vec2(0.); + vec3 n = vec3(cos(theta.x) * sin(theta.y), sin(theta.x) * sin(theta.y), cos(theta.y)); + + vec3 nr = n.zxy * ni.x + n.yzx * ni.y + n.xyz * ni.z; + vec3 rdr = reflect(rd, nr); + float talpha; + vec3 reflcol = background(ro, rdr, l_dir,talpha); + + vec3 rd2 = refract(rd, nr, 1. / IOR); + + float accum = 1.; + vec3 no2 = ni; + vec3 ro_refr = ro; + + vec4 [2] colo = vec4[2](vec4(0.),vec4(0.)); + + for (int j = 0; j < 2 + ANGLE_loops; j++) + { + float tb; + vec2 coords2 = ro_refr.xy * no2.z + ro_refr.yz * no2.x + ro_refr.zx * no2.y; + vec3 eye2 = vec3(coords2, -1.); + vec3 rd2trans = rd2.yzx * no2.x + rd2.zxy * no2.y + rd2.xyz * no2.z; + + rd2trans.z = -rd2trans.z; + vec4 internalcol = insides(eye2, rd2trans, no2, l_dir, tb); + if (tb > 0.) + { + internalcol.rgb *= accum; + colo[j]=internalcol; + } + + if ((tb <= 0.) || (internalcol.a < 1.)) + { + float tout = box(ro_refr, rd2, BOXDIMS, no2, false); + no2 = n.zyx * no2.x + n.xzy * no2.y + n.yxz * no2.z; + vec3 rout = ro_refr + tout * rd2; + vec3 rdout = refract(rd2, -no2, IOR); + float fresnel2 = R0 + (1. - R0) * pow(1. - dot(rdout, no2), 1.3); + rd2 = reflect(rd2, -no2); + +#ifdef backside_refl + if((dot(rdout, no2))>0.5){fresnel2=1.;} +#endif + ro_refr = rout; + ro_refr.z = max(ro_refr.z, -0.999); + + accum *= fresnel2; + } + } + float fresnel = R0 + (1. - R0) * pow(1. - dot(-rd, nr), 5.); + col = mix(mix(colo[1].rgb * colo[1].a, colo[0].rgb, colo[0].a)*fadeborders, reflcol, pow(fresnel, 1.5)); + col=clamp(col,0.,1.); +#ifdef AA_CUBE + } + incol_once=col; + if(!bg_in_once){ + bg_in_once=true; + float alpha; + incolbg_once = vec4(background(eye, rd, l_dir, alpha), 0.15); +#if defined(BG_ALPHA)||defined(ONLY_BOX)||defined(SHADOW_ALPHA) + incolbg_once.w = alpha; +#endif + } +#endif + + float cineshader_alpha = 0.; + cineshader_alpha = clamp(0.15*dot(eye,ro),0.,1.); + vec4 tcolx = vec4(col, cineshader_alpha); +#if defined(BG_ALPHA)||defined(ONLY_BOX)||defined(SHADOW_ALPHA) + tcolx.w = 1.; +#endif + tot += tcolx; + } + else + { + vec4 tcolx = vec4(0.); +#ifdef AA_CUBE + if(!bg_out_once){ + bg_out_once=true; +#endif + float alpha; + tcolx = vec4(background(eye, rd, l_dir, alpha), 0.15); +#if defined(BG_ALPHA)||defined(ONLY_BOX)||defined(SHADOW_ALPHA) + tcolx.w = alpha; +#endif +#ifdef AA_CUBE + outcolbg_once=tcolx; + }else tcolx=max(outcolbg_once,incolbg_once); +#endif + tot += tcolx; + } +#if defined(AA_CUBE)||defined(AA_ALL) + } + tot /= float(AA*AA); +#endif + fragColor = tot; +#ifdef NO_ALPHA + fragColor.w = 1.; +#endif + fragColor.rgb=clamp(fragColor.rgb,0.,1.); + // Note: iChannel0 line removed (texture channel not supported) + // Original line was for optional background blending when BG_ALPHA/ONLY_BOX/SHADOW_ALPHA defined + // #if defined(BG_ALPHA)||defined(ONLY_BOX)||defined(SHADOW_ALPHA) + // fragColor.rgb=fragColor.rgb*fragColor.w+texture(iChannel0, fragCoord/iResolution.xy).rgb*(1.-fragColor.w); + // #endif +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/dbz/dbz.frag.msl b/shaders/dbz/dbz.frag.msl new file mode 100644 index 0000000..aff2880 --- /dev/null +++ b/shaders/dbz/dbz.frag.msl @@ -0,0 +1,127 @@ +#include +using namespace metal; + +// New Leaked 3I/Atlas NASA Footage — msm01 +// MSL port of dbz.vk.glsl. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +constant float NBCaps = 3.0; + +static float2x2 r2d(float a) { + float c = cos(a), s = sin(a); + return float2x2(c, s, -s, c); +} + +static float hash12(float2 p) { + float3 p3 = fract(float3(p.xyx) * 0.1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +static float fbm(float2 v_p) { + float pvpx = v_p.x; + float2 V1 = float2(floor(pvpx)); + float2 V2 = float2(floor(pvpx + 1.0)); + return mix(hash12(V1), hash12(V2), smoothstep(0.0, 1.0, fract(pvpx))); +} + +#define S(a,b,c) smoothstep(a,b,c) + +fragment float4 dbz_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float2 p = float2((1.0 / U.iResolution.y) * (fragCoord.x - U.iResolution.x / 2.0), + fragCoord.y / U.iResolution.y - 0.5); + + p.x = -p.x; + p *= 150.0; + + float4 col = float4(0.05, 0.05, 0.15, 1.0); + + float2 save1 = p; + + p = p * r2d(-0.05); + col = mix(col, float4(0.2, 0.3, 0.5, 1.0), + smoothstep(75.0, 0.0, abs(p.y - 5.0 * fbm(float2(0.01 * (p.x - 33.333 * U.iTime))) + 3.5))); + p = p * r2d(0.05); + + p = p * r2d(-0.05); + p *= 0.35; + p += float2(-5.0 * U.iTime, 0.0); + + float2 b = fract(5.0 * p); + p = floor(5.0 * p); + if (fbm(float2(p.x * p.y)) > 0.996) { + col += clamp(1.0 - pow(3.0 * length(b + float2(-0.5)), 0.5), 0.0, 1.0); + } + + p = save1; + float2 save3; + + float Nb_Capsules = clamp(NBCaps, 0.0, 4.0); + for (float i = 0.0; i < Nb_Capsules; i++) { + p = save1; + p = p * r2d(-0.05); + p *= 2.5; + p *= 1.0 - 0.25 * i; + p += float2(150.0 * fbm(float2(0.15 * U.iTime + i * 54.321)) - 75.0, + 50.0 * sin(0.25 * U.iTime + i * 54.321) - 25.0); + save3 = p; + + p *= 0.04; + p.y = abs(p.y); + + if (p.x > 0.0) { + col += float4(0.0, 1.0, 0.5, 1.0) * smoothstep(0.2, 0.0, abs(p.y - 0.05 * fbm(float2(1.5 * p.x - 40.0 * U.iTime))) - 0.05) * smoothstep(29.0, 0.0, abs(p.x)); + col += float4(1.0, 1.0, 1.0, 1.0) * smoothstep(0.1, 0.0, abs(p.y - 0.05 * fbm(float2(1.5 * p.x - 40.0 * U.iTime))) - 0.05) * smoothstep(29.0, 0.0, abs(p.x)); + } + + p = save3; + p.y = abs(p.y); + p += float2(-10.0, 0.0); + p *= float2(0.75, 1.0); + + col += 0.8 * float4(0.0, 1.0, 0.5, 1.0) * S(20.0, 0.0, length(p) - 25.0 + 7.0 * sin(0.30 * length(p) * atan2(p.y, p.x) + 55.0 * U.iTime)); + col += 0.8 * float4(1.0, 1.0, 1.0, 1.0) * S(20.0, 0.0, length(p) - 20.0 + 7.0 * sin(0.30 * length(p) * atan2(p.y, p.x) + 55.0 * U.iTime)); + + p = save3; + + col = mix(col, float4(1.0), 0.5 * S(10.0, 0.0, length(p + float2(5.0, 0.0)) - 20.0) * abs(sin(50.0 * U.iTime))); + col = mix(col, float4(1.0), 0.5 * S(20.0, 0.0, length(p + float2(5.0, 0.0)) - 20.0)); + col = mix(col, float4(1.0), S(0.01, 0.0, length(p) - 20.0)); + + if (length(p) - 20.0 < 0.0) { + col = mix(col, float4(0.65, 0.68, 0.68 + 0.1 * (3.0 - i), 1.0), S(0.5, 0.0, length(p - float2(2.0, 0.0)) - 17.0)); + if (S(0.0, 1.0, length(float2(3.0, 2.0) * p + float2(33.5, 0.0)) - 23.0) > 0.0) { + col = mix(col, float4(0.45, 0.55, 0.55 + 0.1 * (3.0 - i), 1.0), + 0.75 * S(0.5, 0.0, length(p - float2(2.0, 0.0) + 0.5 * fbm(float2(4.5 * atan2(p.y, p.x)))) - 9.0)); + } + + col = mix(col, float4(0.0), S(0.2, 0.0, abs(length(p) - 19.9) - 0.20)); + col = mix(col, float4(0.5, 0.2, 0.3, 1.0) + - S(5.0, 0.0, length(p + float2(-6.0, 15.0)) - 20.0) + - S(0.25, 0.0, abs(length(p + float2(0.0, 3.0)) - 15.0) - 0.4) + - S(0.0, 1.5, p.y - 8.5) + + 0.25 * float4(1.0, 0.5, 0.0, 1.0) * S(10.0, 0.0, abs(p.y)) + , + S(0.5, 0.0, length(float2(3.0, 2.0) * p + float2(35.0, 0.0)) - 19.9)); + + col = mix(col, float4(0.0, 0.0, 0.0, 1.0), S(1.0, 0.0, abs(length(float2(3.0, 2.0) * p + float2(35.0, 0.0)) - 19.9) - 0.1)); + col = mix(col, float4(0.0, 0.0, 0.0, 1.0), S(1.0, 0.0, abs(length(float2(3.0, 2.0) * p + float2(33.5, 0.0)) - 23.0) - 0.1)); + + if (p.y > 0.0) col = mix(col, float4(0.0, 0.0, 0.0, 1.0), S(1.0, 0.0, abs(length(float2(3.0, 2.0) * p + float2(29.0, 0.0)) - 30.0) - 0.1)); + if (p.y < 0.0) col = mix(col, float4(0.0, 0.0, 0.0, 1.0), S(1.0, 0.0, abs(length(float2(3.0, 2.0) * p + float2(-31.0, 0.0)) - 30.0) - 0.1)); + } + } + + return clamp(col, 0.0, 1.0); +} diff --git a/shaders/dbz/dbz.frag.spv b/shaders/dbz/dbz.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..716fe9b1c75b37e1da02bfd4ff06205a7767b013 GIT binary patch literal 14872 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 literal 0 HcmV?d00001 diff --git a/shaders/dbz/dbz.vk.glsl b/shaders/dbz/dbz.vk.glsl new file mode 100644 index 0000000..0419868 --- /dev/null +++ b/shaders/dbz/dbz.vk.glsl @@ -0,0 +1,127 @@ +#version 450 + +// Name: New Leaked 3I/Atlas NASA Footage +// Author: msm01 +// URL: https://www.shadertoy.com/view/3ftcRr + +layout(location = 0) in vec2 vUV; +layout(location = 0) out vec4 FragColor; + +layout(set = 3, binding = 0) uniform ShadertoyUBO { + float iTime; + vec2 iResolution; +}; + +#define s(a,b,c) smoothstep(a,b,c) +#define PI 3.14159 +#define NBCaps 3. + +mat2 r2d(float a) { float c = cos(a), s = sin(a); return mat2(c, s, -s, c); } +float metaDiamond(vec2 p, vec2 pixel, float r) { vec2 d = abs(p - pixel); return r / (d.x + d.y); } + +float hash12(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +float fbm(in vec2 v_p) { + float pvpx = v_p.x; + vec2 V1 = vec2(floor(pvpx)); + vec2 V2 = vec2(floor(pvpx + 1.0)); + return mix(hash12(V1), hash12(V2), smoothstep(0.0, 1.0, fract(pvpx))); +} + +void mainImage(out vec4 fragColor, in vec2 fragCoord) { + vec2 p = vec2((1.0 / iResolution.y) * (fragCoord.x - iResolution.x / 2.0), + fragCoord.y / iResolution.y - 0.5); + + p.x = -p.x; + p *= 150.0; + + vec4 col = vec4(0.05, 0.05, 0.15, 1.0); + + vec2 save1 = p; + vec2 save2 = p; + + p *= r2d(-0.05); + col = mix(col, vec4(0.2, 0.3, 0.5, 1.0), + smoothstep(75.0, 0.0, abs(p.y - 5.0 * fbm(vec2(0.01 * (p.x - 33.333 * iTime))) + 3.5))); + p *= r2d(0.05); + + p *= r2d(-0.05); + p *= 0.35; + p += vec2(-5.0 * iTime, 0.0); + + vec2 b = fract(5.0 * p); + p = floor(5.0 * p); + if (fbm(vec2(p.x * p.y)) > 0.996) col += clamp(1.0 - pow(3.0 * length(b + vec2(-0.5)), 0.5), 0.0, 1.0); + + p = save1; + vec2 save3; + + float Nb_Capsules = clamp(NBCaps, 0.0, 4.0); + for (float i = 0.0; i < Nb_Capsules; i++) { + p = save1; + p *= r2d(-0.05); + p *= 2.5; + p *= 1.0 - 0.25 * i; + p += vec2(150.0 * fbm(vec2(0.15 * iTime + i * 54.321)) - 75.0, + 50.0 * sin(0.25 * iTime + i * 54.321) - 25.0); + save3 = p; + + p *= 0.04; + p.y = abs(p.y); + + if (p.x > 0.0) { + col += vec4(0.0, 1.0, 0.5, 1.0) * smoothstep(0.2, 0.0, abs(p.y - 0.05 * fbm(vec2(1.5 * p.x - 40.0 * iTime))) - 0.05) * smoothstep(29.0, 0.0, abs(p.x)); + col += vec4(1.0, 1.0, 1.0, 1.0) * smoothstep(0.1, 0.0, abs(p.y - 0.05 * fbm(vec2(1.5 * p.x - 40.0 * iTime))) - 0.05) * smoothstep(29.0, 0.0, abs(p.x)); + } + + p = save3; + p.y = abs(p.y); + p += vec2(-10.0, 0.0); + p *= vec2(0.75, 1.0); + + col += 0.8 * vec4(0.0, 1.0, 0.5, 1.0) * s(20.0, 0.0, length(p) - 25.0 + 7.0 * sin(0.30 * length(p) * atan(p.y, p.x) + 55.0 * iTime)); + col += 0.8 * vec4(1.0, 1.0, 1.0, 1.0) * s(20.0, 0.0, length(p) - 20.0 + 7.0 * sin(0.30 * length(p) * atan(p.y, p.x) + 55.0 * iTime)); + + p = save3; + + col = mix(col, vec4(1.0), 0.5 * s(10.0, 0.0, length(p + vec2(5.0, 0.0)) - 20.0) * abs(sin(50.0 * iTime))); + col = mix(col, vec4(1.0), 0.5 * s(20.0, 0.0, length(p + vec2(5.0, 0.0)) - 20.0)); + + col = mix(col, vec4(1.0), s(0.01, 0.0, length(p) - 20.0)); + + if (length(p) - 20.0 < 0.0) { + col = mix(col, vec4(0.65, 0.68, 0.68 + 0.1 * (3.0 - i), 1.0), s(0.5, 0.0, length(p - vec2(2.0, 0.0)) - 17.0)); + if (s(0.0, 1.0, length(vec2(3.0, 2.0) * p + vec2(33.5, 0.0)) - 23.0) > 0.0) + col = mix(col, vec4(0.45, 0.55, 0.55 + 0.1 * (3.0 - i), 1.0), + 0.75 * s(0.5, 0.0, length(p - vec2(2.0, 0.0) + 0.5 * fbm(vec2(4.5 * atan(p.y, p.x)))) - 9.0)); + + col = mix(col, vec4(0.0), s(0.2, 0.0, abs(length(p) - 19.9) - 0.20)); + col = mix(col, vec4(0.5, 0.2, 0.3, 1.0) + - s(5.0, 0.0, length(p + vec2(-6.0, 15.0)) - 20.0) + - s(0.25, 0.0, abs(length(p + vec2(0.0, 3.0)) - 15.0) - 0.4) + - s(0.0, 1.5, p.y - 8.5) + + 0.25 * vec4(1.0, 0.5, 0.0, 1.0) * s(10.0, 0.0, abs(p.y)) + , + s(0.5, 0.0, length(vec2(3.0, 2.0) * p + vec2(35.0, 0.0)) - 19.9)); + + col = mix(col, vec4(0.0, 0.0, 0.0, 1.0), s(1.0, 0.0, abs(length(vec2(3.0, 2.0) * p + vec2(35.0, 0.0)) - 19.9) - 0.1)); + col = mix(col, vec4(0.0, 0.0, 0.0, 1.0), s(1.0, 0.0, abs(length(vec2(3.0, 2.0) * p + vec2(33.5, 0.0)) - 23.0) - 0.1)); + + if (p.y > 0.0) col = mix(col, vec4(0.0, 0.0, 0.0, 1.0), s(1.0, 0.0, abs(length(vec2(3.0, 2.0) * p + vec2(29.0, 0.0)) - 30.0) - 0.1)); + if (p.y < 0.0) col = mix(col, vec4(0.0, 0.0, 0.0, 1.0), s(1.0, 0.0, abs(length(vec2(3.0, 2.0) * p + vec2(-31.0, 0.0)) - 30.0) - 0.1)); + } + } + + fragColor = clamp(col, 0.0, 1.0); +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/fractal_pyramid/fractal_pyramid.frag.msl b/shaders/fractal_pyramid/fractal_pyramid.frag.msl new file mode 100644 index 0000000..5403a15 --- /dev/null +++ b/shaders/fractal_pyramid/fractal_pyramid.frag.msl @@ -0,0 +1,67 @@ +#include +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); +} diff --git a/shaders/fractal_pyramid/fractal_pyramid.frag.spv b/shaders/fractal_pyramid/fractal_pyramid.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..a97a38e8a4d7bcedc5d3c4e147f38959fb8eb3e6 GIT binary patch literal 6728 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 100.0) break; + col += palette(length(p) * 0.1) / (400.0 * d); + t += d; + } + return vec4(col, 1.0 / (d * 100.0)); +} + +void mainImage(out vec4 fragColor, in vec2 fragCoord) { + vec2 uv = (fragCoord - (iResolution.xy * 0.5)) / iResolution.x; + vec3 ro = vec3(0.0, 0.0, -50.0); + ro.xz = rotate(ro.xz, iTime); + vec3 cf = normalize(-ro); + vec3 cs = normalize(cross(cf, vec3(0.0, 1.0, 0.0))); + vec3 cu = normalize(cross(cf, cs)); + + vec3 uuv = ro + cf * 3.0 + uv.x * cs + uv.y * cu; + vec3 rd = normalize(uuv - ro); + + vec4 col = rm(ro, rd); + fragColor = col; +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/just_another_cube/just_another_cube.frag.msl b/shaders/just_another_cube/just_another_cube.frag.msl new file mode 100644 index 0000000..a30666a --- /dev/null +++ b/shaders/just_another_cube/just_another_cube.frag.msl @@ -0,0 +1,89 @@ +#include +using namespace metal; + +// Just Another Cube — mrange +// MSL port of just_another_cube.vk.glsl. The Shadertoy original uses +// mutable file-scope globals; in MSL we pass them by reference. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +constant float M = 1e-3; + +static float D(float3 p, + thread float2x2& R, + thread float& d, + thread float& G) { + p.xy = p.xy * R; + p.xz = p.xz * R; + + float3 S = sin(123.0 * p); + + float shell = abs(length(p) - 0.6); + p *= p * p * p; + d = pow(dot(p, p), 0.125) - 0.5 + - pow(1.0 + S.x * S.y * S.z, 8.0) / 1e5; + + G = min(G, max(shell, d)); + + return d; +} + +fragment float4 just_another_cube_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 C = in.uv * U.iResolution; + + float2x2 R; + float d = 1.0, z = 0.0, G = 9.0; + + float3 r = float3(U.iResolution, U.iResolution.y); + float3 I = normalize(float3(C - 0.5 * r.xy, r.y)); + float3 B = float3(1, 2, 9) * M; + float3 p = float3(0.0); + float3 O = float3(0.0); + + { + float4 cs = cos(0.3 * U.iTime + float4(0, 11, 33, 0)); + R = float2x2(cs.x, cs.y, cs.z, cs.w); + } + + for (; z < 9.0 && d > M; z += D(p, R, d, G)) { + p = z * I; + p.z -= 2.0; + } + + if (z < 9.0) { + for (int i = 0; i < 3; ) { + r = float3(0.0); + r[i] = M; + O[i++] = D(p + r, R, d, G) - D(p - r, R, d, G); + } + + O = normalize(O); + z = 1.0 + dot(O, I); + + r = reflect(I, O); + + C = (p + r * (5.0 - p.y) / abs(r.y)).xz; + + float3 colorTerm; + if (r.y > 0.0) { + d = sqrt(length(C * C)) + 1.0; + colorTerm = 5e2 * smoothstep(5.0, 4.0, d) * d * B; + } else { + colorTerm = exp(-2.0 * length(C)) * (B / M - 1.0); + } + + O = z * z * colorTerm + pow(1.0 + O.y, 5.0) * B; + } + + float4 result = sqrt(float4(O + B / G, O.x + B.x / G)); + return result; +} diff --git a/shaders/just_another_cube/just_another_cube.frag.spv b/shaders/just_another_cube/just_another_cube.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..661fe27781e8677359733998cb3eed401de9176f GIT binary patch literal 6808 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 M; + z += D(p) + ) + p = z * I, + p.z -= 2.; + + O = vec3(0.0); + + if (z < 9.) { + for (int i = 0; i < 3; ) { + r -= r; + r[i] = M; + O[i++] = D(p + r) - D(p - r); + } + + z = 1. + dot(O = normalize(O), I); + + r = reflect(I, O); + + C = (p + r * (5. - p.y) / abs(r.y)).xz; + + O = + z * z * + ( + r.y > 0. + ? 5e2 * smoothstep(5., 4., d = sqrt(length(C * C)) + 1.) * d * B + : exp(-2. * length(C)) * (B / M - 1.) + ) + + pow(1. + O.y, 5.) * B; + } + + o = sqrt(O + B / G).xyzx; +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/octograms/octograms.frag.msl b/shaders/octograms/octograms.frag.msl new file mode 100644 index 0000000..1298725 --- /dev/null +++ b/shaders/octograms/octograms.frag.msl @@ -0,0 +1,95 @@ +#include +using namespace metal; + +// Octograms — whisky_shusuky +// MSL port of octograms.vk.glsl. The Shadertoy original uses a mutable +// file-scope `gTime`; in MSL we pass it as a parameter through the chain. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +static float2x2 rot(float a) { + float c = cos(a), s = sin(a); + return float2x2(c, s, -s, c); +} + +static float sdBox(float3 p, float3 b) { + float3 q = abs(p) - b; + return length(max(q, float3(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0); +} + +static float boxGeom(float3 pos, float scale) { + pos *= scale; + float base = sdBox(pos, float3(0.4, 0.4, 0.1)) / 1.5; + pos.xy = (pos.xy * 5.0 - float2(0.0, 3.5)) * rot(0.75); + return -base; +} + +static float box_set(float3 pos, float gTime) { + float3 pos_origin = pos; + + pos = pos_origin; + pos.y += sin(gTime * 0.4) * 2.5; + pos.xy = pos.xy * rot(0.8); + float box1 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.y -= sin(gTime * 0.4) * 2.5; + pos.xy = pos.xy * rot(0.8); + float box2 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.x += sin(gTime * 0.4) * 2.5; + pos.xy = pos.xy * rot(0.8); + float box3 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.x -= sin(gTime * 0.4) * 2.5; + pos.xy = pos.xy * rot(0.8); + float box4 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.xy = pos.xy * rot(0.8); + float box5 = boxGeom(pos, 0.5) * 6.0; + + pos = pos_origin; + float box6 = boxGeom(pos, 0.5) * 6.0; + + return max(max(max(max(max(box1, box2), box3), box4), box5), box6); +} + +fragment float4 octograms_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float2 p = (fragCoord * 2.0 - U.iResolution) / min(U.iResolution.x, U.iResolution.y); + + float3 ro = float3(0.0, -0.2, U.iTime * 4.0); + float3 ray = normalize(float3(p, 1.5)); + ray.xy = ray.xy * rot(sin(U.iTime * 0.03) * 5.0); + ray.yz = ray.yz * rot(sin(U.iTime * 0.05) * 0.2); + float t = 0.1; + float ac = 0.0; + + for (int i = 0; i < 99; i++) { + float3 pos = ro + ray * t; + pos = fract((pos - 2.0) / 4.0) * 4.0 - 2.0; + float gTime = U.iTime - float(i) * 0.01; + + float d = box_set(pos, gTime); + d = max(abs(d), 0.01); + ac += exp(-d * 23.0); + t += d * 0.55; + } + + float3 col = float3(ac * 0.02); + col += float3(0.0, 0.2 * abs(sin(U.iTime)), 0.5 + sin(U.iTime) * 0.2); + + return float4(col, 1.0 - t * (0.02 + 0.02 * sin(U.iTime))); +} diff --git a/shaders/octograms/octograms.frag.spv b/shaders/octograms/octograms.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..a2f37972f50aaa067425e3501e399515c69a6c85 GIT binary patch literal 11152 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 literal 0 HcmV?d00001 diff --git a/shaders/octograms/octograms.vk.glsl b/shaders/octograms/octograms.vk.glsl new file mode 100644 index 0000000..598d867 --- /dev/null +++ b/shaders/octograms/octograms.vk.glsl @@ -0,0 +1,109 @@ +#version 450 + +// Name: Octograms +// Author: whisky_shusuky +// URL: https://www.shadertoy.com/view/tlVGDt + +layout(location = 0) in vec2 vUV; +layout(location = 0) out vec4 FragColor; + +layout(set = 3, binding = 0) uniform ShadertoyUBO { + float iTime; + vec2 iResolution; +}; + +float gTime = 0.0; +const float REPEAT = 5.0; + +mat2 rot(float a) { + float c = cos(a), s = sin(a); + return mat2(c, s, -s, c); +} + +float sdBox(vec3 p, vec3 b) { + vec3 q = abs(p) - b; + return length(max(q, vec3(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0); +} + +float boxGeom(vec3 pos, float scale) { + pos *= scale; + float base = sdBox(pos, vec3(.4, .4, .1)) / 1.5; + pos.xy *= 5.0; + pos.y -= 3.5; + pos.xy *= rot(.75); + float result = -base; + return result; +} + +float box_set(vec3 pos, float iTimeLocal) { + vec3 pos_origin = pos; + pos = pos_origin; + pos.y += sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box1 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.y -= sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box2 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.x += sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box3 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.x -= sin(gTime * 0.4) * 2.5; + pos.xy *= rot(.8); + float box4 = boxGeom(pos, 2.0 - abs(sin(gTime * 0.4)) * 1.5); + + pos = pos_origin; + pos.xy *= rot(.8); + float box5 = boxGeom(pos, .5) * 6.0; + + pos = pos_origin; + float box6 = boxGeom(pos, .5) * 6.0; + + float result = max(max(max(max(max(box1, box2), box3), box4), box5), box6); + return result; +} + +float mapScene(vec3 pos, float iTimeLocal) { + return box_set(pos, iTimeLocal); +} + +void mainImage(out vec4 fragColor, in vec2 fragCoord) { + vec2 p = (fragCoord.xy * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y); + vec3 ro = vec3(0.0, -0.2, iTime * 4.0); + vec3 ray = normalize(vec3(p, 1.5)); + ray.xy = ray.xy * rot(sin(iTime * .03) * 5.0); + ray.yz = ray.yz * rot(sin(iTime * .05) * .2); + float t = 0.1; + vec3 col = vec3(0.0); + float ac = 0.0; + + for (int i = 0; i < 99; i++) { + vec3 pos = ro + ray * t; + pos = mod(pos - 2.0, 4.0) - 2.0; + gTime = iTime - float(i) * 0.01; + + float d = mapScene(pos, iTime); + + d = max(abs(d), 0.01); + ac += exp(-d * 23.0); + + t += d * 0.55; + } + + col = vec3(ac * 0.02); + col += vec3(0.0, 0.2 * abs(sin(iTime)), 0.5 + sin(iTime) * 0.2); + + fragColor = vec4(col, 1.0 - t * (0.02 + 0.02 * sin(iTime))); +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/remember/remember.frag.msl b/shaders/remember/remember.frag.msl new file mode 100644 index 0000000..ac29bbb --- /dev/null +++ b/shaders/remember/remember.frag.msl @@ -0,0 +1,64 @@ +#include +using namespace metal; + +// Remember — diatribes +// MSL port of remember.vk.glsl. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +static float hash12(float2 p) { + float3 p3 = fract(float3(p.xyx) * 0.1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +fragment float4 remember_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float2 u = fragCoord; + + float3 q, p = float3(U.iResolution, U.iResolution.x / U.iResolution.y); + + float i = 0.0, s = 0.0; + float d = 0.125 * hash12(u); + float t = U.iTime * 0.1; + + u = (u + u - p.xy) / p.y; + if (abs(u.y) > 0.8) { return float4(0); } + + float4 o = float4(0.0); + + for (; i < 64.0; i++) { + + q = p = float3(u * d, d + t * 5.0); + // mat2(cos(.1*p.z+.1*t+vec4(0,33,11,0))) — column-major: (m00,m10,m01,m11) + float4 cs = cos(0.1 * p.z + 0.1 * t + float4(0, 33, 11, 0)); + float2x2 m = float2x2(cs.x, cs.y, cs.z, cs.w); + p.xy = p.xy * m; + + q.xz = cos(q.xz); + p.z = cos(p.z); + + for (s = 1.0; s++ < 6.0;) { + q += sin(0.6 * t + p.zxy * 0.6); + p += sin(t + t + p.yzx * s) * 0.6; + } + + s = 0.02 + abs(min(length(p + 3.0 * sin(p.z * 0.5)) - 4.0, length(q - 2.0 * sin(p.z * 0.4)) - 6.0)) * 0.2; + d += s; + + float4 brightTerm = min(0.01 * float4(6, 2, 1, 0) / max(length(u * sin(t + t + t)), 0.001), float4(50.0)); + o += brightTerm + 1.0 / s * length(u); + } + + o = tanh(max(o / 6e2 + dot(u, u) * 0.35, 0.0)); + return o; +} diff --git a/shaders/remember/remember.frag.spv b/shaders/remember/remember.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d8193926c2d942a38bf361dbf0d8298fce9ce57d GIT binary patch literal 6616 zcmZ9Q2YjAY6^Gw6`MUQmqa-aIS}di-V(CtSv?ZF9wz!R?~n64|MNfRo_o)^BOk3EGJ9B-Rb`{H zG1=UzEdM5CLtrwvp}B5o+}yaZufJ{K*-u?$z}T!hk27XmHY}?_D_yPSojRuDI2{>J zoIDeNs>zyVhu~|nky%4yOG8srL*w}^+j@Fh`ug{DwzqVaceb~*m3!N_^_O?G8#lZV zSKhg;bD*slP$Hr@Zz(IW<}B-I?dv#e@%&xe7cYmYX0|NrK}xJ-BHDFs=xW{3PRQBI z^RPT_JihKct~#559!Pj9x@U>wtFxuzoFAHQ$a(~wa7Hadk(er)nYrZoKlB90Mb{#cPkVW?9lru> zY~)*=>{yR_1L7C;T{vj2(l+0wLA&DLf_?Yl!gzE#r^ImM5u^6wgI*MAaX%nW2SHOZZf7-t^+c~8*t z)?myjh;xU1YO-Tq-*Y*|T=vSZIn7ZE_Pq?*m)27U=h#~0dN_MA3voVuG2d*k^GCkZ z!N!F|zBzEl>W@0)JRkGXPeRNy4>7m%JsFXYm@~k}EI=aWDPVc$am+%*aq=;45!i9Q z<1y|mu)Jr_af=bh%G-ZAexg+Rum1_UCl}|#UV7&I{M+UE@UDzc*t0SL@vKZj$5~kl z_N-`I`}z~?jRo5rjRo8I=7R0n>n+&&4-{zbd17$a|tcl+6hbv6-U%ySYa?`Mzpr}57Po5Pqm_s;`6zPK;X z$ChtS<6Z!kQ`{@(X+g}V&sto!T;zQrSgx426;&Lv>iSA*!ggWPTCc0}JcHmhQr~t&&O0M^e(zHU;@d2*zsNrZcPX4c^~2=qM0X*6`gfxBt78wl!JeJl)7mZr z%k?0xNBc#Hxg0Bw{p$nUgUHnn_T2cM+rt6G82O0V1vVz^7lS<~afbGQ<#r>Ui=pV3 zAdb@)cjTpD^ZNz&GO(OIk9+fSu(A5gW6wMf@?zf&aqR0W!1~WbVvVl^%f}k`f<5E% z5wj0mtm9QFMn3A;58jLDYoQn74r)<9&=VH-H`Ee2y_jF4lP?*!_=nz8x&5 z_}L@-?pb~Z5`8x==6xsF9L2T13)^@<=QTzy#=INs7|&R&^(Ju4;TU7&V$6HM)>k~2 z@5Ppn_vU7BtWjT#eIGc+np@jg@d5PJi0{Mu(cW>j@5cwxA42@}e;BP_9q0ZdU~}wa zKfS9TMdZvG`Q_q$`B?Jbg7$sU{s7`!<`z4b^J=SOu8)I@ckC0`w<7Yfr=J8{Yy9@R z4J@a)pMLfzesg{bY>av0&GzAM$Rw8xmQv9L9k=wqxP?Wohu~P ze+W+BK_qJbDmZG_A9=q9)@M&+tzQSb*2wn_u$-~>L!Vsn9C{{V{5QeItYt6eqra8x z;(hpb;^UpZ8(Z!$5_jY~;8?T%i2W}3E<}Iy;(K8EkXZZo;ardY$om7ZdFv7V{wDE0 z{1DN11c_RH1a|+UmZM;6E7tO3Z24H>$@MZr{?)B zawnoM-VM1pyT1c(L?Zt8U^!!q*C%KEF!Y1Sgk+olPe}28{W;l@?=LAvKIZ)E2{C`e zHcmcj{5#kh#~}LSx6ePou0emq{u6AhXGDMW@ZrRJu8nyJiQfm0fb|!}->A;_DDnVe zjJf3gg*b=%q5n8ye~zK`S(|bHM&zQ_$H51X_(M9Yd(j2mCgLZ7H!xpO;%rRD$A9_z=~!dkOZQ+(@=XC77d@7be-HXE DqhCH# literal 0 HcmV?d00001 diff --git a/shaders/remember/remember.vk.glsl b/shaders/remember/remember.vk.glsl new file mode 100644 index 0000000..5a31987 --- /dev/null +++ b/shaders/remember/remember.vk.glsl @@ -0,0 +1,61 @@ +#version 450 + +// Name: Remember +// Author: diatribes +// URL: https://www.shadertoy.com/view/tXSBDK + +layout(location = 0) in vec2 vUV; +layout(location = 0) out vec4 FragColor; + +layout(set = 3, binding = 0) uniform ShadertoyUBO { + float iTime; + vec2 iResolution; +}; + +// fuzzy brain — Hash function to replace iChannel0 texture noise +float hash12(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + +void mainImage(out vec4 o, vec2 u) { + + vec3 q, p = vec3(iResolution.xy, iResolution.x / iResolution.y); + + float i = 0.0, s, + d = .125 * hash12(u), + t = iTime * .1; + + u = (u + u - p.xy) / p.y; + if (abs(u.y) > .8) { o = vec4(0); return; } + + o = vec4(0.0); + + for (; i < 64.; i++) { + + q = p = vec3(u * d, d + t * 5.); + p.xy *= mat2(cos(.1 * p.z + .1 * t + vec4(0, 33, 11, 0))); + + q.xz = cos(q.xz); + p.z = cos(p.z); + for (s = 1.; s++ < 6.; + q += sin(.6 * t + p.zxy * .6), + p += sin(t + t + p.yzx * s) * .6); + + d += s = .02 + abs(min(length(p + 3. * sin(p.z * .5)) - 4., length(q - 2. * sin(p.z * .4)) - 6.)) * .2; + + vec4 brightTerm = min(.01 * vec4(6, 2, 1, 0) / max(length(u * sin(t + t + t)), 0.001), vec4(50.0)); + o += brightTerm + 1. / s * length(u); + + } + + o = tanh(max(o / 6e2 + dot(u, u) * .35, 0.)); +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/seascape/seascape.frag.msl b/shaders/seascape/seascape.frag.msl new file mode 100644 index 0000000..bcd12ae --- /dev/null +++ b/shaders/seascape/seascape.frag.msl @@ -0,0 +1,181 @@ +#include +using namespace metal; + +// Seascape — Alexander Alekseev (TDM, 2014) +// MSL port of seascape.vk.glsl. iTime threaded through helpers because +// MSL does not allow file-scope mutable globals. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +constant int NUM_STEPS = 32; +constant float PI = 3.141592; +constant float EPSILON = 1e-3; + +constant int ITER_GEOMETRY = 3; +constant int ITER_FRAGMENT = 5; +constant float SEA_HEIGHT = 0.6; +constant float SEA_CHOPPY = 4.0; +constant float SEA_SPEED = 0.8; +constant float SEA_FREQ = 0.16; +constant float3 SEA_BASE = float3(0.0, 0.09, 0.18); +constant float3 SEA_WATER_COLOR = float3(0.8, 0.9, 0.6) * 0.6; +constant float2x2 octave_m = float2x2(1.6, 1.2, -1.2, 1.6); + +static float3x3 fromEuler(float3 ang) { + float2 a1 = float2(sin(ang.x), cos(ang.x)); + float2 a2 = float2(sin(ang.y), cos(ang.y)); + float2 a3 = float2(sin(ang.z), cos(ang.z)); + float3x3 m; + m[0] = float3(a1.y * a3.y + a1.x * a2.x * a3.x, a1.y * a2.x * a3.x + a3.y * a1.x, -a2.y * a3.x); + m[1] = float3(-a2.y * a1.x, a1.y * a2.y, a2.x); + m[2] = float3(a3.y * a1.x * a2.x + a1.y * a3.x, a1.x * a3.x - a1.y * a3.y * a2.x, a2.y * a3.y); + return m; +} + +static float hash(float2 p) { + float h = dot(p, float2(127.1, 311.7)); + return fract(sin(h) * 43758.5453123); +} + +static float noise(float2 p) { + float2 i = floor(p); + float2 f = fract(p); + float2 u = f * f * (3.0 - 2.0 * f); + return -1.0 + 2.0 * mix(mix(hash(i + float2(0.0, 0.0)), + hash(i + float2(1.0, 0.0)), u.x), + mix(hash(i + float2(0.0, 1.0)), + hash(i + float2(1.0, 1.0)), u.x), u.y); +} + +static float diffuseLight(float3 n, float3 l, float p) { + return pow(dot(n, l) * 0.4 + 0.6, p); +} + +static float specularLight(float3 n, float3 l, float3 e, float s) { + float nrm = (s + 8.0) / (PI * 8.0); + return pow(max(dot(reflect(e, n), l), 0.0), s) * nrm; +} + +static float3 getSkyColor(float3 e) { + e.y = (max(e.y, 0.0) * 0.8 + 0.2) * 0.8; + return float3(pow(1.0 - e.y, 2.0), 1.0 - e.y, 0.6 + (1.0 - e.y) * 0.4) * 1.1; +} + +static float sea_octave(float2 uv, float choppy) { + uv += noise(uv); + float2 wv = 1.0 - abs(sin(uv)); + float2 swv = abs(cos(uv)); + wv = mix(wv, swv, wv); + return pow(1.0 - pow(wv.x * wv.y, 0.65), choppy); +} + +static float seaMap(float3 p, float iTime, int iter) { + float SEA_TIME = 1.0 + iTime * SEA_SPEED; + float freq = SEA_FREQ; + float amp = SEA_HEIGHT; + float choppy = SEA_CHOPPY; + float2 uv = p.xz; uv.x *= 0.75; + + float d, h = 0.0; + for (int i = 0; i < iter; i++) { + d = sea_octave((uv + SEA_TIME) * freq, choppy); + d += sea_octave((uv - SEA_TIME) * freq, choppy); + h += d * amp; + uv = uv * octave_m; + freq *= 1.9; + amp *= 0.22; + choppy = mix(choppy, 1.0, 0.2); + } + return p.y - h; +} + +static float3 getSeaColor(float3 p, float3 n, float3 l, float3 eye, float3 dist) { + float fresnel = clamp(1.0 - dot(n, -eye), 0.0, 1.0); + fresnel = min(fresnel * fresnel * fresnel, 0.5); + + float3 reflected = getSkyColor(reflect(eye, n)); + float3 refracted = SEA_BASE + diffuseLight(n, l, 80.0) * SEA_WATER_COLOR * 0.12; + + float3 color = mix(refracted, reflected, fresnel); + + float atten = max(1.0 - dot(dist, dist) * 0.001, 0.0); + color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten; + + color += specularLight(n, l, eye, 600.0 * rsqrt(dot(dist, dist))); + + return color; +} + +static float3 getNormal(float3 p, float eps, float iTime) { + float3 n; + n.y = seaMap(p, iTime, ITER_FRAGMENT); + n.x = seaMap(float3(p.x + eps, p.y, p.z), iTime, ITER_FRAGMENT) - n.y; + n.z = seaMap(float3(p.x, p.y, p.z + eps), iTime, ITER_FRAGMENT) - n.y; + n.y = eps; + return normalize(n); +} + +static float heightMapTracing(float3 ori, float3 dir, thread float3& p, float iTime) { + float tm = 0.0; + float tx = 1000.0; + float hx = seaMap(ori + dir * tx, iTime, ITER_GEOMETRY); + if (hx > 0.0) { + p = ori + dir * tx; + return tx; + } + float hm = seaMap(ori, iTime, ITER_GEOMETRY); + for (int i = 0; i < NUM_STEPS; i++) { + float tmid = mix(tm, tx, hm / (hm - hx)); + p = ori + dir * tmid; + float hmid = seaMap(p, iTime, ITER_GEOMETRY); + if (hmid < 0.0) { + tx = tmid; + hx = hmid; + } else { + tm = tmid; + hm = hmid; + } + if (abs(hmid) < EPSILON) break; + } + return mix(tm, tx, hm / (hm - hx)); +} + +static float3 getPixel(float2 coord, float time, float2 iResolution, float iTime) { + float2 uv = coord / iResolution; + uv = uv * 2.0 - 1.0; + uv.x *= iResolution.x / iResolution.y; + + float3 ang = float3(sin(time * 3.0) * 0.1, sin(time) * 0.2 + 0.3, time); + float3 ori = float3(0.0, 3.5, time * 5.0); + float3 dir = normalize(float3(uv.xy, -2.0)); + dir.z += length(uv) * 0.14; + dir = normalize(dir) * fromEuler(ang); + + float3 p; + heightMapTracing(ori, dir, p, iTime); + float3 dist = p - ori; + float EPSILON_NRM = 0.1 / iResolution.x; + float3 n = getNormal(p, dot(dist, dist) * EPSILON_NRM, iTime); + float3 light = normalize(float3(0.0, 1.0, 0.8)); + + return mix( + getSkyColor(dir), + getSeaColor(p, n, light, dir, dist), + pow(smoothstep(0.0, -0.02, dir.y), 0.2)); +} + +fragment float4 seascape_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float time = U.iTime * 0.3; + float3 color = getPixel(fragCoord, time, U.iResolution, U.iTime); + return float4(pow(color, float3(0.65)), 1.0); +} diff --git a/shaders/seascape/seascape.frag.spv b/shaders/seascape/seascape.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..5dc028a143258ddcdcda51f4c2641d12836d405b GIT binary patch literal 19556 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 A)c^nh literal 0 HcmV?d00001 diff --git a/shaders/seascape/seascape.vk.glsl b/shaders/seascape/seascape.vk.glsl new file mode 100644 index 0000000..ddb72a7 --- /dev/null +++ b/shaders/seascape/seascape.vk.glsl @@ -0,0 +1,200 @@ +#version 450 + +// Name: Seascape +// Author: Alexander Alekseev +// URL: https://www.shadertoy.com/view/Ms2SD1 +// +// "Seascape" by Alexander Alekseev aka TDM - 2014 +// CC BY-NC-SA 3.0 Unported License. + +layout(location = 0) in vec2 vUV; +layout(location = 0) out vec4 FragColor; + +layout(set = 3, binding = 0) uniform ShadertoyUBO { + float iTime; + vec2 iResolution; +}; + +const int NUM_STEPS = 32; +const float PI = 3.141592; +const float EPSILON = 1e-3; +#define EPSILON_NRM (0.1 / iResolution.x) + +const int ITER_GEOMETRY = 3; +const int ITER_FRAGMENT = 5; +const float SEA_HEIGHT = 0.6; +const float SEA_CHOPPY = 4.0; +const float SEA_SPEED = 0.8; +const float SEA_FREQ = 0.16; +const vec3 SEA_BASE = vec3(0.0, 0.09, 0.18); +const vec3 SEA_WATER_COLOR = vec3(0.8, 0.9, 0.6) * 0.6; +#define SEA_TIME (1.0 + iTime * SEA_SPEED) +const mat2 octave_m = mat2(1.6, 1.2, -1.2, 1.6); + +mat3 fromEuler(vec3 ang) { + vec2 a1 = vec2(sin(ang.x), cos(ang.x)); + vec2 a2 = vec2(sin(ang.y), cos(ang.y)); + vec2 a3 = vec2(sin(ang.z), cos(ang.z)); + mat3 m; + m[0] = vec3(a1.y * a3.y + a1.x * a2.x * a3.x, a1.y * a2.x * a3.x + a3.y * a1.x, -a2.y * a3.x); + m[1] = vec3(-a2.y * a1.x, a1.y * a2.y, a2.x); + m[2] = vec3(a3.y * a1.x * a2.x + a1.y * a3.x, a1.x * a3.x - a1.y * a3.y * a2.x, a2.y * a3.y); + return m; +} + +float hash(vec2 p) { + float h = dot(p, vec2(127.1, 311.7)); + return fract(sin(h) * 43758.5453123); +} + +float noise(in vec2 p) { + vec2 i = floor(p); + vec2 f = fract(p); + vec2 u = f * f * (3.0 - 2.0 * f); + return -1.0 + 2.0 * mix(mix(hash(i + vec2(0.0, 0.0)), + hash(i + vec2(1.0, 0.0)), u.x), + mix(hash(i + vec2(0.0, 1.0)), + hash(i + vec2(1.0, 1.0)), u.x), u.y); +} + +float diffuse(vec3 n, vec3 l, float p) { + return pow(dot(n, l) * 0.4 + 0.6, p); +} + +float specular(vec3 n, vec3 l, vec3 e, float s) { + float nrm = (s + 8.0) / (PI * 8.0); + return pow(max(dot(reflect(e, n), l), 0.0), s) * nrm; +} + +vec3 getSkyColor(vec3 e) { + e.y = (max(e.y, 0.0) * 0.8 + 0.2) * 0.8; + return vec3(pow(1.0 - e.y, 2.0), 1.0 - e.y, 0.6 + (1.0 - e.y) * 0.4) * 1.1; +} + +float sea_octave(vec2 uv, float choppy) { + uv += noise(uv); + vec2 wv = 1.0 - abs(sin(uv)); + vec2 swv = abs(cos(uv)); + wv = mix(wv, swv, wv); + return pow(1.0 - pow(wv.x * wv.y, 0.65), choppy); +} + +float map(vec3 p) { + float freq = SEA_FREQ; + float amp = SEA_HEIGHT; + float choppy = SEA_CHOPPY; + vec2 uv = p.xz; uv.x *= 0.75; + + float d, h = 0.0; + for (int i = 0; i < ITER_GEOMETRY; i++) { + d = sea_octave((uv + SEA_TIME) * freq, choppy); + d += sea_octave((uv - SEA_TIME) * freq, choppy); + h += d * amp; + uv *= octave_m; freq *= 1.9; amp *= 0.22; + choppy = mix(choppy, 1.0, 0.2); + } + return p.y - h; +} + +float map_detailed(vec3 p) { + float freq = SEA_FREQ; + float amp = SEA_HEIGHT; + float choppy = SEA_CHOPPY; + vec2 uv = p.xz; uv.x *= 0.75; + + float d, h = 0.0; + for (int i = 0; i < ITER_FRAGMENT; i++) { + d = sea_octave((uv + SEA_TIME) * freq, choppy); + d += sea_octave((uv - SEA_TIME) * freq, choppy); + h += d * amp; + uv *= octave_m; freq *= 1.9; amp *= 0.22; + choppy = mix(choppy, 1.0, 0.2); + } + return p.y - h; +} + +vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) { + float fresnel = clamp(1.0 - dot(n, -eye), 0.0, 1.0); + fresnel = min(fresnel * fresnel * fresnel, 0.5); + + vec3 reflected = getSkyColor(reflect(eye, n)); + vec3 refracted = SEA_BASE + diffuse(n, l, 80.0) * SEA_WATER_COLOR * 0.12; + + vec3 color = mix(refracted, reflected, fresnel); + + float atten = max(1.0 - dot(dist, dist) * 0.001, 0.0); + color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten; + + color += specular(n, l, eye, 600.0 * inversesqrt(dot(dist, dist))); + + return color; +} + +vec3 getNormal(vec3 p, float eps) { + vec3 n; + n.y = map_detailed(p); + n.x = map_detailed(vec3(p.x + eps, p.y, p.z)) - n.y; + n.z = map_detailed(vec3(p.x, p.y, p.z + eps)) - n.y; + n.y = eps; + return normalize(n); +} + +float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) { + float tm = 0.0; + float tx = 1000.0; + float hx = map(ori + dir * tx); + if (hx > 0.0) { + p = ori + dir * tx; + return tx; + } + float hm = map(ori); + for (int i = 0; i < NUM_STEPS; i++) { + float tmid = mix(tm, tx, hm / (hm - hx)); + p = ori + dir * tmid; + float hmid = map(p); + if (hmid < 0.0) { + tx = tmid; + hx = hmid; + } else { + tm = tmid; + hm = hmid; + } + if (abs(hmid) < EPSILON) break; + } + return mix(tm, tx, hm / (hm - hx)); +} + +vec3 getPixel(in vec2 coord, float time) { + vec2 uv = coord / iResolution.xy; + uv = uv * 2.0 - 1.0; + uv.x *= iResolution.x / iResolution.y; + + vec3 ang = vec3(sin(time * 3.0) * 0.1, sin(time) * 0.2 + 0.3, time); + vec3 ori = vec3(0.0, 3.5, time * 5.0); + vec3 dir = normalize(vec3(uv.xy, -2.0)); dir.z += length(uv) * 0.14; + dir = normalize(dir) * fromEuler(ang); + + vec3 p; + heightMapTracing(ori, dir, p); + vec3 dist = p - ori; + vec3 n = getNormal(p, dot(dist, dist) * EPSILON_NRM); + vec3 light = normalize(vec3(0.0, 1.0, 0.8)); + + return mix( + getSkyColor(dir), + getSeaColor(p, n, light, dir, dist), + pow(smoothstep(0.0, -0.02, dir.y), 0.2)); +} + +void mainImage(out vec4 fragColor, in vec2 fragCoord) { + float time = iTime * 0.3; + vec3 color = getPixel(fragCoord, time); + fragColor = vec4(pow(color, vec3(0.65)), 1.0); +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +} diff --git a/shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.msl b/shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.msl new file mode 100644 index 0000000..3e2854b --- /dev/null +++ b/shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.msl @@ -0,0 +1,47 @@ +#include +using namespace metal; + +// Shader Art Coding Introduction — kishimisu +// MSL port of shader_art_coding_introduction.vk.glsl. + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +static float3 palette(float t) { + float3 a = float3(0.5, 0.5, 0.5); + float3 b = float3(0.5, 0.5, 0.5); + float3 c = float3(1.0, 1.0, 1.0); + float3 d = float3(0.263, 0.416, 0.557); + return a + b * cos(6.28318 * (c * t * d)); +} + +fragment float4 shader_art_coding_introduction_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float2 uv = (fragCoord * 2.0 - U.iResolution) / U.iResolution.y; + float2 uv0 = uv; + float3 finalColor = float3(0.0); + + for (float i = 0.0; i < 4.0; i++) { + uv = fract(uv * 1.5) - 0.5; + + float d = length(uv) * exp(-length(uv0)); + + float3 col = palette(length(uv0) + i * 0.4 + U.iTime * 0.4); + + d = sin(d * 8.0 + U.iTime) / 8.0; + d = abs(d); + d = pow(0.01 / d, 1.2); + + finalColor += col * d; + } + + return float4(finalColor, 1.0); +} diff --git a/shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.spv b/shaders/shader_art_coding_introduction/shader_art_coding_introduction.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..a92b9caa72f770b95a819da7f8b005c7b59fa037 GIT binary patch literal 3712 zcmZ9NS#y+C5QYyV1IWJbVnSR{kYZm9O8{X&ql8t(B@D>~Mkkq&Od_BNh#)TDE`mS6 zzu=|iomE)ng;o9yFDy%~!t!}0U&nz{)#&Y3ifZ5f}^m^3L(N#CZCH6x9M zNpRz8I^TY%edS=ad*!vkpy6XdSMAYw_ zOF4Q@slQMzR;$HjJ*!(`8rUtRDw3m<*=YOR*IPJQTsGXZu64L)O{>0Knu)Jxpm1_m zrCb@P#plwjQLZx3UE>E_-oE<>_ zGjOFW_82;PvgfW!nXJa-N9!*P6nblMhSu+1`lqAy%QtiG8EAdx=`&_7+8Fm)j&1&YgtdJImiz)lE+pa>!=-d_H10tx zxsZr^2=4dqu5Jsv3Hy(`zmD3?*w=4P9j&tz+ngpuU*tUk{$<)vZDFs)X0h($dx-w_ zf?YAkePFqeh&y0Vy4W_G3I{>KAF1&_Y!AB!`{z4%YICz+-}pyJE-cn_yqC$`Hdpx(~Q4Dj5(hn=E-lPD|?WO_^-fn z`rJ=@GhfWJe2w^?vupb4R zukD?F46*MU*}0a1jggO>$HDI7_i&FV5aZ+{Z+XW1mM2r$xD|-^&U>Oi@}C6Tm;Osx z&6Qw#*Y__o)Q)-k9sP!`8Hn??=FALx&t@UcehxbB>S}Pz))@cSh3&V<*V*#^uM5BW zSey=tGFy0puTQXtyKQGFKdPJq)(LnCnrnoWG;qHD~<- z;$54F=#P242%euw%=aa1U@x#;N(*q)-!S+I2)5q*&( zA31M<&51qU2A@OZC-ckVzV9H`S%~OAk3=nf)^cVS5a$%NFM_Qdzqgmb##}@q=UuRG z)_GXtG9qWJd+3w%jrv}FXX@DFJ+SvC=6MAyw-_;hA diff --git a/shaders/test/test.vk.glsl b/shaders/test/test.vk.glsl index 819ab8e..3d0312e 100644 --- a/shaders/test/test.vk.glsl +++ b/shaders/test/test.vk.glsl @@ -4,7 +4,8 @@ // Author: JailDesigner // // Vulkan port of test.gl.glsl. Bindings follow the SDL3 GPU convention: -// set=3, binding=0 — fragment uniform buffer (ShadertoyUniforms in C++). +// set=3, binding=0 — fragment uniform buffer (anonymous block: members +// are accessible directly as iTime / iResolution, like Shadertoy). layout(location = 0) in vec2 vUV; layout(location = 0) out vec4 FragColor; @@ -12,7 +13,7 @@ layout(location = 0) out vec4 FragColor; layout(set = 3, binding = 0) uniform ShadertoyUBO { float iTime; vec2 iResolution; -} u; +}; vec3 palette(float t) { vec3 a = vec3(1.0, 0.5, 0.5); @@ -23,10 +24,10 @@ vec3 palette(float t) { } void mainImage(out vec4 fragColor, in vec2 fragCoord) { - vec2 uv = (fragCoord * 2.0 - u.iResolution) / u.iResolution.y; + vec2 uv = (fragCoord * 2.0 - iResolution) / iResolution.y; float d = length(uv); vec3 col = palette(d); - d = sin(d * 8.0 + u.iTime) / 8.0; + d = sin(d * 8.0 + iTime) / 8.0; d = abs(d); d = 0.02 / d; col *= d; @@ -34,7 +35,7 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) { } void main() { - vec2 fragCoordPixels = vUV * u.iResolution; + vec2 fragCoordPixels = vUV * iResolution; vec4 outColor; mainImage(outColor, fragCoordPixels); FragColor = outColor; diff --git a/shaders/water/water.frag.msl b/shaders/water/water.frag.msl new file mode 100644 index 0000000..82249d5 --- /dev/null +++ b/shaders/water/water.frag.msl @@ -0,0 +1,40 @@ +#include +using namespace metal; + +// Water — diatribes +// MSL port of water.vk.glsl. Entry point is named after the shader (water_fs). + +struct ShadertoyUBO { + float iTime; + float2 iResolution; +}; + +struct PassthroughVOut { + float4 pos [[position]]; + float2 uv; +}; + +fragment float4 water_fs(PassthroughVOut in [[stage_in]], + constant ShadertoyUBO& U [[buffer(0)]]) { + float2 fragCoord = in.uv * U.iResolution; + float2 u = fragCoord; + + float s = 0.002, i = 0.0, n; + float3 r = float3(U.iResolution, U.iResolution.x / U.iResolution.y); + float3 p = float3(0); + u = (u - r.xy / 2.0) / r.y - 0.3; + + float4 o = float4(0); + + for (; i < 32.0 && s > 0.001; i++) { + float4 term = float4(5, 2, 1, 0) / max(length(u - 0.1), 0.001); + o += min(term, float4(100.0)); + p += float3(u * s, s); + s = 1.0 + p.y; + for (n = 0.01; n < 1.0; n += n) { + s += abs(dot(sin(p.z + U.iTime + p / n), float3(1))) * n * 0.1; + } + } + o = tanh(o / 5e2); + return o; +} diff --git a/shaders/water/water.frag.spv b/shaders/water/water.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..0bbbc2886c63ccff5b68034ec6b5d7784774a010 GIT binary patch literal 3796 zcmZ9OS#y+C5QaZUh9HDBEQ*R*Tu>qcvWKuF!T=5?tl}DCG9jZ$CQK#~+z29y3%H>I zZg}Niu)Orj3%vH9SW1;uKF{Q9YRsv6>F&3?PoLALzX>%nTk4WzMlv^9b` z+GI|W&Glrvy0W=FJ$<92J!9pwL;0Se!brZSzfj8el?xMj<7QXI6-N4o#`~)SGDK9@ z%}{ARH9W`u;oejERTBdn+9n3pw&VgGQm>n8-}s-Msl3nL%Dz)cSfR) z`ixnKjD1&Qo4*(o7uU3fy#(83jipFqJfr!`kmk#;#I{%Zt*QSWq&4N+QrkYsEycbU z*$8F;>uKMY+UDPnZmjzm--r}0;~SAp8Z6_Rk;Z$5@IQn;1GK_=&c}gw3dB9v!LfFQ zy%poe_3JxYxuJL54k9OH#CGCibu6L!Qz*e_(Tj^OYzzBoqmr9R!>xcHoty}G3KZ~6tzjs9L2`ss4L~H?m&YvyYwHwh-1N)?H&&$9SJvxVO{Xpz< z*`VZhr@j6H&A$3JzOA-1E~ozoq;q2L^lLlwa+{b(>pROXxxZmDNMoH(zxT*>X0J`N z{jS4ryx+BUJNcgJD)2nJ+0{Av3OIYtSHygs@)wCQ=Nn+2{0>g#8RR1VTXZ>n*3;g~ zTzQx8fWNt(OP@KO=lhg1$2(|;?(!-+2zyh)+*cm4^-La52m)~bZ>tn)ZNz^jUM}ZHoeCWz{&5XPtC}d zs+cBpd*S!`VCsvwhpXcJh9m9~bbXh2GxJsfbL9`E+@t8$bp`hrx}5XbO{TvEtAVll z+{ZiF8+mp6;_rpEosTuZerucm1TemfZtGv0a`LXJT2r&N9(!F1&u;vaz#M%SQf>pf zb@bU+`@a!br@9ZDQocLQ+l(zIV*f4Z?x!!}wxRpmCZc8=y0QAaw|A6Nch>yv`-d58 zM>=cDzv#hEIsI+i1LQhE#Oy_Pu6|8p_MyvV!OtnTAKhGi zx2dhY19%2&s>eG$gYF&T&fVz#eu}vBA#~&P)iV#y(qZ76c|QI1ysP{XAn%MA6W(B;gDcan=9 zyoesN>K$GJ_V^0<&fd$w7f*XH**r*I9G7J=yIMjzN1&rPXc}J;eLJ}eZX(X zGi&#!objGnpIpp&9$n7+$C(Du<=w+Go&q@_?;f64PJIwr0M6p8NasT7tPUZEflL1g zQok~4717-zW_1)@&U((A_G`es%vF!Gm(W|mX%PF3q01Z7j2s6mKp8~LM9RngUdJ|1 z-WdCK2Do?RoJIGX(f>ElPGx9E?`?k@S_tE8yjdz#xEqzzt zLmBxWpj$WWOQ{|EeTXe*T+EJK_3Zf0+PjeMuZ;aZLT>=E-^b{3IpBW! .001; i++) { + vec4 term = vec4(5,2,1,0)/max(length(u-.1), 0.001); + o += min(term, vec4(100.0)); + for (p += vec3(u*s,s), s = 1. + p.y, n =.01; n < 1.; n+=n) { + s += abs(dot(sin(p.z+iTime+p / n), vec3(1))) * n*.1; + } + } + o = tanh(o/5e2); +} + +void main() { + vec2 fragCoordPixels = vUV * iResolution; + vec4 outColor; + mainImage(outColor, fragCoordPixels); + FragColor = outColor; +}