[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M73BZW5ZPZQJMNX9F02DM3FZ":3,"skill-same:01M73BZW5ZPZQJMNX9F02DM3FZ":46},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":14,"repositoryHtmlUrl":27,"repositoryHomepageUrl":6,"ownerHtmlUrl":28,"ownerBlogUrl":29,"ownerDescription":30,"updatedAt":31,"install":32,"resources":45},"01M73BZW5ZPZQJMNX9F02DM3FZ","threejs-fundamentals",null,"Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.","kalash33\u002Fkstack","kalash33","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F90259149?v=4","01M7365X8Q0B73NYHA730SMZWN","Kalash Poddar","01M7365X9D0JK47C3Q0YCCK9Z2",0,"MIT","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fthreejs-fundamentals\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: threejs-fundamentals\ndescription: Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.\n---\n\n# Three.js Fundamentals\n\n## Quick Start\n\n```javascript\nimport * as THREE from \"three\";\n\n\u002F\u002F Create scene, camera, renderer\nconst scene = new THREE.Scene();\nconst camera = new THREE.PerspectiveCamera(\n  75,\n  window.innerWidth \u002F window.innerHeight,\n  0.1,\n  1000,\n);\nconst renderer = new THREE.WebGLRenderer({ antialias: true });\n\nrenderer.setSize(window.innerWidth, window.innerHeight);\nrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\ndocument.body.appendChild(renderer.domElement);\n\n\u002F\u002F Add a mesh\nconst geometry = new THREE.BoxGeometry(1, 1, 1);\nconst material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });\nconst cube = new THREE.Mesh(geometry, material);\nscene.add(cube);\n\n\u002F\u002F Add light\nscene.add(new THREE.AmbientLight(0xffffff, 0.5));\nconst dirLight = new THREE.DirectionalLight(0xffffff, 1);\ndirLight.position.set(5, 5, 5);\nscene.add(dirLight);\n\ncamera.position.z = 5;\n\n\u002F\u002F Animation loop\nfunction animate() {\n  requestAnimationFrame(animate);\n  cube.rotation.x += 0.01;\n  cube.rotation.y += 0.01;\n  renderer.render(scene, camera);\n}\nanimate();\n\n\u002F\u002F Handle resize\nwindow.addEventListener(\"resize\", () => {\n  camera.aspect = window.innerWidth \u002F window.innerHeight;\n  camera.updateProjectionMatrix();\n  renderer.setSize(window.innerWidth, window.innerHeight);\n});\n```\n\n## Core Classes\n\n### Scene\n\nContainer for all 3D objects, lights, and cameras.\n\n```javascript\nconst scene = new THREE.Scene();\nscene.background = new THREE.Color(0x000000); \u002F\u002F Solid color\nscene.background = texture; \u002F\u002F Skybox texture\nscene.background = cubeTexture; \u002F\u002F Cubemap\nscene.environment = envMap; \u002F\u002F Environment map for PBR\nscene.fog = new THREE.Fog(0xffffff, 1, 100); \u002F\u002F Linear fog\nscene.fog = new THREE.FogExp2(0xffffff, 0.02); \u002F\u002F Exponential fog\n```\n\n### Cameras\n\n**PerspectiveCamera** - Most common, simulates human eye.\n\n```javascript\n\u002F\u002F PerspectiveCamera(fov, aspect, near, far)\nconst camera = new THREE.PerspectiveCamera(\n  75, \u002F\u002F Field of view (degrees)\n  window.innerWidth \u002F window.innerHeight, \u002F\u002F Aspect ratio\n  0.1, \u002F\u002F Near clipping plane\n  1000, \u002F\u002F Far clipping plane\n);\n\ncamera.position.set(0, 5, 10);\ncamera.lookAt(0, 0, 0);\ncamera.updateProjectionMatrix(); \u002F\u002F Call after changing fov, aspect, near, far\n```\n\n**OrthographicCamera** - No perspective distortion, good for 2D\u002Fisometric.\n\n```javascript\n\u002F\u002F OrthographicCamera(left, right, top, bottom, near, far)\nconst aspect = window.innerWidth \u002F window.innerHeight;\nconst frustumSize = 10;\nconst camera = new THREE.OrthographicCamera(\n  (frustumSize * aspect) \u002F -2,\n  (frustumSize * aspect) \u002F 2,\n  frustumSize \u002F 2,\n  frustumSize \u002F -2,\n  0.1,\n  1000,\n);\n```\n\n**ArrayCamera** - Multiple viewports with sub-cameras.\n\n```javascript\nconst cameras = [];\nfor (let i = 0; i \u003C 4; i++) {\n  const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);\n  subcamera.viewport = new THREE.Vector4(\n    Math.floor(i % 2) * 0.5,\n    Math.floor(i \u002F 2) * 0.5,\n    0.5,\n    0.5,\n  );\n  cameras.push(subcamera);\n}\nconst arrayCamera = new THREE.ArrayCamera(cameras);\n```\n\n**CubeCamera** - Renders environment maps for reflections.\n\n```javascript\nconst cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);\nconst cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);\nscene.add(cubeCamera);\n\n\u002F\u002F Use for reflections\nmaterial.envMap = cubeRenderTarget.texture;\n\n\u002F\u002F Update each frame (expensive!)\ncubeCamera.position.copy(reflectiveMesh.position);\ncubeCamera.update(renderer, scene);\n```\n\n### WebGLRenderer\n\n```javascript\nconst renderer = new THREE.WebGLRenderer({\n  canvas: document.querySelector(\"#canvas\"), \u002F\u002F Optional existing canvas\n  antialias: true, \u002F\u002F Smooth edges\n  alpha: true, \u002F\u002F Transparent background\n  powerPreference: \"high-performance\", \u002F\u002F GPU hint\n  preserveDrawingBuffer: true, \u002F\u002F For screenshots\n});\n\nrenderer.setSize(width, height);\nrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\n\n\u002F\u002F Tone mapping\nrenderer.toneMapping = THREE.ACESFilmicToneMapping;\nrenderer.toneMappingExposure = 1.0;\n\n\u002F\u002F Color space (Three.js r152+)\nrenderer.outputColorSpace = THREE.SRGBColorSpace;\n\n\u002F\u002F Shadows\nrenderer.shadowMap.enabled = true;\nrenderer.shadowMap.type = THREE.PCFSoftShadowMap;\n\n\u002F\u002F Clear color\nrenderer.setClearColor(0x000000, 1);\n\n\u002F\u002F Render\nrenderer.render(scene, camera);\n```\n\n### Object3D\n\nBase class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.\n\n```javascript\nconst obj = new THREE.Object3D();\n\n\u002F\u002F Transform\nobj.position.set(x, y, z);\nobj.rotation.set(x, y, z); \u002F\u002F Euler angles (radians)\nobj.quaternion.set(x, y, z, w); \u002F\u002F Quaternion rotation\nobj.scale.set(x, y, z);\n\n\u002F\u002F Local vs World transforms\nobj.getWorldPosition(targetVector);\nobj.getWorldQuaternion(targetQuaternion);\nobj.getWorldDirection(targetVector);\n\n\u002F\u002F Hierarchy\nobj.add(child);\nobj.remove(child);\nobj.parent;\nobj.children;\n\n\u002F\u002F Visibility\nobj.visible = false;\n\n\u002F\u002F Layers (for selective rendering\u002Fraycasting)\nobj.layers.set(1);\nobj.layers.enable(2);\nobj.layers.disable(0);\n\n\u002F\u002F Traverse hierarchy\nobj.traverse((child) => {\n  if (child.isMesh) child.material.color.set(0xff0000);\n});\n\n\u002F\u002F Matrix updates\nobj.matrixAutoUpdate = true; \u002F\u002F Default: auto-update matrices\nobj.updateMatrix(); \u002F\u002F Manual matrix update\nobj.updateMatrixWorld(true); \u002F\u002F Update world matrix recursively\n```\n\n### Group\n\nEmpty container for organizing objects.\n\n```javascript\nconst group = new THREE.Group();\ngroup.add(mesh1);\ngroup.add(mesh2);\nscene.add(group);\n\n\u002F\u002F Transform entire group\ngroup.position.x = 5;\ngroup.rotation.y = Math.PI \u002F 4;\n```\n\n### Mesh\n\nCombines geometry and material.\n\n```javascript\nconst mesh = new THREE.Mesh(geometry, material);\n\n\u002F\u002F Multiple materials (one per geometry group)\nconst mesh = new THREE.Mesh(geometry, [material1, material2]);\n\n\u002F\u002F Useful properties\nmesh.geometry;\nmesh.material;\nmesh.castShadow = true;\nmesh.receiveShadow = true;\n\n\u002F\u002F Frustum culling\nmesh.frustumCulled = true; \u002F\u002F Default: skip if outside camera view\n\n\u002F\u002F Render order\nmesh.renderOrder = 10; \u002F\u002F Higher = rendered later\n```\n\n## Coordinate System\n\nThree.js uses a **right-handed coordinate system**:\n\n- **+X** points right\n- **+Y** points up\n- **+Z** points toward viewer (out of screen)\n\n```javascript\n\u002F\u002F Axes helper\nconst axesHelper = new THREE.AxesHelper(5);\nscene.add(axesHelper); \u002F\u002F Red=X, Green=Y, Blue=Z\n```\n\n## Math Utilities\n\n### Vector3\n\n```javascript\nconst v = new THREE.Vector3(x, y, z);\nv.set(x, y, z);\nv.copy(otherVector);\nv.clone();\n\n\u002F\u002F Operations (modify in place)\nv.add(v2);\nv.sub(v2);\nv.multiply(v2);\nv.multiplyScalar(2);\nv.divideScalar(2);\nv.normalize();\nv.negate();\nv.clamp(min, max);\nv.lerp(target, alpha);\n\n\u002F\u002F Calculations (return new value)\nv.length();\nv.lengthSq(); \u002F\u002F Faster than length()\nv.distanceTo(v2);\nv.dot(v2);\nv.cross(v2); \u002F\u002F Modifies v\nv.angleTo(v2);\n\n\u002F\u002F Transform\nv.applyMatrix4(matrix);\nv.applyQuaternion(q);\nv.project(camera); \u002F\u002F World to NDC\nv.unproject(camera); \u002F\u002F NDC to world\n```\n\n### Matrix4\n\n```javascript\nconst m = new THREE.Matrix4();\nm.identity();\nm.copy(other);\nm.clone();\n\n\u002F\u002F Build transforms\nm.makeTranslation(x, y, z);\nm.makeRotationX(theta);\nm.makeRotationY(theta);\nm.makeRotationZ(theta);\nm.makeRotationFromQuaternion(q);\nm.makeScale(x, y, z);\n\n\u002F\u002F Compose\u002Fdecompose\nm.compose(position, quaternion, scale);\nm.decompose(position, quaternion, scale);\n\n\u002F\u002F Operations\nm.multiply(m2); \u002F\u002F m = m * m2\nm.premultiply(m2); \u002F\u002F m = m2 * m\nm.invert();\nm.transpose();\n\n\u002F\u002F Camera matrices\nm.makePerspective(left, right, top, bottom, near, far);\nm.makeOrthographic(left, right, top, bottom, near, far);\nm.lookAt(eye, target, up);\n```\n\n### Quaternion\n\n```javascript\nconst q = new THREE.Quaternion();\nq.setFromEuler(euler);\nq.setFromAxisAngle(axis, angle);\nq.setFromRotationMatrix(matrix);\n\nq.multiply(q2);\nq.slerp(target, t); \u002F\u002F Spherical interpolation\nq.normalize();\nq.invert();\n```\n\n### Euler\n\n```javascript\nconst euler = new THREE.Euler(x, y, z, \"XYZ\"); \u002F\u002F Order matters!\neuler.setFromQuaternion(q);\neuler.setFromRotationMatrix(m);\n\n\u002F\u002F Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'\n```\n\n### Color\n\n```javascript\nconst color = new THREE.Color(0xff0000);\nconst color = new THREE.Color(\"red\");\nconst color = new THREE.Color(\"rgb(255, 0, 0)\");\nconst color = new THREE.Color(\"#ff0000\");\n\ncolor.setHex(0x00ff00);\ncolor.setRGB(r, g, b); \u002F\u002F 0-1 range\ncolor.setHSL(h, s, l); \u002F\u002F 0-1 range\n\ncolor.lerp(otherColor, alpha);\ncolor.multiply(otherColor);\ncolor.multiplyScalar(2);\n```\n\n### MathUtils\n\n```javascript\nTHREE.MathUtils.clamp(value, min, max);\nTHREE.MathUtils.lerp(start, end, alpha);\nTHREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);\nTHREE.MathUtils.degToRad(degrees);\nTHREE.MathUtils.radToDeg(radians);\nTHREE.MathUtils.randFloat(min, max);\nTHREE.MathUtils.randInt(min, max);\nTHREE.MathUtils.smoothstep(x, min, max);\nTHREE.MathUtils.smootherstep(x, min, max);\n```\n\n## Common Patterns\n\n### Proper Cleanup\n\n```javascript\nfunction dispose() {\n  \u002F\u002F Dispose geometries\n  mesh.geometry.dispose();\n\n  \u002F\u002F Dispose materials\n  if (Array.isArray(mesh.material)) {\n    mesh.material.forEach((m) => m.dispose());\n  } else {\n    mesh.material.dispose();\n  }\n\n  \u002F\u002F Dispose textures\n  texture.dispose();\n\n  \u002F\u002F Remove from scene\n  scene.remove(mesh);\n\n  \u002F\u002F Dispose renderer\n  renderer.dispose();\n}\n```\n\n### Clock for Animation\n\n```javascript\nconst clock = new THREE.Clock();\n\nfunction animate() {\n  const delta = clock.getDelta(); \u002F\u002F Time since last frame (seconds)\n  const elapsed = clock.getElapsedTime(); \u002F\u002F Total time (seconds)\n\n  mesh.rotation.y += delta * 0.5; \u002F\u002F Consistent speed regardless of framerate\n\n  requestAnimationFrame(animate);\n  renderer.render(scene, camera);\n}\n```\n\n### Responsive Canvas\n\n```javascript\nfunction onWindowResize() {\n  const width = window.innerWidth;\n  const height = window.innerHeight;\n\n  camera.aspect = width \u002F height;\n  camera.updateProjectionMatrix();\n\n  renderer.setSize(width, height);\n  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\n}\nwindow.addEventListener(\"resize\", onWindowResize);\n```\n\n### Loading Manager\n\n```javascript\nconst manager = new THREE.LoadingManager();\n\nmanager.onStart = (url, loaded, total) => console.log(\"Started loading\");\nmanager.onLoad = () => console.log(\"All loaded\");\nmanager.onProgress = (url, loaded, total) => console.log(`${loaded}\u002F${total}`);\nmanager.onError = (url) => console.error(`Error loading ${url}`);\n\nconst textureLoader = new THREE.TextureLoader(manager);\nconst gltfLoader = new GLTFLoader(manager);\n```\n\n## Performance Tips\n\n1. **Limit draw calls**: Merge geometries, use instancing, atlas textures\n2. **Frustum culling**: Enabled by default, ensure bounding boxes are correct\n3. **LOD (Level of Detail)**: Use `THREE.LOD` for distance-based mesh switching\n4. **Object pooling**: Reuse objects instead of creating\u002Fdestroying\n5. **Avoid `getWorldPosition` in loops**: Cache results\n\n```javascript\n\u002F\u002F Merge static geometries\nimport { mergeGeometries } from \"three\u002Fexamples\u002Fjsm\u002Futils\u002FBufferGeometryUtils.js\";\nconst merged = mergeGeometries([geo1, geo2, geo3]);\n\n\u002F\u002F LOD\nconst lod = new THREE.LOD();\nlod.addLevel(highDetailMesh, 0);\nlod.addLevel(medDetailMesh, 50);\nlod.addLevel(lowDetailMesh, 100);\nscene.add(lod);\n```\n\n## See Also\n\n- `threejs-geometry` - Geometry creation and manipulation\n- `threejs-materials` - Material types and properties\n- `threejs-lighting` - Light types and shadows\n","# Three.js Fundamentals\n\n## Quick Start\n\n```javascript\nimport * as THREE from \"three\";\n\n\u002F\u002F Create scene, camera, renderer\nconst scene = new THREE.Scene();\nconst camera = new THREE.PerspectiveCamera(\n  75,\n  window.innerWidth \u002F window.innerHeight,\n  0.1,\n  1000,\n);\nconst renderer = new THREE.WebGLRenderer({ antialias: true });\n\nrenderer.setSize(window.innerWidth, window.innerHeight);\nrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\ndocument.body.appendChild(renderer.domElement);\n\n\u002F\u002F Add a mesh\nconst geometry = new THREE.BoxGeometry(1, 1, 1);\nconst material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });\nconst cube = new THREE.Mesh(geometry, material);\nscene.add(cube);\n\n\u002F\u002F Add light\nscene.add(new THREE.AmbientLight(0xffffff, 0.5));\nconst dirLight = new THREE.DirectionalLight(0xffffff, 1);\ndirLight.position.set(5, 5, 5);\nscene.add(dirLight);\n\ncamera.position.z = 5;\n\n\u002F\u002F Animation loop\nfunction animate() {\n  requestAnimationFrame(animate);\n  cube.rotation.x += 0.01;\n  cube.rotation.y += 0.01;\n  renderer.render(scene, camera);\n}\nanimate();\n\n\u002F\u002F Handle resize\nwindow.addEventListener(\"resize\", () => {\n  camera.aspect = window.innerWidth \u002F window.innerHeight;\n  camera.updateProjectionMatrix();\n  renderer.setSize(window.innerWidth, window.innerHeight);\n});\n```\n\n## Core Classes\n\n### Scene\n\nContainer for all 3D objects, lights, and cameras.\n\n```javascript\nconst scene = new THREE.Scene();\nscene.background = new THREE.Color(0x000000); \u002F\u002F Solid color\nscene.background = texture; \u002F\u002F Skybox texture\nscene.background = cubeTexture; \u002F\u002F Cubemap\nscene.environment = envMap; \u002F\u002F Environment map for PBR\nscene.fog = new THREE.Fog(0xffffff, 1, 100); \u002F\u002F Linear fog\nscene.fog = new THREE.FogExp2(0xffffff, 0.02); \u002F\u002F Exponential fog\n```\n\n### Cameras\n\n**PerspectiveCamera** - Most common, simulates human eye.\n\n```javascript\n\u002F\u002F PerspectiveCamera(fov, aspect, near, far)\nconst camera = new THREE.PerspectiveCamera(\n  75, \u002F\u002F Field of view (degrees)\n  window.innerWidth \u002F window.innerHeight, \u002F\u002F Aspect ratio\n  0.1, \u002F\u002F Near clipping plane\n  1000, \u002F\u002F Far clipping plane\n);\n\ncamera.position.set(0, 5, 10);\ncamera.lookAt(0, 0, 0);\ncamera.updateProjectionMatrix(); \u002F\u002F Call after changing fov, aspect, near, far\n```\n\n**OrthographicCamera** - No perspective distortion, good for 2D\u002Fisometric.\n\n```javascript\n\u002F\u002F OrthographicCamera(left, right, top, bottom, near, far)\nconst aspect = window.innerWidth \u002F window.innerHeight;\nconst frustumSize = 10;\nconst camera = new THREE.OrthographicCamera(\n  (frustumSize * aspect) \u002F -2,\n  (frustumSize * aspect) \u002F 2,\n  frustumSize \u002F 2,\n  frustumSize \u002F -2,\n  0.1,\n  1000,\n);\n```\n\n**ArrayCamera** - Multiple viewports with sub-cameras.\n\n```javascript\nconst cameras = [];\nfor (let i = 0; i \u003C 4; i++) {\n  const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);\n  subcamera.viewport = new THREE.Vector4(\n    Math.floor(i % 2) * 0.5,\n    Math.floor(i \u002F 2) * 0.5,\n    0.5,\n    0.5,\n  );\n  cameras.push(subcamera);\n}\nconst arrayCamera = new THREE.ArrayCamera(cameras);\n```\n\n**CubeCamera** - Renders environment maps for reflections.\n\n```javascript\nconst cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);\nconst cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);\nscene.add(cubeCamera);\n\n\u002F\u002F Use for reflections\nmaterial.envMap = cubeRenderTarget.texture;\n\n\u002F\u002F Update each frame (expensive!)\ncubeCamera.position.copy(reflectiveMesh.position);\ncubeCamera.update(renderer, scene);\n```\n\n### WebGLRenderer\n\n```javascript\nconst renderer = new THREE.WebGLRenderer({\n  canvas: document.querySelector(\"#canvas\"), \u002F\u002F Optional existing canvas\n  antialias: true, \u002F\u002F Smooth edges\n  alpha: true, \u002F\u002F Transparent background\n  powerPreference: \"high-performance\", \u002F\u002F GPU hint\n  preserveDrawingBuffer: true, \u002F\u002F For screenshots\n});\n\nrenderer.setSize(width, height);\nrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\n\n\u002F\u002F Tone mapping\nrenderer.toneMapping = THREE.ACESFilmicToneMapping;\nrenderer.toneMappingExposure = 1.0;\n\n\u002F\u002F Color space (Three.js r152+)\nrenderer.outputColorSpace = THREE.SRGBColorSpace;\n\n\u002F\u002F Shadows\nrenderer.shadowMap.enabled = true;\nrenderer.shadowMap.type = THREE.PCFSoftShadowMap;\n\n\u002F\u002F Clear color\nrenderer.setClearColor(0x000000, 1);\n\n\u002F\u002F Render\nrenderer.render(scene, camera);\n```\n\n### Object3D\n\nBase class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.\n\n```javascript\nconst obj = new THREE.Object3D();\n\n\u002F\u002F Transform\nobj.position.set(x, y, z);\nobj.rotation.set(x, y, z); \u002F\u002F Euler angles (radians)\nobj.quaternion.set(x, y, z, w); \u002F\u002F Quaternion rotation\nobj.scale.set(x, y, z);\n\n\u002F\u002F Local vs World transforms\nobj.getWorldPosition(targetVector);\nobj.getWorldQuaternion(targetQuaternion);\nobj.getWorldDirection(targetVector);\n\n\u002F\u002F Hierarchy\nobj.add(child);\nobj.remove(child);\nobj.parent;\nobj.children;\n\n\u002F\u002F Visibility\nobj.visible = false;\n\n\u002F\u002F Layers (for selective rendering\u002Fraycasting)\nobj.layers.set(1);\nobj.layers.enable(2);\nobj.layers.disable(0);\n\n\u002F\u002F Traverse hierarchy\nobj.traverse((child) => {\n  if (child.isMesh) child.material.color.set(0xff0000);\n});\n\n\u002F\u002F Matrix updates\nobj.matrixAutoUpdate = true; \u002F\u002F Default: auto-update matrices\nobj.updateMatrix(); \u002F\u002F Manual matrix update\nobj.updateMatrixWorld(true); \u002F\u002F Update world matrix recursively\n```\n\n### Group\n\nEmpty container for organizing objects.\n\n```javascript\nconst group = new THREE.Group();\ngroup.add(mesh1);\ngroup.add(mesh2);\nscene.add(group);\n\n\u002F\u002F Transform entire group\ngroup.position.x = 5;\ngroup.rotation.y = Math.PI \u002F 4;\n```\n\n### Mesh\n\nCombines geometry and material.\n\n```javascript\nconst mesh = new THREE.Mesh(geometry, material);\n\n\u002F\u002F Multiple materials (one per geometry group)\nconst mesh = new THREE.Mesh(geometry, [material1, material2]);\n\n\u002F\u002F Useful properties\nmesh.geometry;\nmesh.material;\nmesh.castShadow = true;\nmesh.receiveShadow = true;\n\n\u002F\u002F Frustum culling\nmesh.frustumCulled = true; \u002F\u002F Default: skip if outside camera view\n\n\u002F\u002F Render order\nmesh.renderOrder = 10; \u002F\u002F Higher = rendered later\n```\n\n## Coordinate System\n\nThree.js uses a **right-handed coordinate system**:\n\n- **+X** points right\n- **+Y** points up\n- **+Z** points toward viewer (out of screen)\n\n```javascript\n\u002F\u002F Axes helper\nconst axesHelper = new THREE.AxesHelper(5);\nscene.add(axesHelper); \u002F\u002F Red=X, Green=Y, Blue=Z\n```\n\n## Math Utilities\n\n### Vector3\n\n```javascript\nconst v = new THREE.Vector3(x, y, z);\nv.set(x, y, z);\nv.copy(otherVector);\nv.clone();\n\n\u002F\u002F Operations (modify in place)\nv.add(v2);\nv.sub(v2);\nv.multiply(v2);\nv.multiplyScalar(2);\nv.divideScalar(2);\nv.normalize();\nv.negate();\nv.clamp(min, max);\nv.lerp(target, alpha);\n\n\u002F\u002F Calculations (return new value)\nv.length();\nv.lengthSq(); \u002F\u002F Faster than length()\nv.distanceTo(v2);\nv.dot(v2);\nv.cross(v2); \u002F\u002F Modifies v\nv.angleTo(v2);\n\n\u002F\u002F Transform\nv.applyMatrix4(matrix);\nv.applyQuaternion(q);\nv.project(camera); \u002F\u002F World to NDC\nv.unproject(camera); \u002F\u002F NDC to world\n```\n\n### Matrix4\n\n```javascript\nconst m = new THREE.Matrix4();\nm.identity();\nm.copy(other);\nm.clone();\n\n\u002F\u002F Build transforms\nm.makeTranslation(x, y, z);\nm.makeRotationX(theta);\nm.makeRotationY(theta);\nm.makeRotationZ(theta);\nm.makeRotationFromQuaternion(q);\nm.makeScale(x, y, z);\n\n\u002F\u002F Compose\u002Fdecompose\nm.compose(position, quaternion, scale);\nm.decompose(position, quaternion, scale);\n\n\u002F\u002F Operations\nm.multiply(m2); \u002F\u002F m = m * m2\nm.premultiply(m2); \u002F\u002F m = m2 * m\nm.invert();\nm.transpose();\n\n\u002F\u002F Camera matrices\nm.makePerspective(left, right, top, bottom, near, far);\nm.makeOrthographic(left, right, top, bottom, near, far);\nm.lookAt(eye, target, up);\n```\n\n### Quaternion\n\n```javascript\nconst q = new THREE.Quaternion();\nq.setFromEuler(euler);\nq.setFromAxisAngle(axis, angle);\nq.setFromRotationMatrix(matrix);\n\nq.multiply(q2);\nq.slerp(target, t); \u002F\u002F Spherical interpolation\nq.normalize();\nq.invert();\n```\n\n### Euler\n\n```javascript\nconst euler = new THREE.Euler(x, y, z, \"XYZ\"); \u002F\u002F Order matters!\neuler.setFromQuaternion(q);\neuler.setFromRotationMatrix(m);\n\n\u002F\u002F Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'\n```\n\n### Color\n\n```javascript\nconst color = new THREE.Color(0xff0000);\nconst color = new THREE.Color(\"red\");\nconst color = new THREE.Color(\"rgb(255, 0, 0)\");\nconst color = new THREE.Color(\"#ff0000\");\n\ncolor.setHex(0x00ff00);\ncolor.setRGB(r, g, b); \u002F\u002F 0-1 range\ncolor.setHSL(h, s, l); \u002F\u002F 0-1 range\n\ncolor.lerp(otherColor, alpha);\ncolor.multiply(otherColor);\ncolor.multiplyScalar(2);\n```\n\n### MathUtils\n\n```javascript\nTHREE.MathUtils.clamp(value, min, max);\nTHREE.MathUtils.lerp(start, end, alpha);\nTHREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);\nTHREE.MathUtils.degToRad(degrees);\nTHREE.MathUtils.radToDeg(radians);\nTHREE.MathUtils.randFloat(min, max);\nTHREE.MathUtils.randInt(min, max);\nTHREE.MathUtils.smoothstep(x, min, max);\nTHREE.MathUtils.smootherstep(x, min, max);\n```\n\n## Common Patterns\n\n### Proper Cleanup\n\n```javascript\nfunction dispose() {\n  \u002F\u002F Dispose geometries\n  mesh.geometry.dispose();\n\n  \u002F\u002F Dispose materials\n  if (Array.isArray(mesh.material)) {\n    mesh.material.forEach((m) => m.dispose());\n  } else {\n    mesh.material.dispose();\n  }\n\n  \u002F\u002F Dispose textures\n  texture.dispose();\n\n  \u002F\u002F Remove from scene\n  scene.remove(mesh);\n\n  \u002F\u002F Dispose renderer\n  renderer.dispose();\n}\n```\n\n### Clock for Animation\n\n```javascript\nconst clock = new THREE.Clock();\n\nfunction animate() {\n  const delta = clock.getDelta(); \u002F\u002F Time since last frame (seconds)\n  const elapsed = clock.getElapsedTime(); \u002F\u002F Total time (seconds)\n\n  mesh.rotation.y += delta * 0.5; \u002F\u002F Consistent speed regardless of framerate\n\n  requestAnimationFrame(animate);\n  renderer.render(scene, camera);\n}\n```\n\n### Responsive Canvas\n\n```javascript\nfunction onWindowResize() {\n  const width = window.innerWidth;\n  const height = window.innerHeight;\n\n  camera.aspect = width \u002F height;\n  camera.updateProjectionMatrix();\n\n  renderer.setSize(width, height);\n  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\n}\nwindow.addEventListener(\"resize\", onWindowResize);\n```\n\n### Loading Manager\n\n```javascript\nconst manager = new THREE.LoadingManager();\n\nmanager.onStart = (url, loaded, total) => console.log(\"Started loading\");\nmanager.onLoad = () => console.log(\"All loaded\");\nmanager.onProgress = (url, loaded, total) => console.log(`${loaded}\u002F${total}`);\nmanager.onError = (url) => console.error(`Error loading ${url}`);\n\nconst textureLoader = new THREE.TextureLoader(manager);\nconst gltfLoader = new GLTFLoader(manager);\n```\n\n## Performance Tips\n\n1. **Limit draw calls**: Merge geometries, use instancing, atlas textures\n2. **Frustum culling**: Enabled by default, ensure bounding boxes are correct\n3. **LOD (Level of Detail)**: Use `THREE.LOD` for distance-based mesh switching\n4. **Object pooling**: Reuse objects instead of creating\u002Fdestroying\n5. **Avoid `getWorldPosition` in loops**: Cache results\n\n```javascript\n\u002F\u002F Merge static geometries\nimport { mergeGeometries } from \"three\u002Fexamples\u002Fjsm\u002Futils\u002FBufferGeometryUtils.js\";\nconst merged = mergeGeometries([geo1, geo2, geo3]);\n\n\u002F\u002F LOD\nconst lod = new THREE.LOD();\nlod.addLevel(highDetailMesh, 0);\nlod.addLevel(medDetailMesh, 50);\nlod.addLevel(lowDetailMesh, 100);\nscene.add(lod);\n```\n\n## See Also\n\n- `threejs-geometry` - Geometry creation and manipulation\n- `threejs-materials` - Material types and properties\n- `threejs-lighting` - Light types and shadows\n",{"name":5,"description":7},"main","b30820b3248f6676d5389f0ccabd4e5250c9c536","skills\u002Fthreejs-fundamentals","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack","https:\u002F\u002Fgithub.com\u002Fkalash33","kalashpoddar.me","Tech-savvy Full Stack Developer 🚀 | Cybersecurity enthusiast 🔒 | Passionate about innovation and securing the digital world 🌐 | Let's code securely! 💻🔐","2026-05-20 04:11:22",{"source":8,"skillName":5,"commands":33,"prompt":43,"zipAvailable":44},[34,37,40],{"tool":35,"command":36},"npx","npx skills add kalash33\u002Fkstack --skill threejs-fundamentals",{"tool":38,"command":39},"bunx","bunx skills add kalash33\u002Fkstack --skill threejs-fundamentals",{"tool":41,"command":42},"pnpm","pnpm dlx skills add kalash33\u002Fkstack --skill threejs-fundamentals","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fthreejs-fundamentals\u002FSKILL.md",true,[],[47,54,61,68,75,82],{"skillNo":48,"name":49,"nameZh":6,"description":50,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":51,"categories":52,"keywords":53,"publishedAt":19},"01M73CFERCR43JCAP606E41EFB","zustand-store-ts","Create Zustand stores with TypeScript, subscribeWithSelector middleware, and proper state\u002Faction separation. Use when building React state management, creating global stores, or implementing reacti...","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fzustand-store-ts\u002FSKILL.md",[],[],{"skillNo":55,"name":56,"nameZh":6,"description":57,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":58,"categories":59,"keywords":60,"publishedAt":19},"01M73CFCMFVTAQEMTZ5HR10X8V","zoom-automation","Automate Zoom meeting creation, management, recordings, webinars, and participant tracking via Rube MCP (Composio). Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fzoom-automation\u002FSKILL.md",[],[],{"skillNo":62,"name":63,"nameZh":6,"description":64,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":65,"categories":66,"keywords":67,"publishedAt":19},"01M73CFAA7EBWXJVXDQ1X555MB","zoho-crm-automation","Automate Zoho CRM tasks via Rube MCP (Composio): create\u002Fupdate records, search contacts, manage leads, and convert leads. Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fzoho-crm-automation\u002FSKILL.md",[],[],{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":19},"01M73CF80XCM9K81567MJ8QZFW","zod-validation-expert","Expert in Zod — TypeScript-first schema validation. Covers parsing, custom errors, refinements, type inference, and integration with React Hook Form, Next.js, and tRPC.","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fzod-validation-expert\u002FSKILL.md",[],[],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":19},"01M73CF4YPMF3RA8ZJDXZSMD93","zeroize-audit","Detects missing zeroization of sensitive data in source code and identifies zeroization removed by compiler optimizations, with assembly-level analysis, and control-flow verification. Use for auditing C\u002FC++\u002FRust code handling secrets, keys, passwords, or other sensitive data.","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fzeroize-audit\u002FSKILL.md",[],[],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":19},"01M73CF2S25EN3XNAMKY47XHPS","zendesk-automation","Automate Zendesk tasks via Rube MCP (Composio): tickets, users, organizations, replies. Always search tools first for current schemas.","https:\u002F\u002Fgithub.com\u002Fkalash33\u002Fkstack\u002Fblob\u002Fmain\u002Fskills\u002Fzendesk-automation\u002FSKILL.md",[],[]]