Let a shader declare a color the sprite sets (#298)
A shader could only ask its sprites for numbers. A tint, an outline colour or a glow colour had to be built from three Property nodes. - New node Color property next to Property: Name and Default (a colour, white unless picked), output `color`. It becomes a colour row below the Shader dropdown and a vec3 uniform in the program. - Number and colour properties share one set of names. A clash is the existing "Another property is named" problem. - Like Color it cannot feed the Vertex output. - Placed from the palette it is called tint, then tint2. - The preview in the Shader tab shows a colour field for it. Like the sliders it starts at the sprite's value and never writes into the project. - `declaredRows` takes the row builder, so the particle graph keeps its number rows unchanged. Tests: - Gate: 222 files, 3452 tests (3445 + 7) - e2e 28: 89 checks (28l-v: default colour drawn, then the colour the sprite sets) - e2e total 1704, counted (1703 + 1) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f4c149211
commit
bf27e42e8a
13 files changed
+303
-57
No files matched your search
@@ -32,9 +32,13 @@ import {
|
||||
|
||||
export interface ShaderUniform {
|
||||
name: string;
|
||||
/** A colour is a vec3 uniform and its default a packed 0xRRGGBB (#298). */
|
||||
kind: 'number' | 'color';
|
||||
default: number;
|
||||
}
|
||||
|
||||
const glslOf = (u: ShaderUniform) => (u.kind === 'color' ? 'vec3' : 'float');
|
||||
|
||||
/**
|
||||
* What a Vertex output node adds to the wearer's vertex stage (#79). It reads the corner's
|
||||
* `vTextureCoord` and the same uniforms the fragment does.
|
||||
@@ -80,7 +84,7 @@ export const perCornerProblem = (what: string) => `Not available per corner: ${w
|
||||
|
||||
/**
|
||||
* A shader graph to the fragment of the sprite's own draw: every node reachable from the Output
|
||||
* becomes one local per output, in dependency order, and every Property a float uniform. The texel
|
||||
* becomes one local per output, in dependency order, and every Property a uniform. The texel
|
||||
* arrives premultiplied, so the prelude unpremultiplies and the epilogue multiplies back.
|
||||
*/
|
||||
export function compileShader(graph: Graph): ShaderBuild {
|
||||
@@ -108,7 +112,11 @@ export function compileShader(graph: Graph): ShaderBuild {
|
||||
const color = walk.input(output, outputDef.inputs[0]!);
|
||||
const alpha = walk.input(output, outputDef.inputs[1]!);
|
||||
|
||||
const uniforms = shaderParamDefs(graph).map((row) => ({ name: row.key, default: row.default }));
|
||||
const uniforms = shaderParamDefs(graph).map((row) => ({
|
||||
name: row.key,
|
||||
kind: row.kind,
|
||||
default: row.default,
|
||||
}));
|
||||
|
||||
// The per-corner part is a walk of its own from the Vertex output: a node feeding both outputs is
|
||||
// emitted once for each stage.
|
||||
@@ -128,7 +136,7 @@ export function compileShader(graph: Graph): ShaderBuild {
|
||||
// A uniform both stages declare has to have one precision; the fragment's default is mediump.
|
||||
head: [
|
||||
...(reachesTime ? [`uniform mediump float ${TIME_UNIFORM};`] : []),
|
||||
...uniforms.map((u) => `uniform mediump float ${uniformName(u.name)};`),
|
||||
...uniforms.map((u) => `uniform mediump ${glslOf(u)} ${uniformName(u.name)};`),
|
||||
DIVIDE_FN,
|
||||
].join('\n'),
|
||||
body: [...cornerLines, `vec2 offset = vec2(${x.code}, ${y.code});`].join('\n'),
|
||||
@@ -153,7 +161,7 @@ export function compileShader(graph: Graph): ShaderBuild {
|
||||
'out vec4 finalColor;',
|
||||
'uniform sampler2D uTexture;',
|
||||
...(fragmentTime ? [`uniform float ${TIME_UNIFORM};`] : []),
|
||||
...uniforms.map((u) => `uniform float ${uniformName(u.name)};`),
|
||||
...uniforms.map((u) => `uniform ${glslOf(u)} ${uniformName(u.name)};`),
|
||||
STRAIGHT_FN,
|
||||
DIVIDE_FN,
|
||||
texelAtFn(mode),
|
||||
|
||||
@@ -2,9 +2,15 @@ import type { PortType } from '../graph/Graph';
|
||||
import type { NodeDef, PortDef } from '../graph/NodeRegistry';
|
||||
import type { SharedPortGroup } from '../graph/portTypes';
|
||||
import { type PropertyBag, textOf } from '../model/Properties';
|
||||
import { propertyNodeParams } from '../properties/declaredRows';
|
||||
import { PROPERTY_DEFAULT_PARAM, propertyNodeParams } from '../properties/declaredRows';
|
||||
import { flatDef } from '../properties/PropertySchema';
|
||||
import { PROPERTY_NAME_PARAM, propertyName, SHADER_PROPERTY } from '../properties/shaders';
|
||||
import {
|
||||
DEFAULT_PROPERTY_COLOR,
|
||||
PROPERTY_NAME_PARAM,
|
||||
propertyName,
|
||||
SHADER_COLOR_PROPERTY,
|
||||
SHADER_PROPERTY,
|
||||
} from '../properties/shaders';
|
||||
|
||||
export type GlslType = 'float' | 'vec3';
|
||||
|
||||
@@ -341,6 +347,25 @@ export const ShaderProperty: ShaderNodeDef = {
|
||||
}),
|
||||
};
|
||||
|
||||
/** The same for a colour (#298); like `Color`, there is none per corner. */
|
||||
export const ShaderColorProperty: ShaderNodeDef = {
|
||||
type: SHADER_COLOR_PROPERTY,
|
||||
label: 'Color property',
|
||||
category: 'shader',
|
||||
description: 'A color the sprite sets: a color row below the Shader dropdown, and a color here.',
|
||||
inputs: [],
|
||||
outputs: [vec3Port('color')],
|
||||
params: [
|
||||
flatDef(PROPERTY_NAME_PARAM, 'text', { label: 'Name', value: 'value' }),
|
||||
flatDef(PROPERTY_DEFAULT_PARAM, 'color', { label: 'Default', value: DEFAULT_PROPERTY_COLOR }),
|
||||
],
|
||||
perPixel: true,
|
||||
derivePorts: ({ node }) => ({ label: propertyName(node) || ShaderColorProperty.label }),
|
||||
emit: (_inputs, params) => ({
|
||||
color: { code: uniformName(textOf(params[PROPERTY_NAME_PARAM] ?? '')), type: 'vec3' },
|
||||
}),
|
||||
};
|
||||
|
||||
export function uniformName(property: string): string {
|
||||
return `u_${property}`;
|
||||
}
|
||||
@@ -550,6 +575,7 @@ export const SHADER_NODES: readonly ShaderNodeDef[] = [
|
||||
ShaderOutput,
|
||||
ShaderVertexOutput,
|
||||
ShaderProperty,
|
||||
ShaderColorProperty,
|
||||
ShaderColor,
|
||||
ShaderNumber,
|
||||
ShaderAdd,
|
||||
|
||||
Reference in new issue
Block a user