r3f-peridot 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/FindSurfaces.ts","../src/utils/CustomOutlinePass.ts","../src/components/OutlineEffect.tsx","../src/utils/VertexWelder.ts","../src/utils/useSurfaceIds.ts"],"names":["THREE","Pass","THREE2","FullScreenQuad","forwardRef","useThree","useRef","useEffect","THREE3","EffectComposer","RenderPass","ShaderPass","FXAAShader","useFrame","useImperativeHandle","THREE4"],"mappings":"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","file":"index.js","sourcesContent":["import * as THREE from 'three'\n\n/*\n This class computes \"surface IDs\" for a given mesh.\n\n A \"surface\" is defined as a set of triangles that share vertices.\n \n Inspired by Ian MacLarty, see:\n https://twitter.com/ianmaclarty/status/1499494878908403712\n*/\nclass FindSurfaces {\n surfaceId: number = 0\n\n constructor() {\n // This identifier, must be globally unique for each surface\n // across all geometry rendered on screen\n this.surfaceId = 0\n }\n\n /*\n * Returns the surface Ids as a Float32Array that can be inserted as a vertex attribute\n */\n getSurfaceIdAttribute(mesh: THREE.Mesh): Float32Array {\n const bufferGeometry = mesh.geometry\n const numVertices = bufferGeometry.attributes.position.count\n const vertexIdToSurfaceId = this._generateSurfaceIds(mesh)\n\n const colors: number[] = []\n for (let i = 0; i < numVertices; i++) {\n const vertexId = i\n const surfaceId = vertexIdToSurfaceId[vertexId]\n\n colors.push(surfaceId, 0, 0, 1)\n }\n\n const colorsTypedArray = new Float32Array(colors)\n return colorsTypedArray\n }\n\n /*\n * Returns a `vertexIdToSurfaceId` map\n * given a vertex, returns the surfaceId\n */\n _generateSurfaceIds(mesh: THREE.Mesh): { [key: number]: number } {\n const bufferGeometry = mesh.geometry\n if (!bufferGeometry.index) {\n // No index buffer, create one\n const indices: number[] = []\n const numVertices = bufferGeometry.attributes.position.count\n for (let i = 0; i < numVertices; i++) {\n indices.push(i)\n }\n bufferGeometry.setIndex(indices)\n }\n const numIndices = bufferGeometry.index!.count\n const indexBuffer = bufferGeometry.index!.array\n // For each vertex, search all its neighbors\n const vertexMap: { [key: number]: number[] } = {}\n for (let i = 0; i < numIndices; i += 3) {\n const i1 = indexBuffer[i + 0]\n const i2 = indexBuffer[i + 1]\n const i3 = indexBuffer[i + 2]\n\n add(i1, i2)\n add(i1, i3)\n add(i2, i3)\n }\n function add(a: number, b: number) {\n if (vertexMap[a] == undefined) vertexMap[a] = []\n if (vertexMap[b] == undefined) vertexMap[b] = []\n\n if (vertexMap[a].indexOf(b) == -1) vertexMap[a].push(b)\n if (vertexMap[b].indexOf(a) == -1) vertexMap[b].push(a)\n }\n\n // Find cycles\n const frontierNodes = Object.keys(vertexMap).map((v) => Number(v))\n const exploredNodes: { [key: number]: boolean } = {}\n const vertexIdToSurfaceId: { [key: number]: number } = {}\n\n while (frontierNodes.length > 0) {\n const node = frontierNodes.pop()!\n if (exploredNodes[node]) continue\n\n // Get all neighbors recursively\n const surfaceVertices = getNeighborsNonRecursive(node)\n // Mark them as explored\n for (const v of surfaceVertices) {\n exploredNodes[v] = true\n vertexIdToSurfaceId[v] = this.surfaceId\n }\n\n this.surfaceId += 1\n }\n\n function getNeighborsNonRecursive(node: number): number[] {\n const frontier = [node]\n const explored: { [key: number]: boolean } = {}\n const result: number[] = []\n\n while (frontier.length > 0) {\n const currentNode = frontier.pop()!\n if (explored[currentNode]) continue\n const neighbors = vertexMap[currentNode]\n result.push(currentNode)\n\n explored[currentNode] = true\n\n for (const n of neighbors) {\n if (!explored[n]) {\n frontier.push(n)\n }\n }\n }\n\n return result\n }\n\n return vertexIdToSurfaceId\n }\n}\n\nexport default FindSurfaces\n\nexport function getSurfaceIdMaterial() {\n return new THREE.ShaderMaterial({\n uniforms: {\n maxSurfaceId: { value: 1 },\n },\n vertexShader: getVertexShader(),\n fragmentShader: getFragmentShader(),\n vertexColors: true,\n })\n}\n\nfunction getVertexShader() {\n return `\n varying vec2 v_uv;\n varying vec4 vColor;\n\n void main() {\n v_uv = uv;\n #ifdef USE_COLOR_ALPHA\n vColor = color;\n #else\n vColor = vec4(color, 1.0);\n #endif\n\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n `\n}\n\nfunction getFragmentShader() {\n return `\n varying vec2 v_uv;\n varying vec4 vColor;\n uniform float maxSurfaceId;\n\n void main() {\n // Normalize the surfaceId when writing to texture\n // Surface ID needs rounding as precision can be lost in perspective correct interpolation \n // - see https://github.com/OmarShehata/webgl-outlines/issues/9 for other solutions eg. flat interpolation.\n float surfaceId = round(vColor.r) / maxSurfaceId;\n gl_FragColor = vec4(surfaceId, 0.0, 0.0, 1.0);\n }\n `\n}\n\n// For debug rendering, assign a random color\n// to each surfaceId\nexport function getDebugSurfaceIdMaterial() {\n return new THREE.ShaderMaterial({\n uniforms: {},\n vertexShader: getVertexShader(),\n fragmentShader: `\n varying vec2 v_uv;\n varying vec4 vColor;\n\n void main() { \n int surfaceId = int(round(vColor.r) * 100.0);\n float R = float(surfaceId % 255) / 255.0;\n float G = float((surfaceId + 50) % 255) / 255.0;\n float B = float((surfaceId * 20) % 255) / 255.0;\n\n gl_FragColor = vec4(R, G, B, 1.0);\n }\n `,\n vertexColors: true,\n })\n}\n\n","import * as THREE from 'three'\nimport { Pass, FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js'\nimport { getSurfaceIdMaterial, getDebugSurfaceIdMaterial } from './FindSurfaces'\n\n/**\n * CustomOutlinePass - A post-processing pass that renders outlines based on depth,\n * normals, and surface IDs.\n *\n * Based on the webgl-outlines technique by Omar Shehata\n * https://github.com/OmarShehata/webgl-outlines\n */\nexport class CustomOutlinePass extends Pass {\n renderScene: THREE.Scene\n renderCamera: THREE.Camera\n resolution: THREE.Vector2\n fsQuad: FullScreenQuad\n surfaceBuffer: THREE.WebGLRenderTarget\n normalOverrideMaterial: THREE.MeshNormalMaterial\n surfaceIdOverrideMaterial: THREE.ShaderMaterial\n surfaceIdDebugOverrideMaterial: THREE.ShaderMaterial\n\n constructor(resolution: THREE.Vector2, scene: THREE.Scene, camera: THREE.Camera) {\n super()\n\n this.renderScene = scene\n this.renderCamera = camera\n this.resolution = new THREE.Vector2(resolution.x, resolution.y)\n\n this.fsQuad = new FullScreenQuad(null as any)\n this.fsQuad.material = this.createOutlinePostProcessMaterial()\n\n // Create a buffer to store the normals of the scene onto\n // or store the \"surface IDs\"\n const surfaceBuffer = new THREE.WebGLRenderTarget(this.resolution.x, this.resolution.y)\n surfaceBuffer.texture.format = THREE.RGBAFormat\n surfaceBuffer.texture.type = THREE.HalfFloatType\n surfaceBuffer.texture.minFilter = THREE.NearestFilter\n surfaceBuffer.texture.magFilter = THREE.NearestFilter\n surfaceBuffer.texture.generateMipmaps = false\n surfaceBuffer.stencilBuffer = false\n this.surfaceBuffer = surfaceBuffer\n\n this.normalOverrideMaterial = new THREE.MeshNormalMaterial()\n this.surfaceIdOverrideMaterial = getSurfaceIdMaterial()\n this.surfaceIdDebugOverrideMaterial = getDebugSurfaceIdMaterial()\n }\n\n dispose() {\n this.surfaceBuffer.dispose()\n this.fsQuad.dispose()\n }\n\n updateMaxSurfaceId(maxSurfaceId: number) {\n this.surfaceIdOverrideMaterial.uniforms.maxSurfaceId.value = maxSurfaceId\n }\n\n setSize(width: number, height: number) {\n this.surfaceBuffer.setSize(width, height)\n this.resolution.set(width, height)\n\n const screenSize = new THREE.Vector4(\n this.resolution.x,\n this.resolution.y,\n 1 / this.resolution.x,\n 1 / this.resolution.y\n )\n const material = this.fsQuad.material as THREE.ShaderMaterial\n material.uniforms.screenSize.value.set(screenSize.x, screenSize.y, screenSize.z, screenSize.w)\n }\n\n getDebugVisualizeValue() {\n return (this.fsQuad.material as THREE.ShaderMaterial).uniforms.debugVisualize.value\n }\n\n isUsingSurfaceIds() {\n const debugVisualize = this.getDebugVisualizeValue()\n\n return (\n debugVisualize == 0 || // Main outlines v2 mode\n debugVisualize == 5 || // Render just surfaceID debug buffer\n debugVisualize == 6\n ) // Render just outlines with surfaceId\n }\n\n render(\n renderer: THREE.WebGLRenderer,\n writeBuffer: THREE.WebGLRenderTarget,\n readBuffer: THREE.WebGLRenderTarget\n ) {\n const debugVisualize = this.getDebugVisualizeValue()\n const isUsingSurfaceIds = this.isUsingSurfaceIds()\n\n // Turn off writing to the depth buffer\n // because we need to read from it in the subsequent passes.\n const depthBufferValue = writeBuffer.depthBuffer\n writeBuffer.depthBuffer = false\n\n // 1. Re-render the scene to capture all normals (or surface IDs) in a texture.\n renderer.setRenderTarget(this.surfaceBuffer)\n const overrideMaterialValue = this.renderScene.overrideMaterial\n\n if (isUsingSurfaceIds) {\n // Render the \"surface ID buffer\"\n if (debugVisualize == 5) {\n this.renderScene.overrideMaterial = this.surfaceIdDebugOverrideMaterial\n } else {\n this.renderScene.overrideMaterial = this.surfaceIdOverrideMaterial\n }\n } else {\n // Render normal buffer\n this.renderScene.overrideMaterial = this.normalOverrideMaterial\n }\n\n renderer.render(this.renderScene, this.renderCamera)\n this.renderScene.overrideMaterial = overrideMaterialValue\n\n const material = this.fsQuad.material as THREE.ShaderMaterial\n material.uniforms['depthBuffer'].value = readBuffer.depthTexture\n material.uniforms['surfaceBuffer'].value = this.surfaceBuffer.texture\n material.uniforms['sceneColorBuffer'].value = readBuffer.texture\n\n // 2. Draw the outlines using the depth texture and normal texture\n // and combine it with the scene color\n if (this.renderToScreen) {\n // If this is the last effect, then renderToScreen is true.\n // So we should render to the screen by setting target null\n // Otherwise, just render into the writeBuffer that the next effect will use as its read buffer.\n renderer.setRenderTarget(null)\n this.fsQuad.render(renderer)\n } else {\n renderer.setRenderTarget(writeBuffer)\n this.fsQuad.render(renderer)\n }\n\n // Reset the depthBuffer value so we continue writing to it in the next render.\n writeBuffer.depthBuffer = depthBufferValue\n }\n\n get vertexShader() {\n return `\n\t\t\tvarying vec2 vUv;\n\t\t\tvoid main() {\n\t\t\t\tvUv = uv;\n\t\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n\t\t\t}\n\t\t\t`\n }\n\n get fragmentShader() {\n return `\n\t\t\t#include <packing>\n\t\t\t// The above include imports \"perspectiveDepthToViewZ\"\n\t\t\t// and other GLSL functions from ThreeJS we need for reading depth.\n\t\t\tuniform sampler2D sceneColorBuffer;\n\t\t\tuniform sampler2D depthBuffer;\n\t\t\tuniform sampler2D surfaceBuffer;\n\t\t\tuniform float cameraNear;\n\t\t\tuniform float cameraFar;\n\t\t\tuniform vec4 screenSize;\n\t\t\tuniform vec3 outlineColor;\n\t\t\tuniform vec4 multiplierParameters;\n\t\t\tuniform int debugVisualize;\n\n\t\t\tvarying vec2 vUv;\n\n\t\t\t// Helper functions for reading from depth buffer.\n\t\t\tfloat readDepth (sampler2D depthSampler, vec2 coord) {\n\t\t\t\tfloat fragCoordZ = texture2D(depthSampler, coord).x;\n\t\t\t\tfloat viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );\n\t\t\t\treturn viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );\n\t\t\t}\n\t\t\tfloat getLinearDepth(vec3 pos) {\n\t\t\t\treturn -(viewMatrix * vec4(pos, 1.0)).z;\n\t\t\t}\n\n\t\t\tfloat getLinearScreenDepth(sampler2D map) {\n\t\t\t\t\tvec2 uv = gl_FragCoord.xy * screenSize.zw;\n\t\t\t\t\treturn readDepth(map,uv);\n\t\t\t}\n\t\t\t// Helper functions for reading normals and depth of neighboring pixels.\n\t\t\tfloat getPixelDepth(int x, int y) {\n\t\t\t\t// screenSize.zw is pixel size \n\t\t\t\t// vUv is current position\n\t\t\t\treturn readDepth(depthBuffer, vUv + screenSize.zw * vec2(x, y));\n\t\t\t}\n\t\t\t// \"surface value\" is either the normal or the \"surfaceID\"\n\t\t\tvec3 getSurfaceValue(int x, int y) {\n\t\t\t\tvec3 val = texture2D(surfaceBuffer, vUv + screenSize.zw * vec2(x, y)).rgb;\n\t\t\t\treturn val;\n\t\t\t}\n\n\t\t\tfloat saturateValue(float num) {\n\t\t\t\treturn clamp(num, 0.0, 1.0);\n\t\t\t}\n\n\t\t\tfloat getSufaceIdDiff(vec3 surfaceValue) {\n\t\t\t\tfloat surfaceIdDiff = 0.0;\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, 0));\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, 1));\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, 1));\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, -1));\n\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, 1));\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, -1));\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(-1, 1));\n\t\t\t\tsurfaceIdDiff += distance(surfaceValue, getSurfaceValue(-1, -1));\n\t\t\t\treturn surfaceIdDiff;\n\t\t\t}\n\n\t\t\tvoid main() {\n\t\t\t\tvec4 sceneColor = texture2D(sceneColorBuffer, vUv);\n\t\t\t\tfloat depth = getPixelDepth(0, 0);\n\t\t\t\t// \"surfaceValue\" is either the normal or the surfaceId\n\t\t\t\tvec3 surfaceValue = getSurfaceValue(0, 0);\n\n\t\t\t\t// Get the difference between depth of neighboring pixels and current.\n\t\t\t\tfloat depthDiff = 0.0;\n\t\t\t\tdepthDiff += abs(depth - getPixelDepth(1, 0));\n\t\t\t\tdepthDiff += abs(depth - getPixelDepth(-1, 0));\n\t\t\t\tdepthDiff += abs(depth - getPixelDepth(0, 1));\n\t\t\t\tdepthDiff += abs(depth - getPixelDepth(0, -1));\n\n\t\t\t\t// Get the difference between surface values of neighboring pixels\n\t\t\t\t// and current\n\t\t\t\tfloat surfaceValueDiff = getSufaceIdDiff(surfaceValue);\n\t\t\t\t\n\t\t\t\t// Apply multiplier & bias to each \n\t\t\t\tfloat depthBias = multiplierParameters.x;\n\t\t\t\tfloat depthMultiplier = multiplierParameters.y;\n\t\t\t\tfloat normalBias = multiplierParameters.z;\n\t\t\t\tfloat normalMultiplier = multiplierParameters.w;\n\n\t\t\t\tdepthDiff = depthDiff * depthMultiplier;\n\t\t\t\tdepthDiff = saturateValue(depthDiff);\n\t\t\t\tdepthDiff = pow(depthDiff, depthBias);\n\n\t\t\t\tif (debugVisualize != 0 && debugVisualize != 6) {\n\t\t\t\t\t// Apply these params when using\n\t\t\t\t\t// normals instead of surfaceIds\n\t\t\t\t\tsurfaceValueDiff = surfaceValueDiff * normalMultiplier;\n\t\t\t\t\tsurfaceValueDiff = saturateValue(surfaceValueDiff);\n\t\t\t\t\tsurfaceValueDiff = pow(surfaceValueDiff, normalBias);\n\t\t\t\t} else {\n\t\t\t\t\tif (surfaceValueDiff != 0.0) surfaceValueDiff = 1.0;\n\t\t\t\t}\n\n\t\t\t\tfloat outline = saturateValue(surfaceValueDiff + depthDiff);\n\t\t\t\n\t\t\t\t// Combine outline with scene color.\n\t\t\t\tvec4 outlineColor = vec4(outlineColor, 1.0);\n\t\t\t\tgl_FragColor = vec4(mix(sceneColor, outlineColor, outline));\n\n\t\t\t\t//// For debug visualization of the different inputs to this shader.\n\t\t\t\tif (debugVisualize == 2) {\n\t\t\t\t\tgl_FragColor = sceneColor;\n\t\t\t\t}\n\t\t\t\tif (debugVisualize == 3) {\n\t\t\t\t\tgl_FragColor = vec4(vec3(depth), 1.0);\n\t\t\t\t}\n\t\t\t\tif (debugVisualize == 4 || debugVisualize == 5) {\n\t\t\t\t\t// 4 visualizes the normal buffer\n\t\t\t\t\t// 5 visualizes the surfaceID buffer \n\t\t\t\t\t// Either way they are the same buffer, we change \n\t\t\t\t\t// what we render into it\n\t\t\t\t\tgl_FragColor = vec4(surfaceValue, 1.0);\n\t\t\t\t}\n\t\t\t\tif (debugVisualize == 6 || debugVisualize == 7) {\n\t\t\t\t\t// Outlines only\n\t\t\t\t\tgl_FragColor = vec4(vec3(outline * outlineColor), 1.0);\n\t\t\t\t}\t\t\t\t\n\t\t\t}\n\t\t\t`\n }\n\n createOutlinePostProcessMaterial() {\n const camera = this.renderCamera as THREE.PerspectiveCamera | THREE.OrthographicCamera\n return new THREE.ShaderMaterial({\n uniforms: {\n debugVisualize: { value: 0 },\n sceneColorBuffer: { value: null },\n depthBuffer: { value: null },\n surfaceBuffer: { value: null },\n outlineColor: { value: new THREE.Color(0xffffff) },\n //4 scalar values packed in one uniform: depth multiplier, depth bias, and same for normals.\n multiplierParameters: {\n value: new THREE.Vector4(0.9, 20, 1, 1),\n },\n cameraNear: { value: camera.near },\n cameraFar: { value: camera.far },\n screenSize: {\n value: new THREE.Vector4(\n this.resolution.x,\n this.resolution.y,\n 1 / this.resolution.x,\n 1 / this.resolution.y\n ),\n },\n },\n vertexShader: this.vertexShader,\n fragmentShader: this.fragmentShader,\n })\n }\n}\n\n","import { useEffect, useRef, forwardRef, useImperativeHandle } from 'react'\nimport { useThree, useFrame } from '@react-three/fiber'\nimport * as THREE from 'three'\nimport { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'\nimport { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'\nimport { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'\nimport { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js'\nimport { CustomOutlinePass } from '../utils/CustomOutlinePass'\nimport FindSurfaces from '../utils/FindSurfaces'\n\nexport interface OutlineEffectProps {\n /** Enable or disable the outline effect */\n enabled?: boolean\n /** Color of the outline (THREE.Color or hex string) */\n outlineColor?: THREE.Color | string\n /** Depth bias for edge detection (default: 0.9) */\n depthBias?: number\n /** Depth multiplier for edge detection (default: 20.0) */\n depthMultiplier?: number\n /** Normal bias for edge detection (default: 1.0) */\n normalBias?: number\n /** Normal multiplier for edge detection (default: 1.0) */\n normalMultiplier?: number\n /**\n * Debug visualization mode (default: 0)\n * - 0: Outlines V2 (surface ID based)\n * - 1: Outlines V1 (depth/normal based)\n * - 2: Original scene\n * - 3: Depth buffer\n * - 4: Normal buffer\n * - 5: SurfaceID debug buffer\n * - 6: Outlines only V2\n */\n debugVisualize?: number\n /** Array of objects to apply outlines to (currently not used, reserved for future) */\n selectedObjects?: THREE.Object3D[]\n}\n\nexport interface OutlineEffectRef {\n /** Update the maximum surface ID for proper normalization */\n updateMaxSurfaceId: (maxSurfaceId: number) => void\n}\n\n/**\n * OutlineEffect - A React Three Fiber component that adds post-processing outline effects\n * to your 3D scene using depth, normals, and surface ID detection.\n *\n * Based on the webgl-outlines technique by Omar Shehata\n * https://github.com/OmarShehata/webgl-outlines\n *\n * @example\n * ```tsx\n * import { Canvas } from '@react-three/fiber'\n * import { OutlineEffect } from 'r3f-gltf-outlines'\n *\n * function Scene() {\n * return (\n * <>\n * <OutlineEffect\n * outlineColor=\"#ffffff\"\n * depthBias={0.9}\n * depthMultiplier={20.0}\n * />\n * <mesh>\n * <boxGeometry />\n * <meshStandardMaterial />\n * </mesh>\n * </>\n * )\n * }\n * ```\n */\nexport const OutlineEffect = forwardRef<OutlineEffectRef, OutlineEffectProps>(\n (\n {\n enabled = true,\n outlineColor = '#ffffff',\n depthBias = 0.9,\n depthMultiplier = 20.0,\n normalBias = 1.0,\n normalMultiplier = 1.0,\n debugVisualize = 0,\n },\n ref\n ) => {\n const { gl, scene, camera, size, invalidate } = useThree()\n const composerRef = useRef<EffectComposer | null>(null)\n const outlinePassRef = useRef<CustomOutlinePass | null>(null)\n const fxaaPassRef = useRef<ShaderPass | null>(null)\n const surfaceIdsComputedRef = useRef<boolean>(false)\n\n useEffect(() => {\n if (!enabled) {\n if (composerRef.current) {\n composerRef.current.dispose()\n composerRef.current = null\n }\n return\n }\n\n const width = Math.max(1, size.width * gl.getPixelRatio())\n const height = Math.max(1, size.height * gl.getPixelRatio())\n\n // Create render target with depthTexture\n const depthTexture = new THREE.DepthTexture(width, height)\n const renderTarget = new THREE.WebGLRenderTarget(width, height, {\n depthTexture: depthTexture,\n depthBuffer: true,\n })\n\n // Create EffectComposer\n const composer = new EffectComposer(gl, renderTarget)\n composerRef.current = composer\n\n // Initial render pass\n const renderPass = new RenderPass(scene, camera)\n composer.addPass(renderPass)\n\n // Outline pass\n const customOutline = new CustomOutlinePass(new THREE.Vector2(width, height), scene, camera)\n customOutline.renderToScreen = true // Make it render to screen\n outlinePassRef.current = customOutline\n composer.addPass(customOutline)\n\n // Antialias pass\n const effectFXAA = new ShaderPass(FXAAShader)\n effectFXAA.uniforms['resolution'].value.set(1 / width, 1 / height)\n effectFXAA.renderToScreen = true // Make FXAA render to screen (last pass)\n customOutline.renderToScreen = false // Outline pass no longer renders to screen\n fxaaPassRef.current = effectFXAA\n composer.addPass(effectFXAA)\n\n return () => {\n composer.dispose()\n renderTarget.dispose()\n depthTexture.dispose()\n }\n }, [enabled, scene, camera, gl, size.width, size.height, invalidate])\n\n // Compute surface IDs when using debug mode 0, 5, or 6 (surface ID modes)\n useEffect(() => {\n if (!enabled) return\n\n const isUsingSurfaceIds = debugVisualize === 0 || debugVisualize === 5 || debugVisualize === 6\n\n if (isUsingSurfaceIds && !surfaceIdsComputedRef.current) {\n const findSurfaces = new FindSurfaces()\n let maxSurfaceId = 0\n\n // Traverse scene and apply surface IDs to all meshes\n scene.traverse((object) => {\n if (object instanceof THREE.Mesh && object.geometry) {\n try {\n const geometry = object.geometry\n\n // Compute surface IDs\n const surfaceIdAttribute = findSurfaces.getSurfaceIdAttribute(object)\n\n // Set as color attribute (used by the shader)\n geometry.setAttribute('color', new THREE.BufferAttribute(surfaceIdAttribute, 4))\n\n // Track max surface ID\n maxSurfaceId = Math.max(maxSurfaceId, findSurfaces.surfaceId)\n } catch (error) {\n console.warn('Failed to compute surface IDs for mesh:', error)\n }\n }\n })\n\n // Update the shader with the max surface ID (+1 for normalization)\n if (outlinePassRef.current && maxSurfaceId > 0) {\n outlinePassRef.current.updateMaxSurfaceId(maxSurfaceId + 1)\n }\n\n surfaceIdsComputedRef.current = true\n } else if (!isUsingSurfaceIds && surfaceIdsComputedRef.current) {\n // Cleanup: remove color attributes when not using surface IDs\n scene.traverse((object) => {\n if (object instanceof THREE.Mesh && object.geometry) {\n object.geometry.deleteAttribute('color')\n }\n })\n surfaceIdsComputedRef.current = false\n }\n }, [enabled, scene, debugVisualize])\n\n // Update uniforms every frame and render composer\n useFrame(() => {\n if (!enabled || !outlinePassRef.current || !composerRef.current) {\n return // Skip rendering if composer is not ready\n }\n\n const outlinePass = outlinePassRef.current\n const material = outlinePass.fsQuad.material as THREE.ShaderMaterial\n const uniforms = material.uniforms\n\n // Update outline color\n if (typeof outlineColor === 'string') {\n uniforms.outlineColor.value.set(outlineColor)\n } else {\n uniforms.outlineColor.value.copy(outlineColor)\n }\n\n // Update multiplier parameters\n uniforms.multiplierParameters.value.set(\n depthBias,\n depthMultiplier,\n normalBias,\n normalMultiplier\n )\n\n // Update debug visualize\n uniforms.debugVisualize.value = debugVisualize\n\n // Update camera near/far\n const cam = camera as THREE.PerspectiveCamera | THREE.OrthographicCamera\n if ('near' in cam) {\n uniforms.cameraNear.value = cam.near\n }\n if ('far' in cam) {\n uniforms.cameraFar.value = cam.far\n }\n\n // Render the composer\n composerRef.current.render()\n }, 1) // Positive priority = runs AFTER R3F's default render\n\n // Update size when canvas resizes\n useEffect(() => {\n if (!composerRef.current || !outlinePassRef.current || !fxaaPassRef.current) return\n\n const width = Math.max(1, size.width * gl.getPixelRatio())\n const height = Math.max(1, size.height * gl.getPixelRatio())\n\n composerRef.current.setSize(width, height)\n outlinePassRef.current.setSize(width, height)\n fxaaPassRef.current.uniforms['resolution'].value.set(1 / width, 1 / height)\n }, [size, gl])\n\n useImperativeHandle(ref, () => ({\n updateMaxSurfaceId: (maxSurfaceId: number) => {\n if (outlinePassRef.current) {\n outlinePassRef.current.updateMaxSurfaceId(maxSurfaceId)\n }\n },\n }))\n\n return null\n }\n)\n\nOutlineEffect.displayName = 'OutlineEffect'\n\n","/**\n * Merges together vertices along the edges between triangles\n * whose angle is below the given threshold.\n *\n * @param {number[]} vertices - Array of (x,y,z) positions as a flat list.\n * @param {number[]} indices - Array of indices of (v1, v2, v3) that define the triangles.\n * @param {number} [thresholdAngle=1] - In degrees. When the angle between the face normals\n * of 2 triangles is less than this threshold, the vertices along their shared edge are merged.\n * @returns {number[]} - A new index buffer without the extra vertices.\n */\nexport function weldVertices(\n vertices: number[],\n indices: number[],\n thresholdAngle: number = 1\n): number[] {\n const mergedMap: { [key: number]: number[] } = {}\n const vertexAliases: { [key: number]: number } = {}\n\n // Helper function to mark 2 vertices as merged\n function merge(i1: number, i2: number) {\n if (mergedMap[i1] == undefined) mergedMap[i1] = []\n\n mergedMap[i1].push(i2)\n }\n // Marks a given edge as deleted, and which one it's replaced by\n function aliasDeletedVertex(deletedVertex: number, remainingVertex: number) {\n if (deletedVertex == remainingVertex) return\n\n vertexAliases[deletedVertex] = remainingVertex\n }\n\n // `computeEdgesToMerge` looks over all the geometry and returns an array of edges that should be merged\n const edgesToMerge = computeEdgesToMerge(vertices, indices, thresholdAngle)\n // Convert the array of edges to merge to a map\n const edgesToMergeMap: { [key: string]: number[][] } = {}\n for (let i = 0; i < edgesToMerge.length; i++) {\n const edgesList = edgesToMerge[i]\n for (const index of edgesList) {\n const key = `${index[0]}_${index[1]}`\n edgesToMergeMap[key] = edgesList\n }\n }\n\n // Go through all triangles\n for (let i = 0; i < indices.length; i += 3) {\n // Look at all 3 edges\n const i1 = indices[i + 0]\n const i2 = indices[i + 1]\n const i3 = indices[i + 2]\n const edges: number[][] = []\n edges.push([i1, i2])\n edges.push([i1, i3])\n edges.push([i2, i3])\n for (const edge of edges) {\n let index0 = edge[0]\n let index1 = edge[1]\n const reverseEdge = [index1, index0]\n let isReverse = false\n\n // Check if this edge exists in the \"merge map\"\n let edgeToMerge: number[] | undefined\n const edgeKey = `${edge[0]}_${edge[1]}`\n const reverseEdgeKey = `${reverseEdge[0]}_${reverseEdge[1]}`\n if (edgesToMergeMap[edgeKey]) {\n edgeToMerge = edge\n }\n if (edgesToMergeMap[reverseEdgeKey]) {\n edgeToMerge = reverseEdge\n isReverse = true\n }\n\n if (edgeToMerge) {\n // Once you found an edge to merge,\n // you need to find its sibling edge, then merge the vertices in the right orientation\n // edgesToMergeMap[edge] contains two edges\n const edgeKeyToUse = isReverse ? reverseEdgeKey : edgeKey\n const possibleEdges = edgesToMergeMap[edgeKeyToUse]\n const possibleEdge1 = possibleEdges[0]\n const possibleEdge2 = possibleEdges[1]\n let otherEdge = possibleEdge1\n let originalEdge = possibleEdge2\n // Just pick the one that is NOT the current edgeToMerge\n if (\n (possibleEdge1[0] == index0 && possibleEdge1[1] == index1) ||\n (possibleEdge1[0] == index1 && possibleEdge1[1] == index0)\n ) {\n otherEdge = possibleEdge2\n originalEdge = possibleEdge1\n }\n\n let index2 = otherEdge[0]\n let index3 = otherEdge[1]\n index0 = originalEdge[0]\n index1 = originalEdge[1]\n\n if (index0 == index2 && index1 == index3) {\n // Not sure why this happens, but sometimes\n // you get these degenerate self edges\n continue\n }\n\n // Merge index0 and index1, with index2 & 3\n // Figure out which orientation to merge in\n // if you have:\n // 1 ---- 2\n // 3 ----- 4\n // You want to merge 1,3, and 2,4\n // NOT the other way around\n const v0 = getVertexFromIndexBuffer(index0, vertices)\n const v2 = getVertexFromIndexBuffer(index2, vertices)\n if (v0.distanceTo(v2) > 0.1) {\n const tmp = index3\n index3 = index2\n index2 = tmp\n }\n\n // Replace deleted indices\n if (vertexAliases[index0]) index0 = vertexAliases[index0]\n if (vertexAliases[index1]) index1 = vertexAliases[index1]\n if (vertexAliases[index2]) index2 = vertexAliases[index2]\n if (vertexAliases[index3]) index3 = vertexAliases[index3]\n\n merge(index0, index2)\n merge(index1, index3)\n // 0 was merged with 2, so we consider 2 the deleted vertex\n aliasDeletedVertex(index2, index0)\n aliasDeletedVertex(index3, index1)\n\n // Remove them edges we've merged from the map\n const mergedEdgeKey = `${index2}_${index3}`\n delete edgesToMergeMap[edgeKeyToUse]\n delete edgesToMergeMap[mergedEdgeKey]\n }\n }\n }\n\n const finalMergeMap = fillOutMergeMap(mergedMap)\n\n /* \n Go through the original index buffer\n replace indices with the merged indices\n \n So if you had the following 2 triangles\n \n \n [0, 1, 2] & [3, 4, 5]\n\n And the merge map tells you the following vertices are merged together:\n \t3 -> 1\n \t4 -> 2\n\n Then you want to replace 3 with 1 whenever you see it, etc.\n So the new buffer is:\n\n [0, 1, 2] & [1, 2, 5]\n\n */\n const newIndexBuffer: number[] = []\n for (let i = 0; i < indices.length; i++) {\n const index = indices[i]\n let newIndex = index\n if (finalMergeMap[index] != undefined) {\n newIndex = finalMergeMap[index]\n }\n\n newIndexBuffer.push(newIndex)\n }\n\n return newIndexBuffer\n}\n\nfunction getVertexFromIndexBuffer(index: number, positionAttr: number[]): Vector3 {\n return new Vector3(\n positionAttr[index * 3 + 0],\n positionAttr[index * 3 + 1],\n positionAttr[index * 3 + 2]\n )\n}\n\nfunction fillOutMergeMap(mergeMap: { [key: number]: number[] }): { [key: number]: number } {\n /*\n If your map looks like this:\n\n 0: [1, 2, 3]\n\n This creates entries for 1, 2, 3 so that they are all replaced with 0\n\n So the result looks like this:\n \n 0: [1, 2, 3],\n 1: [0],\n 2: [0],\n 3: [0],\n */\n const newMergeMap: { [key: number]: number } = {}\n for (let i = 0; i < Object.keys(mergeMap).length; i++) {\n const key = Number(Object.keys(mergeMap)[i]) // 0\n const indices = mergeMap[key] // [1, 2, 3]\n for (const ind of indices) {\n newMergeMap[ind] = key\n }\n }\n\n return newMergeMap\n}\n\n// Based on ThreeJS class\nclass Vector3 {\n x: number\n y: number\n z: number\n\n constructor(x: number = 0, y: number = 0, z: number = 0) {\n this.x = x\n this.y = y\n this.z = z\n }\n clone(): Vector3 {\n return new Vector3(this.x, this.y, this.z)\n }\n\n set(x: number, y: number, z: number): Vector3 {\n this.x = x\n this.y = y\n this.z = z\n return this\n }\n\n distanceTo(v: Vector3): number {\n const dx = this.x - v.x,\n dy = this.y - v.y,\n dz = this.z - v.z\n return Math.sqrt(dx * dx + dy * dy + dz * dz)\n }\n\n lengthSq(): number {\n return this.x * this.x + this.y * this.y + this.z * this.z\n }\n\n multiplyScalar(scalar: number): Vector3 {\n this.x *= scalar\n this.y *= scalar\n this.z *= scalar\n\n return this\n }\n\n subVectors(a: Vector3, b: Vector3): Vector3 {\n this.x = a.x - b.x\n this.y = a.y - b.y\n this.z = a.z - b.z\n\n return this\n }\n\n dot(v: Vector3): number {\n return this.x * v.x + this.y * v.y + this.z * v.z\n }\n cross(v: Vector3): Vector3 {\n return this.crossVectors(this, v)\n }\n\n crossVectors(a: Vector3, b: Vector3): Vector3 {\n const ax = a.x,\n ay = a.y,\n az = a.z\n const bx = b.x,\n by = b.y,\n bz = b.z\n\n this.x = ay * bz - az * by\n this.y = az * bx - ax * bz\n this.z = ax * by - ay * bx\n return this\n }\n}\n\n// Code below is adapted from ThreeJS EdgesGeometry\n// https://github.com/mrdoob/three.js/blob/dev/src/geometries/EdgesGeometry.js\nconst _v0 = new Vector3()\nconst _normal = new Vector3()\nconst precisionPoints = 4\nconst precision = Math.pow(10, precisionPoints)\n\nfunction hashVertex(v: Vector3): string {\n return `${Math.round(v.x * precision)},${Math.round(v.y * precision)},${Math.round(\n v.z * precision\n )}`\n}\n\nfunction getNormal(a: Vector3, b: Vector3, c: Vector3, resultNormal: Vector3): Vector3 {\n resultNormal.subVectors(c, b)\n _v0.subVectors(a, b)\n resultNormal.cross(_v0)\n\n const targetLengthSq = resultNormal.lengthSq()\n if (targetLengthSq > 0) {\n return resultNormal.multiplyScalar(1 / Math.sqrt(targetLengthSq))\n }\n\n return resultNormal.set(0, 0, 0)\n}\n\ninterface EdgeData {\n index0: number\n index1: number\n normal: Vector3\n}\n\nfunction computeEdgesToMerge(\n vertices: number[],\n indices: number[],\n thresholdAngle: number = 1\n): number[][][] {\n const DEG2RAD = Math.PI / 180\n const thresholdDot = Math.cos(DEG2RAD * thresholdAngle)\n\n const indexCount = indices.length\n\n const indexArr = [0, 0, 0]\n const hashes = new Array(3)\n\n const edgeData: { [key: string]: EdgeData | null } = {}\n const edgesToMerge: number[][][] = []\n\n for (let i = 0; i < indexCount; i += 3) {\n indexArr[0] = indices[i]\n indexArr[1] = indices[i + 1]\n indexArr[2] = indices[i + 2]\n\n const a = getVertexFromIndexBuffer(indexArr[0], vertices)\n const b = getVertexFromIndexBuffer(indexArr[1], vertices)\n const c = getVertexFromIndexBuffer(indexArr[2], vertices)\n\n getNormal(a, b, c, _normal)\n\n // create hashes for the edge from the vertices\n hashes[0] = hashVertex(a)\n hashes[1] = hashVertex(b)\n hashes[2] = hashVertex(c)\n\n // skip degenerate triangles\n if (hashes[0] === hashes[1] || hashes[1] === hashes[2] || hashes[2] === hashes[0]) {\n continue\n }\n\n // iterate over every edge\n for (let j = 0; j < 3; j++) {\n // get the first and next vertex making up the edge\n const jNext = (j + 1) % 3\n const vecHash0 = hashes[j]\n const vecHash1 = hashes[jNext]\n\n const hash = `${vecHash0}_${vecHash1}`\n const reverseHash = `${vecHash1}_${vecHash0}`\n\n if (reverseHash in edgeData && edgeData[reverseHash]) {\n // if we found a sibling edge add it into the vertex array if\n // it meets the angle threshold and delete the edge from the map.\n if (_normal.dot(edgeData[reverseHash]!.normal) > thresholdDot) {\n // Merge these two edges if they are separate\n const edge1 = [edgeData[reverseHash]!.index0, edgeData[reverseHash]!.index1]\n const edge2 = [indexArr[j], indexArr[jNext]]\n\n edgesToMerge.push([edge1, edge2])\n }\n edgeData[reverseHash] = null\n } else if (!(hash in edgeData)) {\n // if we've already got an edge here then skip adding a new one\n edgeData[hash] = {\n index0: indexArr[j],\n index1: indexArr[jNext],\n normal: _normal.clone(),\n }\n }\n }\n }\n\n return edgesToMerge\n}\n\n","import { useEffect } from 'react'\nimport { useThree } from '@react-three/fiber'\nimport * as THREE from 'three'\nimport FindSurfaces from './FindSurfaces'\n\n/**\n * Hook that computes and applies surface IDs to all meshes in the scene\n * This is required for outline V2 (surface ID based outlines) to work\n */\nexport function useSurfaceIds(enabled: boolean = true) {\n const { scene } = useThree()\n\n useEffect(() => {\n if (!enabled) return\n\n const findSurfaces = new FindSurfaces()\n let maxSurfaceId = 0\n\n // Traverse scene and apply surface IDs to all meshes\n scene.traverse((object) => {\n if (object instanceof THREE.Mesh && object.geometry) {\n const geometry = object.geometry\n\n // Compute surface IDs\n const surfaceIdAttribute = findSurfaces.getSurfaceIdAttribute(object)\n\n // Set as color attribute (used by the shader)\n geometry.setAttribute('color', new THREE.BufferAttribute(surfaceIdAttribute, 4))\n\n // Track max surface ID\n maxSurfaceId = Math.max(maxSurfaceId, findSurfaces.surfaceId)\n }\n })\n\n // Return the max surface ID for normalization in the shader\n return () => {\n // Cleanup: remove color attributes when disabled\n scene.traverse((object) => {\n if (object instanceof THREE.Mesh && object.geometry) {\n object.geometry.deleteAttribute('color')\n }\n })\n }\n }, [scene, enabled])\n}\n\nexport default useSurfaceIds\n\n"]}