[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-5518c160-2c3c-45c6-915d-192e353cb7d9":3,"$f-8JeTZqwVcIQzzPxKZS8BJ7ak00B-vgHRPFUtCEvY8k":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},"5518c160-2c3c-45c6-915d-192e353cb7d9","threejs-shaders","Three.js着色器 - GLSL、ShaderMaterial、uniforms、自定义效果。用于创建自定义视觉效果、修改顶点、编写片段着色器或扩展内置材质。","cat_coding_frontend","mod_coding","sickn33,coding","---\nname: threejs-shaders\ndescription: Three.js shaders - GLSL, ShaderMaterial, uniforms, custom effects. Use when creating custom visual effects, modifying vertices, writing fragment shaders, or extending built-in materials.\nrisk: unknown\nsource: community\n---\n\n# Three.js Shaders\n\n## When to Use\n- You need custom shader logic in Three.js.\n- The task involves `ShaderMaterial`, uniforms, GLSL, vertex deformation, or fragment-based effects.\n- You are extending material behavior beyond what built-in materials provide.\n\n## Quick Start\n\n```javascript\nimport * as THREE from \"three\";\n\nconst material = new THREE.ShaderMaterial({\n  uniforms: {\n    time: { value: 0 },\n    color: { value: new THREE.Color(0xff0000) },\n  },\n  vertexShader: `\n    void main() {\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    }\n  `,\n  fragmentShader: `\n    uniform vec3 color;\n\n    void main() {\n      gl_FragColor = vec4(color, 1.0);\n    }\n  `,\n});\n\n\u002F\u002F Update in animation loop\nmaterial.uniforms.time.value = clock.getElapsedTime();\n```\n\n## ShaderMaterial vs RawShaderMaterial\n\n### ShaderMaterial\n\nThree.js provides built-in uniforms and attributes.\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  vertexShader: `\n    \u002F\u002F Built-in uniforms available:\n    \u002F\u002F uniform mat4 modelMatrix;\n    \u002F\u002F uniform mat4 modelViewMatrix;\n    \u002F\u002F uniform mat4 projectionMatrix;\n    \u002F\u002F uniform mat4 viewMatrix;\n    \u002F\u002F uniform mat3 normalMatrix;\n    \u002F\u002F uniform vec3 cameraPosition;\n\n    \u002F\u002F Built-in attributes available:\n    \u002F\u002F attribute vec3 position;\n    \u002F\u002F attribute vec3 normal;\n    \u002F\u002F attribute vec2 uv;\n\n    void main() {\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    }\n  `,\n  fragmentShader: `\n    void main() {\n      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n    }\n  `,\n});\n```\n\n### RawShaderMaterial\n\nFull control - you define everything.\n\n```javascript\nconst material = new THREE.RawShaderMaterial({\n  uniforms: {\n    projectionMatrix: { value: camera.projectionMatrix },\n    modelViewMatrix: { value: new THREE.Matrix4() },\n  },\n  vertexShader: `\n    precision highp float;\n\n    attribute vec3 position;\n    uniform mat4 projectionMatrix;\n    uniform mat4 modelViewMatrix;\n\n    void main() {\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    }\n  `,\n  fragmentShader: `\n    precision highp float;\n\n    void main() {\n      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n    }\n  `,\n});\n```\n\n## Uniforms\n\n### Uniform Types\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  uniforms: {\n    \u002F\u002F Numbers\n    floatValue: { value: 1.5 },\n    intValue: { value: 1 },\n\n    \u002F\u002F Vectors\n    vec2Value: { value: new THREE.Vector2(1, 2) },\n    vec3Value: { value: new THREE.Vector3(1, 2, 3) },\n    vec4Value: { value: new THREE.Vector4(1, 2, 3, 4) },\n\n    \u002F\u002F Colors (converted to vec3)\n    colorValue: { value: new THREE.Color(0xff0000) },\n\n    \u002F\u002F Matrices\n    mat3Value: { value: new THREE.Matrix3() },\n    mat4Value: { value: new THREE.Matrix4() },\n\n    \u002F\u002F Textures\n    textureValue: { value: texture },\n    cubeTextureValue: { value: cubeTexture },\n\n    \u002F\u002F Arrays\n    floatArray: { value: [1.0, 2.0, 3.0] },\n    vec3Array: {\n      value: [new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0)],\n    },\n  },\n});\n```\n\n### GLSL Declarations\n\n```glsl\n\u002F\u002F In shader\nuniform float floatValue;\nuniform int intValue;\nuniform vec2 vec2Value;\nuniform vec3 vec3Value;\nuniform vec3 colorValue;    \u002F\u002F Color becomes vec3\nuniform vec4 vec4Value;\nuniform mat3 mat3Value;\nuniform mat4 mat4Value;\nuniform sampler2D textureValue;\nuniform samplerCube cubeTextureValue;\nuniform float floatArray[3];\nuniform vec3 vec3Array[2];\n```\n\n### Updating Uniforms\n\n```javascript\n\u002F\u002F Direct assignment\nmaterial.uniforms.time.value = clock.getElapsedTime();\n\n\u002F\u002F Vector\u002FColor updates\nmaterial.uniforms.position.value.set(x, y, z);\nmaterial.uniforms.color.value.setHSL(hue, 1, 0.5);\n\n\u002F\u002F Matrix updates\nmaterial.uniforms.matrix.value.copy(mesh.matrixWorld);\n```\n\n## Varyings\n\nPass data from vertex to fragment shader.\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  vertexShader: `\n    varying vec2 vUv;\n    varying vec3 vNormal;\n    varying vec3 vPosition;\n\n    void main() {\n      vUv = uv;\n      vNormal = normalize(normalMatrix * normal);\n      vPosition = (modelViewMatrix * vec4(position, 1.0)).xyz;\n\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    }\n  `,\n  fragmentShader: `\n    varying vec2 vUv;\n    varying vec3 vNormal;\n    varying vec3 vPosition;\n\n    void main() {\n      \u002F\u002F Use interpolated values\n      gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);\n    }\n  `,\n});\n```\n\n## Common Shader Patterns\n\n### Texture Sampling\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  uniforms: {\n    map: { value: texture },\n  },\n  vertexShader: `\n    varying vec2 vUv;\n\n    void main() {\n      vUv = uv;\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    }\n  `,\n  fragmentShader: `\n    uniform sampler2D map;\n    varying vec2 vUv;\n\n    void main() {\n      vec4 texColor = texture2D(map, vUv);\n      gl_FragColor = texColor;\n    }\n  `,\n});\n```\n\n### Vertex Displacement\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  uniforms: {\n    time: { value: 0 },\n    amplitude: { value: 0.5 },\n  },\n  vertexShader: `\n    uniform float time;\n    uniform float amplitude;\n\n    void main() {\n      vec3 pos = position;\n\n      \u002F\u002F Wave displacement\n      pos.z += sin(pos.x * 5.0 + time) * amplitude;\n      pos.z += sin(pos.y * 5.0 + time) * amplitude;\n\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);\n    }\n  `,\n  fragmentShader: `\n    void main() {\n      gl_FragColor = vec4(0.5, 0.8, 1.0, 1.0);\n    }\n  `,\n});\n```\n\n### Fresnel Effect\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  vertexShader: `\n    varying vec3 vNormal;\n    varying vec3 vWorldPosition;\n\n    void main() {\n      vNormal = normalize(normalMatrix * normal);\n      vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n    }\n  `,\n  fragmentShader: `\n    varying vec3 vNormal;\n    varying vec3 vWorldPosition;\n\n    void main() {\n      \u002F\u002F cameraPosition is auto-provided by ShaderMaterial\n      vec3 viewDirection = normalize(cameraPosition - vWorldPosition);\n      float fresnel = pow(1.0 - dot(viewDirection, vNormal), 3.0);\n\n      vec3 baseColor = vec3(0.0, 0.0, 0.5);\n      vec3 fresnelColor = vec3(0.5, 0.8, 1.0);\n\n      gl_FragColor = vec4(mix(baseColor, fresnelColor, fresnel), 1.0);\n    }\n  `,\n});\n```\n\n### Noise-Based Effects\n\n```glsl\n\u002F\u002F Simple noise function\nfloat random(vec2 st) {\n  return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\n\u002F\u002F Value noise\nfloat noise(vec2 st) {\n  vec2 i = floor(st);\n  vec2 f = fract(st);\n\n  float a = random(i);\n  float b = random(i + vec2(1.0, 0.0));\n  float c = random(i + vec2(0.0, 1.0));\n  float d = random(i + vec2(1.0, 1.0));\n\n  vec2 u = f * f * (3.0 - 2.0 * f);\n\n  return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;\n}\n\n\u002F\u002F Usage\nfloat n = noise(vUv * 10.0 + time);\n```\n\n### Gradient\n\n```glsl\n\u002F\u002F Linear gradient\nvec3 color = mix(colorA, colorB, vUv.y);\n\n\u002F\u002F Radial gradient\nfloat dist = distance(vUv, vec2(0.5));\nvec3 color = mix(centerColor, edgeColor, dist * 2.0);\n\n\u002F\u002F Smooth gradient with custom curve\nfloat t = smoothstep(0.0, 1.0, vUv.y);\nvec3 color = mix(colorA, colorB, t);\n```\n\n### Rim Lighting\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  vertexShader: `\n    varying vec3 vNormal;\n    varying vec3 vViewPosition;\n\n    void main() {\n      vNormal = normalize(normalMatrix * normal);\n      vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\n      vViewPosition = mvPosition.xyz;\n      gl_Position = projectionMatrix * mvPosition;\n    }\n  `,\n  fragmentShader: `\n    varying vec3 vNormal;\n    varying vec3 vViewPosition;\n\n    void main() {\n      vec3 viewDir = normalize(-vViewPosition);\n      float rim = 1.0 - max(0.0, dot(viewDir, vNormal));\n      rim = pow(rim, 4.0);\n\n      vec3 baseColor = vec3(0.2, 0.2, 0.8);\n      vec3 rimColor = vec3(1.0, 0.5, 0.0);\n\n      gl_FragColor = vec4(baseColor + rimColor * rim, 1.0);\n    }\n  `,\n});\n```\n\n### Dissolve Effect\n\n```glsl\nuniform float progress;\nuniform sampler2D noiseMap;\n\nvoid main() {\n  float noise = texture2D(noiseMap, vUv).r;\n\n  if (noise \u003C progress) {\n    discard;\n  }\n\n  \u002F\u002F Edge glow\n  float edge = smoothstep(progress, progress + 0.1, noise);\n  vec3 edgeColor = vec3(1.0, 0.5, 0.0);\n  vec3 baseColor = vec3(0.5);\n\n  gl_FragColor = vec4(mix(edgeColor, baseColor, edge), 1.0);\n}\n```\n\n## Extending Built-in Materials\n\n### onBeforeCompile\n\nModify existing material shaders.\n\n```javascript\nconst material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });\n\nmaterial.onBeforeCompile = (shader) => {\n  \u002F\u002F Add custom uniform\n  shader.uniforms.time = { value: 0 };\n\n  \u002F\u002F Store reference for updates\n  material.userData.shader = shader;\n\n  \u002F\u002F Modify vertex shader\n  shader.vertexShader = shader.vertexShader.replace(\n    \"#include \u003Cbegin_vertex>\",\n    `\n    #include \u003Cbegin_vertex>\n    transformed.y += sin(position.x * 10.0 + time) * 0.1;\n    `,\n  );\n\n  \u002F\u002F Add uniform declaration\n  shader.vertexShader = \"uniform float time;\\n\" + shader.vertexShader;\n};\n\n\u002F\u002F Update in animation loop\nif (material.userData.shader) {\n  material.userData.shader.uniforms.time.value = clock.getElapsedTime();\n}\n```\n\n### Common Injection Points\n\n```javascript\n\u002F\u002F Vertex shader chunks\n\"#include \u003Cbegin_vertex>\"; \u002F\u002F After position is calculated\n\"#include \u003Cproject_vertex>\"; \u002F\u002F After gl_Position\n\"#include \u003Cbeginnormal_vertex>\"; \u002F\u002F Normal calculation start\n\n\u002F\u002F Fragment shader chunks\n\"#include \u003Ccolor_fragment>\"; \u002F\u002F After diffuse color\n\"#include \u003Coutput_fragment>\"; \u002F\u002F Final output\n\"#include \u003Cfog_fragment>\"; \u002F\u002F After fog applied\n```\n\n## GLSL Built-in Functions\n\n### Math Functions\n\n```glsl\n\u002F\u002F Basic\nabs(x), sign(x), floor(x), ceil(x), fract(x)\nmod(x, y), min(x, y), max(x, y), clamp(x, min, max)\nmix(a, b, t), step(edge, x), smoothstep(edge0, edge1, x)\n\n\u002F\u002F Trigonometry\nsin(x), cos(x), tan(x)\nasin(x), acos(x), atan(y, x), atan(x)\nradians(degrees), degrees(radians)\n\n\u002F\u002F Exponential\npow(x, y), exp(x), log(x), exp2(x), log2(x)\nsqrt(x), inversesqrt(x)\n```\n\n### Vector Functions\n\n```glsl\n\u002F\u002F Length and distance\nlength(v), distance(p0, p1), dot(x, y), cross(x, y)\n\n\u002F\u002F Normalization\nnormalize(v)\n\n\u002F\u002F Reflection and refraction\nreflect(I, N), refract(I, N, eta)\n\n\u002F\u002F Component-wise\nlessThan(x, y), lessThanEqual(x, y)\ngreaterThan(x, y), greaterThanEqual(x, y)\nequal(x, y), notEqual(x, y)\nany(bvec), all(bvec)\n```\n\n### Texture Functions\n\n```glsl\n\u002F\u002F GLSL 1.0 (default) - use texture2D\u002FtextureCube\ntexture2D(sampler, coord)\ntexture2D(sampler, coord, bias)\ntextureCube(sampler, coord)\n\n\u002F\u002F GLSL 3.0 (glslVersion: THREE.GLSL3) - use texture()\n\u002F\u002F texture(sampler, coord) replaces texture2D\u002FtextureCube\n\u002F\u002F Also use: out vec4 fragColor instead of gl_FragColor\n\n\u002F\u002F Texture size (GLSL 1.30+)\ntextureSize(sampler, lod)\n```\n\n## Common Material Properties\n\n```javascript\nconst material = new THREE.ShaderMaterial({\n  uniforms: {\n    \u002F* ... *\u002F\n  },\n  vertexShader: \"\u002F* ... *\u002F\",\n  fragmentShader: \"\u002F* ... *\u002F\",\n\n  \u002F\u002F Rendering\n  transparent: true,\n  opacity: 1.0,\n  side: THREE.DoubleSide,\n  depthTest: true,\n  depthWrite: true,\n\n  \u002F\u002F Blending\n  blending: THREE.NormalBlending,\n  \u002F\u002F AdditiveBlending, SubtractiveBlending, MultiplyBlending\n\n  \u002F\u002F Wireframe\n  wireframe: false,\n  wireframeLinewidth: 1, \u002F\u002F Note: >1 has no effect on most platforms (WebGL limitation)\n\n  \u002F\u002F Extensions\n  extensions: {\n    derivatives: true, \u002F\u002F For fwidth, dFdx, dFdy\n    fragDepth: true, \u002F\u002F gl_FragDepth\n    drawBuffers: true, \u002F\u002F Multiple render targets\n    shaderTextureLOD: true, \u002F\u002F texture2DLod\n  },\n\n  \u002F\u002F GLSL version\n  glslVersion: THREE.GLSL3, \u002F\u002F For WebGL2 features\n});\n```\n\n## Shader Includes\n\n### Using Three.js Shader Chunks\n\n```javascript\nimport { ShaderChunk } from \"three\";\n\nconst fragmentShader = `\n  ${ShaderChunk.common}\n  ${ShaderChunk.packing}\n\n  uniform sampler2D depthTexture;\n  varying vec2 vUv;\n\n  void main() {\n    float depth = texture2D(depthTexture, vUv).r;\n    float linearDepth = perspectiveDepthToViewZ(depth, 0.1, 1000.0);\n    gl_FragColor = vec4(vec3(-linearDepth \u002F 100.0), 1.0);\n  }\n`;\n```\n\n### External Shader Files\n\n```javascript\n\u002F\u002F With vite\u002Fwebpack\nimport vertexShader from \".\u002Fshaders\u002Fvertex.glsl\";\nimport fragmentShader from \".\u002Fshaders\u002Ffragment.glsl\";\n\nconst material = new THREE.ShaderMaterial({\n  vertexShader,\n  fragmentShader,\n});\n```\n\n## Instanced Shaders\n\n```javascript\n\u002F\u002F Instanced attribute\nconst offsets = new Float32Array(instanceCount * 3);\n\u002F\u002F Fill offsets...\ngeometry.setAttribute(\"offset\", new THREE.InstancedBufferAttribute(offsets, 3));\n\nconst material = new THREE.ShaderMaterial({\n  vertexShader: `\n    attribute vec3 offset;\n\n    void main() {\n      vec3 pos = position + offset;\n      gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);\n    }\n  `,\n  fragmentShader: `\n    void main() {\n      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n    }\n  `,\n});\n```\n\n## Debugging Shaders\n\n```javascript\n\u002F\u002F Check for compile errors\nmaterial.onBeforeCompile = (shader) => {\n  console.log(\"Vertex Shader:\", shader.vertexShader);\n  console.log(\"Fragment Shader:\", shader.fragmentShader);\n};\n\n\u002F\u002F Visual debugging\nfragmentShader: `\n  void main() {\n    \u002F\u002F Debug UV\n    gl_FragColor = vec4(vUv, 0.0, 1.0);\n\n    \u002F\u002F Debug normals\n    gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1.0);\n\n    \u002F\u002F Debug position\n    gl_FragColor = vec4(vPosition * 0.1 + 0.5, 1.0);\n  }\n`;\n\n\u002F\u002F Check WebGL errors\nrenderer.debug.checkShaderErrors = true;\n```\n\n## Performance Tips\n\n1. **Minimize uniforms**: Group related values into vectors\n2. **Avoid conditionals**: Use mix\u002Fstep instead of if\u002Felse\n3. **Precalculate**: Move calculations to JS when possible\n4. **Use textures**: For complex functions, use lookup tables\n5. **Limit overdraw**: Avoid transparent objects when possible\n\n```glsl\n\u002F\u002F Instead of:\nif (value > 0.5) {\n  color = colorA;\n} else {\n  color = colorB;\n}\n\n\u002F\u002F Use:\ncolor = mix(colorB, colorA, step(0.5, value));\n```\n\n## TSL (Three.js Shading Language) - Future Direction\n\nTSL is the new shader authoring system for Three.js, designed to work with both WebGL and WebGPU renderers. GLSL patterns above are **WebGL-only** and will not work with the WebGPU renderer.\n\n### TSL Quick Start\n\n```javascript\nimport { MeshStandardNodeMaterial } from \"three\u002Faddons\u002Fnodes\u002FNodes.js\";\nimport {\n  uv, sin, timerLocal, vec4, color, positionLocal, normalLocal,\n  float, mul, add\n} from \"three\u002Faddons\u002Fnodes\u002FNodes.js\";\n\nconst material = new MeshStandardNodeMaterial();\n\n\u002F\u002F Animated color based on UV and time\nconst time = timerLocal();\nmaterial.colorNode = color(sin(add(uv().x, time)), uv().y, 0.5);\n\n\u002F\u002F Vertex displacement\nmaterial.positionNode = add(\n  positionLocal,\n  mul(normalLocal, sin(add(positionLocal.x, time)).mul(0.1))\n);\n```\n\n### Key Differences from GLSL\n\n| GLSL (WebGL only)       | TSL (WebGL + WebGPU)         |\n| ----------------------- | ---------------------------- |\n| `ShaderMaterial`        | `MeshStandardNodeMaterial`   |\n| String-based shaders    | JavaScript node graph        |\n| `onBeforeCompile`       | Node composition             |\n| Manual uniforms         | `uniform()` node             |\n| `texture2D()`           | `texture()` node             |\n| `gl_Position`           | `positionNode`               |\n| `gl_FragColor`          | `colorNode` \u002F `outputNode`   |\n\n### When to Use What\n\n- **GLSL ShaderMaterial**: Existing WebGL projects, maximum shader control, porting existing shaders\n- **TSL NodeMaterial**: New projects, WebGPU support needed, cross-renderer compatibility\n\n## See Also\n\n- `threejs-materials` - Built-in material types\n- `threejs-postprocessing` - Full-screen shader effects\n- `threejs-textures` - Texture sampling in shaders\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,128,1849,"2026-05-16 13:44:20",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"前端开发","frontend","mdi-language-html5","HTML\u002FCSS\u002FJavaScript\u002F框架相关",1,96,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"6a166779-e2ff-4993-bf55-7c7ed9f89d53","1.0.0","threejs-shaders.zip",4923,"uploads\u002Fskills\u002F5518c160-2c3c-45c6-915d-192e353cb7d9\u002Fthreejs-shaders.zip","1c88221b8d1fbe6375f5c1c039c94c7ee0e35bc39d5153900da3ab62f8f72f14","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":16227}]",{"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]