Last active
August 10, 2026 21:31
-
-
Save amirrajan/ce0823b016b002f5a3d29852cb89104d to your computer and use it in GitHub Desktop.
hodor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Texture2D scene : register(t0, space2); | |
| SamplerState sampler0 : register(s0, space2); | |
| // Scalar uniforms passed from Ruby via `uniforms: [{ name:, value:, type: }, ...]`. | |
| // Members must match the array order. Fragment uniform buffers live in space3 | |
| // (b registers) for SDL_shadercross HLSL. | |
| cbuffer Uniforms : register(b0, space3) { | |
| int tick_count; | |
| float time; | |
| }; | |
| // Pseudo-random hash: turns a 2D coordinate into a repeatable "random" value in | |
| // [0, 1). The huge multiplier makes sin() wrap wildly so nearby inputs produce | |
| // very different outputs, giving cheap noise without any lookup texture. | |
| float rand(float2 n) { | |
| return frac(sin(cos(dot(n, float2(12.9898, 12.1414)))) * 83758.5453); | |
| } | |
| // Value noise: smooth, continuous noise made by interpolating the random hash | |
| // values at the four surrounding integer grid corners. | |
| float noise(float2 n) { | |
| const float2 d = float2(0.0, 1.0); // offsets: d.xy=(0,0) d.yx=(1,0) d.yy=(1,1) | |
| float2 b = floor(n); // bottom-left integer cell corner | |
| float2 f = smoothstep(float2(0.0, 0.0), float2(1.0, 1.0), frac(n)); // eased position within cell | |
| // bilinear blend of the four corner random values using the eased weights | |
| return lerp(lerp(rand(b), rand(b + d.yx), f.x), | |
| lerp(rand(b + d.xy), rand(b + d.yy), f.x), f.y); | |
| } | |
| // Fractal Brownian motion: sums several octaves of value noise, each at higher | |
| // frequency and lower amplitude, to build the turbulent, wispy look of flame. | |
| float fbm(float2 n) { | |
| float total = 0.0; | |
| float amplitude = (1280.0 / 720.0) * 0.5; // starting octave weight (scaled by aspect ratio) | |
| float2 vn = n; | |
| for (int i = 0; i < 5; i++) { | |
| total += noise(vn) * amplitude; // accumulate this octave | |
| vn += vn * 1.7; // raise frequency (finer detail) next octave | |
| amplitude *= 0.47; // shrink influence of each finer octave | |
| } | |
| return total; | |
| } | |
| struct Input { | |
| float4 tex_color : COLOR0; | |
| float2 tex_coord : TEXCOORD0; | |
| }; | |
| struct Output { | |
| float4 frag_color : SV_Target; | |
| }; | |
| Output main(Input input) { | |
| Output output; | |
| // tick_count now comes straight from the `Uniforms` cbuffer above. | |
| // Fire palette: warm/cool color keys later blended together by the noise. | |
| const float3 c1 = float3(0.5, 0.0, 0.1); // deep red | |
| const float3 c2 = float3(0.9, 0.1, 0.0); // orange-red | |
| const float3 c3 = float3(0.2, 0.1, 0.7); // blue (cool tone added in) | |
| const float3 c4 = float3(1.0, 0.9, 0.1); // yellow (hot core) | |
| const float3 c5 = float3(0.1, 0.1, 0.1); // dark end of the shadow term | |
| const float3 c6 = float3(0.9, 0.9, 0.9); // light end of the shadow term | |
| // Animation time in seconds (provided directly as a float uniform). | |
| float i_time = tick_count / 60.0; | |
| float2 i_resolution = float2(1280.0, 720.0); | |
| // Pixel coordinate with the Y axis flipped so the fire rises upward. | |
| float2 frag_coord = float2(input.tex_coord.x * i_resolution.x, | |
| i_resolution.y - input.tex_coord.y * i_resolution.y); | |
| const float2 speed = float2(0.1, 0.9); // horizontal/vertical flow speed of the flames | |
| float shift = 1.327 + sin(i_time * 2.0) / 2.4; // slow flicker/brightness pulse over time | |
| const float alpha = 1.0; // fully opaque output | |
| float dist = 3.5 - sin(i_time * 0.4) / 1.89; // gently "breathes" the zoom of the noise field | |
| float2 uv = frag_coord.xy / i_resolution.xy; // normalized 0..1 coords (kept for reference) | |
| // Sampling position into the noise field; dividing by resolution.xx keeps the | |
| // aspect square so the flames aren't stretched horizontally. | |
| float2 p = frag_coord.xy * dist / i_resolution.xx; | |
| // Two layers of sine warping bend the coordinates so flames curl and sway. | |
| p += sin(p.yx * 4.0 + float2(0.2, -0.3) * i_time) * 0.04; | |
| p += sin(p.yx * 8.0 + float2(0.6, 0.1) * i_time) * 0.01; | |
| p.x -= i_time / 4.0; // scroll sideways so the fire drifts (larger divisor = slower drift) | |
| // Several fbm samples at different speeds/offsets/scales; each is a moving | |
| // layer of turbulence. The added constants (-6, -4, +2) bias the layers so | |
| // they combine into a plausible flame density field. | |
| float q = fbm(p - i_time * 0.3 + 1.0 * sin(i_time + 0.5) / 2.0); | |
| float qb = fbm(p - i_time * 0.4 + 0.1 * cos(i_time) / 2.0); | |
| float q2 = fbm(p - i_time * 0.44 - 5.0 * cos(i_time) / 2.0) - 6.0; | |
| float q3 = fbm(p - i_time * 0.9 - 10.0 * cos(i_time) / 15.0) - 4.0; | |
| float q4 = fbm(p - i_time * 1.4 - 20.0 * sin(i_time) / 14.0) + 2.0; | |
| // Weighted blend of the layers into one turbulence value. | |
| q = (q + qb - 0.4 * q2 - 2.0 * q3 + 0.6 * q4) / 3.8; | |
| // Feed the turbulence back in to distort the field again (domain warping), | |
| // producing the characteristic licking, flowing flame shapes. | |
| float2 r = float2(fbm(p + q / 2.0 + i_time * speed.x - p.x - p.y), | |
| fbm(p + q - i_time * speed.y)); | |
| // Final flame color: a cool blue whose brightness falls off sharply (pow 4) | |
| // away from the core. r.y drives the intensity and max(0, p.y) concentrates | |
| // the glow toward the base of the fire. | |
| float3 color = float3(0.05, 0.2, 1.0) / (pow((r.y + r.y) * max(0.0, p.y) + 0.1, 4.0)); | |
| // Reinhard-style tone map: compress bright values into [0,1] so hot spots | |
| // don't simply clip to solid white. | |
| color = color / (1.0 + max(float3(0.0, 0.0, 0.0), color)); | |
| output.frag_color = float4(color.x, color.y, color.z, alpha); | |
| return output; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def tick args | |
| args.outputs.shader = { | |
| path: "shaders/effect.frag.hlsl", | |
| uniforms: { | |
| tick_count: { value: Kernel.tick_count, type: :int }, | |
| time: { value: Kernel.tick_count.fdiv(60), type: :float }, | |
| } | |
| } | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| - [Game] * INFO - executing ./.dragonruby/shadercross/windows-amd64/bin/shadercross.exe C:\dr-shaders\dragonruby-windows-amd64\/mygame/shaders/effect.frag.hlsl -d DXIL -o C:\dr-shaders\dragonruby-windows-amd64\/mygame/shaders/effect.frag.dxil to transpile shader (57) | |
| - [Game] | |
| - [Render] shader compile: dxil='shaders/effect.frag.dxil' msl='shaders/effect.frag.msl' spirv='shaders/effect.frag.spv' num_samplers=2 num_uniform_buffers=0 | |
| - [Render] shader blobs loaded: dxil=3956 bytes, msl=730 bytes, spirv=1320 bytes | |
| - [Render] shader compile: chose format DXIL (device supports DXBC DXIL ) | |
| - [Render] shader compile succeeded (format=DXIL ) | |
| - [Render] created top level gpu render state (num_sampler_bindings=1, shader num_samplers=2) | |
| ! [SDL] Could not create graphics pipeline state! Error Code: The parameter is incorrect. (0x80070057) | |
| ! [SDL] Could not create graphics pipeline state! Error Code: The parameter is incorrect. (0x80070057) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment