[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M717BJN47M2TMJR8TD9VSMS2":3,"skill-same:01M717BJN47M2TMJR8TD9VSMS2":62},{"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":37,"linkOnly":38,"markdownContent":39,"markdownBody":40,"frontMatter":41,"refName":42,"commitSha":43,"skillDirectory":44,"forksCount":14,"repositoryHtmlUrl":45,"repositoryHomepageUrl":6,"ownerHtmlUrl":46,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":47,"install":48,"resources":61},"01M717BJN47M2TMJR8TD9VSMS2","threejs-shaders",null,"Three.js shaders - GLSL, ShaderMaterial, uniforms, custom effects. Use when creating custom visual effects, modifying vertices, writing fragment shaders, or extending built-in materials.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcursor\u002Fthreejs-shaders\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"shaders","threejs shaders","threejs","js","use","community","three","visual effects","visual","writing","GLSL","fragment","unknown","materials","custom","effects","when","extending","2026-11-10 10:12:30",false,"---\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## 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## 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","# Three.js Shaders\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## 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",{"name":5,"risk":31,"source":24,"description":7},"main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fcursor\u002Fthreejs-shaders","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":49,"prompt":59,"zipAvailable":60},[50,53,56],{"tool":51,"command":52},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill threejs-shaders",{"tool":54,"command":55},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill threejs-shaders",{"tool":57,"command":58},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill threejs-shaders","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcursor\u002Fthreejs-shaders\u002FSKILL.md",true,[],[63,87,112,122,135,154],{"skillNo":64,"name":65,"nameZh":6,"description":66,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":74,"publishedAt":37},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[69],{"categoryNo":70,"categoryName":71,"taxonomyType":72,"taxonomyTypeDesc":73},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[75,76,77,78,79,80,81,82,83,84,85,86],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":37},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[94,95,96,97,98,99,77,100,101,102,103,35,104,105,106,107,108,109,110,111],"trend","trend tap","tap","api keys","Bash","time","trending","hacker","aggregator","do","brew","live","data","google","install","read","across","api",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":37},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[119,120,94,104,105,106,107,98,77,109,121,110,111,35,102,101,100,108,99,97],"trend radar","radar","pulse",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":37},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[129,130,131,132,133,134],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":146,"publishedAt":37},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[141],{"categoryNo":142,"categoryName":143,"taxonomyType":144,"taxonomyTypeDesc":145},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[137,83,147,148,149,86,104,150,151,152,96,153,108],"Audio","cli","youtube","images","https","files","pdfs",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":160,"publishedAt":37},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[156,161,162,163,108,164,151,165,166,167,168,169],"status","play","go","latest","github","discover","control","cmd","volume"]