Skip to content

Commit d073206

Browse files
authored
fix: make smoothstep and step available as chained methods on vec nodes (#2135)
1 parent d2eab99 commit d073206

2 files changed

Lines changed: 172 additions & 5 deletions

File tree

tsl-testing/node-type.test.ts

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect, test } from 'vitest';
2-
import { Fn, vec2, vec3, vec4 } from 'three/tsl';
2+
import { Fn, smoothstep, smoothstepElement, step, stepElement, vec2, vec3, vec4 } from 'three/tsl';
33
import * as THREE from 'three/webgpu';
44

55
const renderer = new THREE.WebGPURenderer();
@@ -232,3 +232,125 @@ test('vec3(1, 0, 2).flipZX()', async () => {
232232
await renderer.init();
233233
renderer.render(scene, camera);
234234
});
235+
236+
// smoothstep — chained method on vector nodes
237+
238+
test('vec2(0.5, 0.5).smoothstep(0.1, 0.9)', async () => {
239+
const result: THREE.Node<'vec2'> = vec2(0.5, 0.5).smoothstep(0.1, 0.9);
240+
241+
expect(result.getNodeType(nodeBuilder)).toBe('vec2');
242+
243+
scene.backgroundNode = result.debug();
244+
245+
await renderer.init();
246+
renderer.render(scene, camera);
247+
});
248+
249+
test('vec3(0.5, 0.5, 0.5).smoothstep(float, float)', async () => {
250+
const result: THREE.Node<'vec3'> = vec3(0.5, 0.5, 0.5).smoothstep(0.1, 0.9);
251+
252+
expect(result.getNodeType(nodeBuilder)).toBe('vec3');
253+
254+
scene.backgroundNode = result.debug();
255+
256+
await renderer.init();
257+
renderer.render(scene, camera);
258+
});
259+
260+
test('vec4(0.5, 0.5, 0.5, 0.5).smoothstep(float, float)', async () => {
261+
const result: THREE.Node<'vec4'> = vec4(0.5, 0.5, 0.5, 0.5).smoothstep(0.1, 0.9);
262+
263+
expect(result.getNodeType(nodeBuilder)).toBe('vec4');
264+
265+
scene.backgroundNode = result.debug();
266+
267+
await renderer.init();
268+
renderer.render(scene, camera);
269+
});
270+
271+
// smoothstep — standalone function with vector args
272+
273+
test('smoothstep(float, float, vec3)', async () => {
274+
const result: THREE.Node<'vec3'> = smoothstep(0.1, 0.9, vec3(0.5, 0.5, 0.5));
275+
276+
expect(result.getNodeType(nodeBuilder)).toBe('vec3');
277+
278+
scene.backgroundNode = result.debug();
279+
280+
await renderer.init();
281+
renderer.render(scene, camera);
282+
});
283+
284+
// smoothstepElement — standalone function with vector args
285+
286+
test('smoothstepElement(vec3, float, float)', async () => {
287+
const result: THREE.Node<'vec3'> = smoothstepElement(vec3(0.5, 0.5, 0.5), 0.1, 0.9);
288+
289+
expect(result.getNodeType(nodeBuilder)).toBe('vec3');
290+
291+
scene.backgroundNode = result.debug();
292+
293+
await renderer.init();
294+
renderer.render(scene, camera);
295+
});
296+
297+
// step — chained method on vector nodes
298+
299+
test('vec2(0.5, 0.5).step(0.3)', async () => {
300+
const result: THREE.Node<'vec2'> = vec2(0.5, 0.5).step(0.3);
301+
302+
expect(result.getNodeType(nodeBuilder)).toBe('vec2');
303+
304+
scene.backgroundNode = result.debug();
305+
306+
await renderer.init();
307+
renderer.render(scene, camera);
308+
});
309+
310+
test('vec3(0.5, 0.5, 0.5).step(float)', async () => {
311+
const result: THREE.Node<'vec3'> = vec3(0.5, 0.5, 0.5).step(0.3);
312+
313+
expect(result.getNodeType(nodeBuilder)).toBe('vec3');
314+
315+
scene.backgroundNode = result.debug();
316+
317+
await renderer.init();
318+
renderer.render(scene, camera);
319+
});
320+
321+
test('vec4(0.5, 0.5, 0.5, 0.5).step(float)', async () => {
322+
const result: THREE.Node<'vec4'> = vec4(0.5, 0.5, 0.5, 0.5).step(0.3);
323+
324+
expect(result.getNodeType(nodeBuilder)).toBe('vec4');
325+
326+
scene.backgroundNode = result.debug();
327+
328+
await renderer.init();
329+
renderer.render(scene, camera);
330+
});
331+
332+
// step — standalone function with vector args
333+
334+
test('step(float, vec3)', async () => {
335+
const result: THREE.Node<'vec3'> = step(0.3, vec3(0.5, 0.5, 0.5));
336+
337+
expect(result.getNodeType(nodeBuilder)).toBe('vec3');
338+
339+
scene.backgroundNode = result.debug();
340+
341+
await renderer.init();
342+
renderer.render(scene, camera);
343+
});
344+
345+
// stepElement — standalone function with vector args
346+
347+
test('stepElement(vec3, float)', async () => {
348+
const result: THREE.Node<'vec3'> = stepElement(vec3(0.5, 0.5, 0.5), 0.3);
349+
350+
expect(result.getNodeType(nodeBuilder)).toBe('vec3');
351+
352+
scene.backgroundNode = result.debug();
353+
354+
await renderer.init();
355+
renderer.render(scene, camera);
356+
});

