From 53054740dccae3e09768e5d926a95cc4739e1ee9 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Thu, 25 Jan 2024 10:00:14 -0500 Subject: [PATCH] WebGPURenderer: ReflectorNode + Examples (#787) * WebGPURenderer: ReflectorNode + Examples * Fix * Update three.js * Add examples * getMaxAnisotropy * Updates * Update patch * Delete examples * Fix --- examples-testing/changes.patch | 81 ++++++++++++++----- examples-testing/index.js | 3 + three.js | 2 +- types/three/examples/jsm/nodes/Nodes.d.ts | 2 + .../jsm/nodes/accessors/CubeTextureNode.d.ts | 4 +- .../jsm/nodes/accessors/TextureNode.d.ts | 6 +- .../jsm/nodes/display/GaussianBlurNode.d.ts | 26 ++++++ .../examples/jsm/nodes/display/PassNode.d.ts | 3 +- .../jsm/nodes/utils/ReflectorNode.d.ts | 30 +++++++ .../jsm/renderers/common/Renderer.d.ts | 6 ++ .../jsm/renderers/webgl/WebGLBackend.d.ts | 2 + .../jsm/renderers/webgpu/WebGPUBackend.d.ts | 4 + 12 files changed, 141 insertions(+), 28 deletions(-) create mode 100644 types/three/examples/jsm/nodes/display/GaussianBlurNode.d.ts create mode 100644 types/three/examples/jsm/nodes/utils/ReflectorNode.d.ts diff --git a/examples-testing/changes.patch b/examples-testing/changes.patch index 8ca2d0938..95b9fdcad 100644 --- a/examples-testing/changes.patch +++ b/examples-testing/changes.patch @@ -13861,12 +13861,53 @@ index b8fb383..0bcc65c 100644 const gui = new GUI(); +diff --git a/examples-testing/examples/webgpu_materials_texture_anisotropy.ts b/examples-testing/examples/webgpu_materials_texture_anisotropy.ts +index 00672da..cf96e31 100644 +--- a/examples-testing/examples/webgpu_materials_texture_anisotropy.ts ++++ b/examples-testing/examples/webgpu_materials_texture_anisotropy.ts +@@ -3,9 +3,9 @@ import * as THREE from 'three'; + import Stats from 'three/addons/libs/stats.module.js'; + import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'; + +-let container, stats; ++let container: HTMLDivElement, stats: Stats; + +-let camera, scene1, scene2, renderer; ++let camera: THREE.PerspectiveCamera, scene1: THREE.Scene, scene2: THREE.Scene, renderer: WebGPURenderer; + + let mouseX = 0, + mouseY = 0; +@@ -76,11 +76,11 @@ async function init() { + texture2.repeat.set(512, 512); + + if (maxAnisotropy > 0) { +- document.getElementById('val_left').innerHTML = texture1.anisotropy; +- document.getElementById('val_right').innerHTML = texture2.anisotropy; ++ document.getElementById('val_left')!.innerHTML = texture1.anisotropy.toString(); ++ document.getElementById('val_right')!.innerHTML = texture2.anisotropy.toString(); + } else { +- document.getElementById('val_left').innerHTML = 'not supported'; +- document.getElementById('val_right').innerHTML = 'not supported'; ++ document.getElementById('val_left')!.innerHTML = 'not supported'; ++ document.getElementById('val_right')!.innerHTML = 'not supported'; + } + + // +@@ -115,7 +115,7 @@ function onWindowResize() { + renderer.setSize(window.innerWidth, window.innerHeight); + } + +-function onDocumentMouseMove(event) { ++function onDocumentMouseMove(event: MouseEvent) { + const windowHalfX = window.innerWidth / 2; + const windowHalfY = window.innerHeight / 2; + diff --git a/examples-testing/examples/webgpu_materials_video.ts b/examples-testing/examples/webgpu_materials_video.ts -index f50456f..59ec321 100644 +index fbbabfc..a1a82bd 100644 --- a/examples-testing/examples/webgpu_materials_video.ts +++ b/examples-testing/examples/webgpu_materials_video.ts -@@ -3,11 +3,14 @@ import * as THREE from 'three'; - import WebGPU from 'three/addons/capabilities/WebGPU.js'; +@@ -2,11 +2,14 @@ import * as THREE from 'three'; + import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'; -let container; @@ -13883,7 +13924,7 @@ index f50456f..59ec321 100644 let mouseX = 0; let mouseY = 0; -@@ -15,14 +18,14 @@ let mouseY = 0; +@@ -14,20 +17,20 @@ let mouseY = 0; let windowHalfX = window.innerWidth / 2; let windowHalfY = window.innerHeight / 2; @@ -13902,16 +13943,14 @@ index f50456f..59ec321 100644 startButton.addEventListener('click', function () { init(); }); -@@ -34,7 +37,7 @@ function init() { - throw new Error('No WebGPU support'); - } + function init() { - const overlay = document.getElementById('overlay'); + const overlay = document.getElementById('overlay')!; overlay.remove(); container = document.createElement('div'); -@@ -55,7 +58,7 @@ function init() { +@@ -48,7 +51,7 @@ function init() { renderer.setAnimationLoop(render); container.appendChild(renderer.domElement); @@ -13920,7 +13959,7 @@ index f50456f..59ec321 100644 video.play(); video.addEventListener('play', function () { this.currentTime = 3; -@@ -131,7 +134,7 @@ function onWindowResize() { +@@ -124,7 +127,7 @@ function onWindowResize() { renderer.setSize(window.innerWidth, window.innerHeight); } @@ -13929,7 +13968,7 @@ index f50456f..59ec321 100644 const uvs = geometry.attributes.uv.array; for (let i = 0; i < uvs.length; i += 2) { -@@ -140,7 +143,7 @@ function change_uvs(geometry, unitx, unity, offsetx, offsety) { +@@ -133,7 +136,7 @@ function change_uvs(geometry, unitx, unity, offsetx, offsety) { } } @@ -13938,7 +13977,7 @@ index f50456f..59ec321 100644 mouseX = event.clientX - windowHalfX; mouseY = (event.clientY - windowHalfY) * 0.3; } -@@ -161,20 +164,20 @@ function render() { +@@ -154,20 +157,20 @@ function render() { for (let i = 0; i < cube_count; i++) { material = materials[i]; @@ -13966,7 +14005,7 @@ index f50456f..59ec321 100644 } } -@@ -182,8 +185,8 @@ function render() { +@@ -175,8 +178,8 @@ function render() { for (let i = 0; i < cube_count; i++) { mesh = meshes[i]; @@ -14114,11 +14153,11 @@ index 4184cb4..f6d36c0 100644 torusKnot.rotation.x += 0.25 * delta; diff --git a/examples-testing/examples/webgpu_video_panorama.ts b/examples-testing/examples/webgpu_video_panorama.ts -index 527cc17..eb03f96 100644 +index c6e051f..dca0db3 100644 --- a/examples-testing/examples/webgpu_video_panorama.ts +++ b/examples-testing/examples/webgpu_video_panorama.ts -@@ -3,7 +3,7 @@ import * as THREE from 'three'; - import WebGPU from 'three/addons/capabilities/WebGPU.js'; +@@ -2,7 +2,7 @@ import * as THREE from 'three'; + import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js'; -let camera, scene, renderer; @@ -14126,16 +14165,16 @@ index 527cc17..eb03f96 100644 let isUserInteracting = false, lon = 0, -@@ -26,7 +26,7 @@ function init() { - throw new Error('No WebGPU support'); - } +@@ -19,7 +19,7 @@ const distance = 0.5; + init(); + function init() { - const container = document.getElementById('container'); + const container = document.getElementById('container')!; camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.25, 10); -@@ -36,7 +36,7 @@ function init() { +@@ -29,7 +29,7 @@ function init() { // invert the geometry on the x-axis so that all of the faces point inward geometry.scale(-1, 1, 1); @@ -14144,7 +14183,7 @@ index 527cc17..eb03f96 100644 video.play(); const texture = new THREE.VideoTexture(video); -@@ -68,7 +68,7 @@ function onWindowResize() { +@@ -61,7 +61,7 @@ function onWindowResize() { renderer.setSize(window.innerWidth, window.innerHeight); } @@ -14153,7 +14192,7 @@ index 527cc17..eb03f96 100644 isUserInteracting = true; onPointerDownPointerX = event.clientX; -@@ -78,7 +78,7 @@ function onPointerDown(event) { +@@ -71,7 +71,7 @@ function onPointerDown(event) { onPointerDownLat = lat; } diff --git a/examples-testing/index.js b/examples-testing/index.js index b952f8694..4a636e1d5 100644 --- a/examples-testing/index.js +++ b/examples-testing/index.js @@ -361,6 +361,7 @@ const files = { // 'webgpu_occlusion', // 'webgpu_particles', // 'webgpu_portal', + // 'webgpu_reflection', // 'webgpu_rtt', // 'webgpu_sandbox', // 'webgpu_shadertoy', @@ -374,7 +375,9 @@ const files = { // 'webgpu_tsl_transpiler', 'webgpu_video_panorama', 'webgpu_postprocessing_afterimage', + // 'webgpu_mirror', // 'webgpu_multisampled_renderbuffers', + 'webgpu_materials_texture_anisotropy', ], webaudio: ['webaudio_orientation', 'webaudio_sandbox', 'webaudio_timing', 'webaudio_visualizer'], webxr: [ diff --git a/three.js b/three.js index 02d41f89d..bd33e679a 160000 --- a/three.js +++ b/three.js @@ -1 +1 @@ -Subproject commit 02d41f89d5a58bee0fbcfcab169409e5337de403 +Subproject commit bd33e679a5b634842bb39a377b9a37eb68bc0e2a diff --git a/types/three/examples/jsm/nodes/Nodes.d.ts b/types/three/examples/jsm/nodes/Nodes.d.ts index 2f7a9217d..b0633e5b7 100644 --- a/types/three/examples/jsm/nodes/Nodes.d.ts +++ b/types/three/examples/jsm/nodes/Nodes.d.ts @@ -179,6 +179,7 @@ export { triplanarTextures, triplanarTexture, } from './utils/TriplanarTexturesNode.js'; +export { default as ReflectorNode, reflector, ReflectorNodeParameters } from './utils/ReflectorNode.js'; // shader node export * from './shadernode/ShaderNode.js'; @@ -322,6 +323,7 @@ export { depthPixel, ViewportDepthNodeScope, } from './display/ViewportDepthNode.js'; +export { default as GaussianBlurNode, gaussianBlur } from './display/GaussianBlurNode.js'; export { default as AfterImageNode, afterImage } from './display/AfterImageNode.js'; export { default as PassNode, pass, depthPass, PassNodeScope } from './display/PassNode.js'; diff --git a/types/three/examples/jsm/nodes/accessors/CubeTextureNode.d.ts b/types/three/examples/jsm/nodes/accessors/CubeTextureNode.d.ts index 847718eb9..a12b0615c 100644 --- a/types/three/examples/jsm/nodes/accessors/CubeTextureNode.d.ts +++ b/types/three/examples/jsm/nodes/accessors/CubeTextureNode.d.ts @@ -5,8 +5,8 @@ import { NodeRepresentation, ShaderNodeObject } from '../shadernode/ShaderNode.j export default class CubeTextureNode extends TextureNode { isCubeTextureNode: boolean; - uvNode: Node | null; - levelNode: Node | null; + uvNode: ShaderNodeObject | null; + levelNode: ShaderNodeObject | null; constructor(value: CubeTexture, uvNode?: Node | null, levelNode?: Node | null); diff --git a/types/three/examples/jsm/nodes/accessors/TextureNode.d.ts b/types/three/examples/jsm/nodes/accessors/TextureNode.d.ts index 74e596c6b..aa886d2b0 100644 --- a/types/three/examples/jsm/nodes/accessors/TextureNode.d.ts +++ b/types/three/examples/jsm/nodes/accessors/TextureNode.d.ts @@ -6,10 +6,10 @@ import { NodeRepresentation, ShaderNodeObject } from '../shadernode/ShaderNode.j export default class TextureNode extends UniformNode { isTextureNode: true; - uvNode: Node | null; - levelNode: Node | null; + uvNode: ShaderNodeObject | null; + levelNode: ShaderNodeObject | null; - constructor(value: Texture, uvNode?: Node, levelNode?: Node | null); + constructor(value: Texture, uvNode?: ShaderNodeObject, levelNode?: ShaderNodeObject | null); getDefaultUV(): Node; diff --git a/types/three/examples/jsm/nodes/display/GaussianBlurNode.d.ts b/types/three/examples/jsm/nodes/display/GaussianBlurNode.d.ts new file mode 100644 index 000000000..0f2b061e7 --- /dev/null +++ b/types/three/examples/jsm/nodes/display/GaussianBlurNode.d.ts @@ -0,0 +1,26 @@ +import { Vector2 } from '../../../../src/Three.js'; +import TempNode from '../core/TempNode.js'; +import TextureNode from '../accessors/TextureNode.js'; +import Node from '../core/Node.js'; +import { NodeRepresentation, ShaderNodeObject } from '../shadernode/ShaderNode.js'; + +export default class GaussianBlurNode extends TempNode { + textureNode: TextureNode; + sigma: number; + + directionNode: Node; + + resolution: Vector2; + + constructor(textureNode: TextureNode, sigma?: number); + + setSize(width: number, height: number): void; +} + +export const gaussianBlur: (node: NodeRepresentation, sigma?: number) => ShaderNodeObject; + +declare module '../shadernode/ShaderNode.js' { + interface NodeElements { + gaussianBlur: typeof gaussianBlur; + } +} diff --git a/types/three/examples/jsm/nodes/display/PassNode.d.ts b/types/three/examples/jsm/nodes/display/PassNode.d.ts index 720ae3e3f..0c7e958bc 100644 --- a/types/three/examples/jsm/nodes/display/PassNode.d.ts +++ b/types/three/examples/jsm/nodes/display/PassNode.d.ts @@ -2,6 +2,7 @@ import { Camera, RenderTarget, Scene, Texture } from '../../../../src/Three.js'; import { ShaderNodeObject } from '../shadernode/ShaderNode.js'; import TempNode from '../core/TempNode.js'; import TextureNode from '../accessors/TextureNode.js'; +import Node from '../core/Node.js'; declare class PassTextureNode extends TextureNode { passNode: PassNode; @@ -24,7 +25,7 @@ export default class PassNode extends TempNode { getTextureDepthNode(): ShaderNodeObject; - getDepthNode(): Node; + getDepthNode(): ShaderNodeObject; setSize(width: number, height: number): void; diff --git a/types/three/examples/jsm/nodes/utils/ReflectorNode.d.ts b/types/three/examples/jsm/nodes/utils/ReflectorNode.d.ts new file mode 100644 index 000000000..548ea8bcf --- /dev/null +++ b/types/three/examples/jsm/nodes/utils/ReflectorNode.d.ts @@ -0,0 +1,30 @@ +import { Camera, Object3D, RenderTarget } from '../../../../src/Three.js'; +import TextureNode from '../accessors/TextureNode.js'; +import { ShaderNodeObject } from '../shadernode/ShaderNode.js'; + +export interface ReflectorNodeParameters { + target?: Object3D | undefined; + resolution?: number | undefined; + generateMipmaps?: boolean | undefined; + bounces?: boolean | undefined; +} + +export default class ReflectorNode extends TextureNode { + target: Object3D; + resolution: number; + generateMipmaps: boolean; + bounces: boolean; + + virtualCameras: WeakMap; + renderTargets: WeakMap; + + constructor(parameters?: ReflectorNodeParameters); + + getTextureNode(): TextureNode; + + getVirtualCamera(camera: Camera): Camera; + + getRenderTarget(camera: Camera): RenderTarget; +} + +export const reflector: (parameters?: ReflectorNodeParameters) => ShaderNodeObject; diff --git a/types/three/examples/jsm/renderers/common/Renderer.d.ts b/types/three/examples/jsm/renderers/common/Renderer.d.ts index ef4ab9660..8fca9b1ea 100644 --- a/types/three/examples/jsm/renderers/common/Renderer.d.ts +++ b/types/three/examples/jsm/renderers/common/Renderer.d.ts @@ -103,6 +103,12 @@ export default class Renderer { renderAsync(scene: Scene, camera: Camera): Promise; + getMaxAnisotropy(): number; + + getActiveCubeFace(): number; + + getActiveMipmapLevel(): number; + setAnimationLoop(callback: ((time: DOMHighResTimeStamp) => void) | null): Promise; /** diff --git a/types/three/examples/jsm/renderers/webgl/WebGLBackend.d.ts b/types/three/examples/jsm/renderers/webgl/WebGLBackend.d.ts index b99f7610b..c26a040de 100644 --- a/types/three/examples/jsm/renderers/webgl/WebGLBackend.d.ts +++ b/types/three/examples/jsm/renderers/webgl/WebGLBackend.d.ts @@ -5,4 +5,6 @@ export default class WebGLBackend extends Backend { constructor(parameters?: BackendParameters); get coordinateSystem(): CoordinateSystem; + + getMaxAnisotropy(): number; } diff --git a/types/three/examples/jsm/renderers/webgpu/WebGPUBackend.d.ts b/types/three/examples/jsm/renderers/webgpu/WebGPUBackend.d.ts index 02e9a5e24..bebc02c29 100644 --- a/types/three/examples/jsm/renderers/webgpu/WebGPUBackend.d.ts +++ b/types/three/examples/jsm/renderers/webgpu/WebGPUBackend.d.ts @@ -14,4 +14,8 @@ export default class WebGPUBackend extends Backend { constructor(parameters?: WebGPUBackendParameters); get coordinateSystem(): CoordinateSystem; + + // utils public + + getMaxAnisotropy(): number; }