Adjust colors: brightness adds instead of multiplying (#62)
game-maker / suite (push) Failing after 4m1s
game-maker / suite (push) Failing after 4m1s
The shipped shader graph gains a `brightness - 1` offset node, so 1 stays neutral and brightness lifts every channel by the same amount; contrast keeps multiplying, saturation keeps mixing with the luma. Fixture, seeds, unit and e2e expectations follow (twelve nodes, 1.25 -> #80c0ff). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
42cafa7543
commit
a32b7c6daa
3 files changed
+41
-23
No files matched your search
@@ -46,15 +46,16 @@ function shaderEditor(f: ProjectFixture, name = 'Adjust colors') {
|
||||
const property = (name: string, value = 1, min = 0, max = 4) => ({ name, default: value, min, max });
|
||||
|
||||
/**
|
||||
* rgb *= brightness; rgb = (rgb - 0.5) * contrast + 0.5; rgb = mix(luma, rgb, saturation) –
|
||||
* eleven nodes, the same maths the built-in prototype had.
|
||||
* rgb += brightness - 1; rgb = (rgb - 0.5) * contrast + 0.5; rgb = mix(luma, rgb, saturation) –
|
||||
* twelve nodes, the recipe `tools/lib/shaders.mjs` ships.
|
||||
*/
|
||||
function buildAdjustColors(s: ReturnType<typeof shaderEditor>) {
|
||||
const texel = s.add(SHADER_TEXTURE_COLOR);
|
||||
const brightness = s.add(SHADER_PROPERTY, property('brightness'));
|
||||
const contrast = s.add(SHADER_PROPERTY, property('contrast'));
|
||||
const saturation = s.add(SHADER_PROPERTY, property('saturation'));
|
||||
const bright = s.add('ShaderMultiply');
|
||||
const offset = s.add('ShaderSubtract', { b: 1 });
|
||||
const bright = s.add('ShaderAdd');
|
||||
const shifted = s.add('ShaderSubtract', { b: 0.5 });
|
||||
const scaled = s.add('ShaderMultiply');
|
||||
const centred = s.add('ShaderAdd', { b: 0.5 });
|
||||
@@ -62,7 +63,8 @@ function buildAdjustColors(s: ReturnType<typeof shaderEditor>) {
|
||||
const mixed = s.add('ShaderMix');
|
||||
const output = s.add(SHADER_OUTPUT);
|
||||
s.link(texel, 'color', bright, 'a');
|
||||
s.link(brightness, 'value', bright, 'b');
|
||||
s.link(brightness, 'value', offset, 'a');
|
||||
s.link(offset, 'result', bright, 'b');
|
||||
s.link(bright, 'result', shifted, 'a');
|
||||
s.link(shifted, 'result', scaled, 'a');
|
||||
s.link(contrast, 'value', scaled, 'b');
|
||||
@@ -72,7 +74,20 @@ function buildAdjustColors(s: ReturnType<typeof shaderEditor>) {
|
||||
s.link(centred, 'result', mixed, 'b');
|
||||
s.link(saturation, 'value', mixed, 't');
|
||||
s.link(mixed, 'result', output, 'color');
|
||||
return { texel, brightness, contrast, saturation, bright, shifted, scaled, centred, luma, mixed, output };
|
||||
return {
|
||||
texel,
|
||||
brightness,
|
||||
contrast,
|
||||
saturation,
|
||||
offset,
|
||||
bright,
|
||||
shifted,
|
||||
scaled,
|
||||
centred,
|
||||
luma,
|
||||
mixed,
|
||||
output,
|
||||
};
|
||||
}
|
||||
|
||||
describe('a shader asset', () => {
|
||||
@@ -161,7 +176,8 @@ describe('compileShader', () => {
|
||||
for (const name of ['brightness', 'contrast', 'saturation'])
|
||||
expect(fragment).toContain(`uniform float u_${name};`);
|
||||
expect(fragment).toContain('vec3 rgb = texel.a > 0.0 ? texel.rgb / texel.a : texel.rgb;');
|
||||
expect(fragment).toMatch(/vec3 n\d+_result = \(n\d+_color \* vec3\(n\d+_value\)\);/);
|
||||
expect(fragment).toMatch(/float n\d+_result = \(n\d+_value - 1\.0\);/);
|
||||
expect(fragment).toMatch(/vec3 n\d+_result = \(n\d+_color \+ vec3\(n\d+_result\)\);/);
|
||||
expect(fragment).toMatch(/vec3 n\d+_result = \(n\d+_result - vec3\(0\.5\)\);/);
|
||||
expect(fragment).toMatch(/float n\d+_value = dot\(n\d+_result, vec3\(0\.2126, 0\.7152, 0\.0722\)\);/);
|
||||
expect(fragment).toMatch(/vec3 n\d+_result = mix\(vec3\(n\d+_value\), n\d+_result, n\d+_value\);/);
|
||||
|
||||
@@ -53,8 +53,8 @@ export async function shader(t) {
|
||||
// 28a. The fixture ships Adjust colors as an asset; the + menu makes another and opens its tab on it.
|
||||
const seeded = (await shaders()).find((s) => s.id === ADJUST);
|
||||
check(
|
||||
'the fixture carries the Adjust colors shader as an asset of eleven nodes',
|
||||
Boolean(seeded) && seeded.nodes.length === 11,
|
||||
'the fixture carries the Adjust colors shader as an asset of twelve nodes',
|
||||
Boolean(seeded) && seeded.nodes.length === 12,
|
||||
JSON.stringify(seeded),
|
||||
);
|
||||
await clickText('+');
|
||||
@@ -226,10 +226,10 @@ export async function shader(t) {
|
||||
colourDistance(neutral, base) < 6,
|
||||
JSON.stringify({ base, neutral }),
|
||||
);
|
||||
await assetProps({ brightness: 0.5 });
|
||||
await assetProps({ brightness: 1.25 });
|
||||
await sleep(300);
|
||||
const darker = await centre();
|
||||
check('brightness 0.5 halves every channel', colourDistance(darker, '#204080') < 24, darker);
|
||||
const lighter = await centre();
|
||||
check('brightness 1.25 adds a quarter to every channel', colourDistance(lighter, '#80c0ff') < 24, lighter);
|
||||
await assetProps({ brightness: 1, contrast: 0 });
|
||||
await sleep(300);
|
||||
const flat = await centre();
|
||||
@@ -241,14 +241,14 @@ export async function shader(t) {
|
||||
await shot('28-shader-desaturated');
|
||||
|
||||
// 28f. The game draws through the same path, so play shows the shader too.
|
||||
await assetProps({ saturation: 1, brightness: 0.5 });
|
||||
await assetProps({ saturation: 1, brightness: 1.25 });
|
||||
await play();
|
||||
await sleep(500);
|
||||
const at = await json("__gm.gameScreen('oshade')");
|
||||
const played = at ? await json(`__gm.pixelAt(${Math.round(at.x + 20)}, ${Math.round(at.y + 20)})`) : null;
|
||||
check(
|
||||
'during play the sprite is drawn with its shader',
|
||||
played !== null && colourDistance(played, '#204080') < 24,
|
||||
played !== null && colourDistance(played, '#80c0ff') < 24,
|
||||
JSON.stringify({ at, played }),
|
||||
);
|
||||
await stop();
|
||||
|
||||
+12
-10
@@ -2,8 +2,8 @@ import { edge, node } from './builders.mjs';
|
||||
|
||||
/**
|
||||
* The "Adjust colors" shader as an asset document: brightness, contrast and saturation, 1 neutral,
|
||||
* on the straight colour – rgb *= brightness; rgb = (rgb - 0.5) * contrast + 0.5;
|
||||
* rgb = mix(luma, rgb, saturation). The recipe the built-in prototype of #62 had, now eleven nodes.
|
||||
* on the straight colour – rgb += brightness - 1; rgb = (rgb - 0.5) * contrast + 0.5;
|
||||
* rgb = mix(luma, rgb, saturation). Brightness adds (user decision, #62 follow-up), so 1 is +0.
|
||||
*/
|
||||
export function adjustColorsShader(id = 'adjust-colors', name = 'Adjust colors') {
|
||||
const property = (nodeId, propertyName, x, y) =>
|
||||
@@ -19,17 +19,19 @@ export function adjustColorsShader(id = 'adjust-colors', name = 'Adjust colors')
|
||||
property(`${id}-brightness`, 'brightness', 0, 160),
|
||||
property(`${id}-contrast`, 'contrast', 0, 320),
|
||||
property(`${id}-saturation`, 'saturation', 0, 480),
|
||||
node(`${id}-bright`, 'ShaderMultiply', 300, 0),
|
||||
node(`${id}-shift`, 'ShaderSubtract', 560, 0, { b: 0.5 }),
|
||||
node(`${id}-scale`, 'ShaderMultiply', 820, 0),
|
||||
node(`${id}-centre`, 'ShaderAdd', 1080, 0, { b: 0.5 }),
|
||||
node(`${id}-luma`, 'ShaderLuminance', 1340, 160),
|
||||
node(`${id}-mix`, 'ShaderMix', 1600, 0),
|
||||
node(`${id}-out`, 'ShaderOutput', 1860, 0),
|
||||
node(`${id}-offset`, 'ShaderSubtract', 260, 160, { b: 1 }),
|
||||
node(`${id}-bright`, 'ShaderAdd', 520, 0),
|
||||
node(`${id}-shift`, 'ShaderSubtract', 780, 0, { b: 0.5 }),
|
||||
node(`${id}-scale`, 'ShaderMultiply', 1040, 0),
|
||||
node(`${id}-centre`, 'ShaderAdd', 1300, 0, { b: 0.5 }),
|
||||
node(`${id}-luma`, 'ShaderLuminance', 1560, 160),
|
||||
node(`${id}-mix`, 'ShaderMix', 1820, 0),
|
||||
node(`${id}-out`, 'ShaderOutput', 2080, 0),
|
||||
],
|
||||
edges: [
|
||||
edge(`${id}-e1`, `${id}-texel`, 'color', `${id}-bright`, 'a'),
|
||||
edge(`${id}-e2`, `${id}-brightness`, 'value', `${id}-bright`, 'b'),
|
||||
edge(`${id}-e2`, `${id}-brightness`, 'value', `${id}-offset`, 'a'),
|
||||
edge(`${id}-e12`, `${id}-offset`, 'result', `${id}-bright`, 'b'),
|
||||
edge(`${id}-e3`, `${id}-bright`, 'result', `${id}-shift`, 'a'),
|
||||
edge(`${id}-e4`, `${id}-shift`, 'result', `${id}-scale`, 'a'),
|
||||
edge(`${id}-e5`, `${id}-contrast`, 'value', `${id}-scale`, 'b'),
|
||||
|
||||
Reference in new issue
Block a user