A square root is one node everywhere else, so the shader graph gets its own (#92)
game-maker / suite (push) Successful in 10m29s

`Sqrt` already exists in the behavior graph (`data/Sqrt.ts`) and in particles
(`ParticleSqrt`); the shader was the only graph without it. `Pow` with exponent
0.5 does the same job, so this is convenience, not a missing capability -- a
radial falloff no longer needs a node whose purpose has to be read off its
parameter.

Like `Pow` it cannot go through `unary()`: GLSL leaves `sqrt` undefined below 0,
so the value is held there with `max(value, 0.0)`. That form takes a float
second argument for a `vec3` too, so unlike `pow` the exponent broadcast has no
counterpart here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5 committed 2026-09-14 19:35:00 +02:00
1 parent 80dd82349d
commit 2637feb715
2 files changed
+35

No files matched your search

+19
View File
@@ -487,6 +487,25 @@ describe('compileShader', () => {
expect(fragment).toMatch(/vec3 n\d+_result = pow\(max\(n\d+_color, 0\.0\), vec3\(2\.2\)\);/);
});
it('writes Sqrt as the GLSL call with the value held at 0, per channel for a colour', () => {
const f = makeProject();
const s = shaderEditor(f, 'Root');
const uv = s.add(SHADER_UV);
const root = s.add('ShaderSqrt');
const tint = s.add('ShaderColor', { value: 0xff8000 });
const rolled = s.add('ShaderSqrt');
const output = s.add(SHADER_OUTPUT);
s.link(uv, 'u', root, 'value');
s.link(root, 'result', output, 'alpha');
s.link(tint, 'color', rolled, 'value');
s.link(rolled, 'result', output, 'color');
const build = compileShader(s.asset().graph);
expect(build.problems).toEqual({});
const { fragment } = build.compiled!;
expect(fragment).toMatch(/float n\d+_result = sqrt\(max\(n\d+_u, 0\.0\)\);/);
expect(fragment).toMatch(/vec3 n\d+_result = sqrt\(max\(n\d+_color, 0\.0\)\);/);
});
it('writes Abs as the GLSL call, per channel for a colour', () => {
const f = makeProject();
const s = shaderEditor(f, 'Fold');