[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-a90120c6-8880-4526-a9b6-4467a3462ee8":3,"$fyfCWwp6arIG-McVV8zixy1ohvXDf_mp3bLaYEzO9rQo":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"a90120c6-8880-4526-a9b6-4467a3462ee8","threejs-fundamentals","Three.js场景设置、相机、渲染器、Object3D层次结构、坐标系。用于设置3D场景、创建相机、配置渲染器、管理对象层次结构或处理变换。","cat_design_graphic","mod_design","sickn33,design","---\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.\nrisk: unknown\nsource: community\n---\n\n# Three.js Fundamentals\n\n## When to Use\n- You need to set up the core structure of a Three.js scene.\n- The task involves scenes, cameras, renderers, transforms, resize handling, or object hierarchy basics.\n- You want foundational Three.js guidance before working on specialized topics like shaders or post-processing.\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### Timer and Clock for Animation\n\n**Timer (recommended in r183)** - pauses when tab is hidden, cleaner API:\n\n```javascript\nconst timer = new THREE.Timer();\n\nrenderer.setAnimationLoop(() => {\n  timer.update();\n  const delta = timer.getDelta();\n  const elapsed = timer.getElapsed();\n\n  mesh.rotation.y += delta * 0.5;\n  renderer.render(scene, camera);\n});\n```\n\n**Clock (legacy, still works):**\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### Animation Loop\n\nPrefer `renderer.setAnimationLoop()` over manual `requestAnimationFrame`. It handles WebXR compatibility and is the standard Three.js pattern:\n\n```javascript\nrenderer.setAnimationLoop(() => {\n  controls.update();\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## WebGPU Renderer (r183)\n\nThree.js includes an experimental WebGPU renderer as an alternative to WebGL:\n\n```javascript\nimport { WebGPURenderer } from \"three\u002Faddons\u002Frenderers\u002Fwebgpu\u002FWebGPURenderer.js\";\n\nconst renderer = new WebGPURenderer({ antialias: true });\nawait renderer.init();\nrenderer.setSize(window.innerWidth, window.innerHeight);\ndocument.body.appendChild(renderer.domElement);\n```\n\nWebGPU uses TSL (Three.js Shading Language) instead of GLSL. The WebGL renderer remains the default and is fully supported.\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\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,246,803,"2026-05-16 13:44:03",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"设计创意","design","mdi-palette-outline","UI 设计、生成艺术、品牌视觉等创意 Skill",3,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"视觉创意","graphic","mdi-brush","海报、Logo、插画等视觉创作",2,48,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"360a41a6-6f9d-4fec-a9d9-05331bc1a29d","1.0.0","threejs-fundamentals.zip",4912,"uploads\u002Fskills\u002Fa90120c6-8880-4526-a9b6-4467a3462ee8\u002Fthreejs-fundamentals.zip","aae2c997638a0a275810fd34a93e566f9631e18406fb5a270be4e1c4fd113d75","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":13329}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]