types/three/src/nodes/math/MathNode.d.ts

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,13 @@ declare module "../core/Node.js" {
503503
}
504504
}
505505

506-
export const step: (x: FloatOrNumber, y: FloatOrNumber) => Node<"float">;
506+
interface Step {
507+
(x: FloatOrNumber, y: FloatOrNumber): Node<"float">;
508+
(x: Vec2OrLessOrFloat, y: Vec2OrLessOrFloat): Node<"vec2">;
509+
(x: Vec3OrLessOrFloat, y: Vec3OrLessOrFloat): Node<"vec3">;
510+
(x: Vec4OrLessOrFloat, y: Vec4OrLessOrFloat): Node<"vec4">;
511+
}
512+
export const step: Step;
507513

508514
interface Reflect {
509515
(I: Vec2OrLessOrFloat, N: Vec2OrLessOrFloat): Node<"vec2">;
@@ -754,6 +760,9 @@ declare module "../core/Node.js" {
754760

755761
interface Smoothstep {
756762
(low: FloatOrNumber, high: FloatOrNumber, x: FloatOrNumber): Node<"float">;
763+
(low: Vec2OrLessOrFloat, high: Vec2OrLessOrFloat, x: Vec2OrLessOrFloat): Node<"vec2">;
764+
(low: Vec3OrLessOrFloat, high: Vec3OrLessOrFloat, x: Vec3OrLessOrFloat): Node<"vec3">;
765+
(low: Vec4OrLessOrFloat, high: Vec4OrLessOrFloat, x: Vec4OrLessOrFloat): Node<"vec4">;
757766
}
758767
export const smoothstep: Smoothstep;
759768

@@ -815,22 +824,58 @@ declare module "../core/Node.js" {
815824

816825
interface SmoothstepElement {
817826
(x: FloatOrNumber, low: FloatOrNumber, high: FloatOrNumber): Node<"float">;
827+
(x: Vec2OrLessOrFloat, low: Vec2OrLessOrFloat, high: Vec2OrLessOrFloat): Node<"vec2">;
828+
(x: Vec3OrLessOrFloat, low: Vec3OrLessOrFloat, high: Vec3OrLessOrFloat): Node<"vec3">;
829+
(x: Vec4OrLessOrFloat, low: Vec4OrLessOrFloat, high: Vec4OrLessOrFloat): Node<"vec4">;
818830
}
819831
export const smoothstepElement: SmoothstepElement;
820-
interface SmoothstepExtension {
832+
interface SmoothstepFloatExtension {
821833
(low: FloatOrNumber, high: FloatOrNumber): Node<"float">;
822834
}
835+
interface SmoothstepVec2Extension {
836+
(low: Vec2OrLessOrFloat, high: Vec2OrLessOrFloat): Node<"vec2">;
837+
}
838+
interface SmoothstepVec3Extension {
839+
(low: Vec3OrLessOrFloat, high: Vec3OrLessOrFloat): Node<"vec3">;
840+
}
841+
interface SmoothstepVec4Extension {
842+
(low: Vec4OrLessOrFloat, high: Vec4OrLessOrFloat): Node<"vec4">;
843+
}
823844
declare module "../core/Node.js" {
824845
interface FloatExtensions {
825-
smoothstep: SmoothstepExtension;
846+
smoothstep: SmoothstepFloatExtension;
847+
}
848+
interface Vec2Extensions {
849+
smoothstep: SmoothstepVec2Extension;
850+
}
851+
interface Vec3Extensions {
852+
smoothstep: SmoothstepVec3Extension;
853+
}
854+
interface Vec4Extensions {
855+
smoothstep: SmoothstepVec4Extension;
826856
}
827857
}
828858

829-
export const stepElement: (x: FloatOrNumber, edge: FloatOrNumber) => Node<"float">;
859+
interface StepElement {
860+
(x: FloatOrNumber, edge: FloatOrNumber): Node<"float">;
861+
(x: Vec2OrLessOrFloat, edge: Vec2OrLessOrFloat): Node<"vec2">;
862+
(x: Vec3OrLessOrFloat, edge: Vec3OrLessOrFloat): Node<"vec3">;
863+
(x: Vec4OrLessOrFloat, edge: Vec4OrLessOrFloat): Node<"vec4">;
864+
}
865+
export const stepElement: StepElement;
830866
declare module "../core/Node.js" {
831867
interface FloatExtensions {
832868
step: (edge: FloatOrNumber) => Node<"float">;
833869
}
870+
interface Vec2Extensions {
871+
step: (edge: Vec2OrLessOrFloat) => Node<"vec2">;
872+
}
873+
interface Vec3Extensions {
874+
step: (edge: Vec3OrLessOrFloat) => Node<"vec3">;
875+
}
876+
interface Vec4Extensions {
877+
step: (edge: Vec4OrLessOrFloat) => Node<"vec4">;
878+
}
834879
}
835880

836881
// GLSL alias function

0 commit comments

Comments
 (0)