Shader graph: Clamp is the Output's default edge, and the sheet's own mode is a constant of its own (#81)
game-maker / suite (push) Successful in 9m16s
game-maker / suite (push) Successful in 9m16s
The default of the Edge param and the address mode the shared sheet physically
carries were the same constant; changing the value would have turned every
sentinel with it and given each shader sprite a full copy of its texture.
SHEET_EDGE ('mirror', what TextureLibrary uploads) is now separate from
DEFAULT_EDGE ('clamp'). A graph whose Sample reads nothing but its own pixel
draws with the plain sheet whatever the Edge says, so the common shader costs
no second copy.
Without a shader the quad's coordinates never leave 0..1, and mirror-repeat
reads like clamp within a texel - so clamp is what a sprite shows anyway.
This commit is contained in:
1 parent
03c4323794
commit
e0c459ce92
7 files changed
+74
-20
No files matched your search
@@ -10,7 +10,9 @@ import {
|
||||
floatLiteral,
|
||||
isShaderNodeDef,
|
||||
SHADER_OUTPUT,
|
||||
SHADER_SAMPLE,
|
||||
SHADER_TIME,
|
||||
SHEET_EDGE,
|
||||
STRAIGHT_FN,
|
||||
TEXEL_ALPHA,
|
||||
TEXEL_COLOR,
|
||||
@@ -29,7 +31,10 @@ export interface CompiledShader {
|
||||
uniforms: ShaderUniform[];
|
||||
/** A Time node feeds the Output: the fragment takes `uTime`, and a sprite wearing it redraws every tick. */
|
||||
time: boolean;
|
||||
/** How the picture continues past its border – the texture variant the sprite's mesh draws with. */
|
||||
/**
|
||||
* The texture variant the sprite's mesh draws with – the Output's Edge where the graph samples
|
||||
* past the border, and the plain sheet where it cannot.
|
||||
*/
|
||||
edge: EdgeMode;
|
||||
}
|
||||
|
||||
@@ -177,5 +182,14 @@ export function compileShader(graph: Graph): ShaderBuild {
|
||||
'}',
|
||||
'',
|
||||
].join('\n');
|
||||
return { compiled: { fragment, uniforms, time, edge: edgeOf(output.params) }, problems, reason: '' };
|
||||
// The edge only shows where a Sample reads somewhere other than its own pixel. A graph that never
|
||||
// shifts a UV stays on the plain sheet, so the common shader costs no second copy of the picture.
|
||||
const shifted = graph.nodes.some(
|
||||
(n) =>
|
||||
n.type === SHADER_SAMPLE &&
|
||||
emitted.has(n.id) &&
|
||||
(edgesInto(graph, n.id, 'u').length > 0 || edgesInto(graph, n.id, 'v').length > 0),
|
||||
);
|
||||
const edge = shifted ? edgeOf(output.params) : SHEET_EDGE;
|
||||
return { compiled: { fragment, uniforms, time, edge }, problems, reason: '' };
|
||||
}
|
||||
@@ -56,16 +56,22 @@ export const STRAIGHT_FN = 'vec3 straight(vec4 c) { return c.a > 0.0 ? c.rgb / c
|
||||
|
||||
/**
|
||||
* How the picture continues past its edge when a `Sample texture` reads outside 0..1 – a setting
|
||||
* of the Output node, because the sampler state is one per draw. Mirror is what every picture has
|
||||
* anyway (`TextureLibrary`); repeat is for tiles.
|
||||
* of the Output node, because the sampler state is one per draw.
|
||||
*/
|
||||
export type EdgeMode = 'repeat' | 'mirror' | 'clamp';
|
||||
export const EDGE_PARAM = 'edge';
|
||||
export const DEFAULT_EDGE: EdgeMode = 'mirror';
|
||||
/**
|
||||
* The address mode the shared sheet carries anyway (`TextureLibrary`): within a texel it reads
|
||||
* like clamp, and no other mode can have it without a cut of its own. Asking for it costs nothing,
|
||||
* so it is what a sprite without a shader draws with.
|
||||
*/
|
||||
export const SHEET_EDGE: EdgeMode = 'mirror';
|
||||
/** Clamp: the border texel goes on, which is what a sprite without a shader shows (#81). */
|
||||
export const DEFAULT_EDGE: EdgeMode = 'clamp';
|
||||
const EDGE_OPTIONS: { value: EdgeMode; label: string }[] = [
|
||||
{ value: 'clamp', label: 'Clamp' },
|
||||
{ value: 'mirror', label: 'Mirror' },
|
||||
{ value: 'repeat', label: 'Repeat' },
|
||||
{ value: 'clamp', label: 'Clamp' },
|
||||
];
|
||||
|
||||
export function edgeOf(params: PropertyBag): EdgeMode {
|
||||
|
||||
Reference in new issue
Block a user