关于 r3f-materials
面向 React Three Fiber 开发者的材质参考技能,涵盖 3D 表面外观与着色器效果。内容从内置材质选择延伸到 GLSL 自定义和 uniform 管理。
主要功能
- 01内置材质对比
- 02常见材质属性
- 03GLSL ShaderMaterial 指南
- 04Uniform 类型与动画
- 05RawShaderMaterial 示例
- 06PBR 与着色器参考
适用场景
- 01为 3D 场景选择材质
- 02创建自定义着色器效果
- 03制作着色器 uniform 动画
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bbeierle12/ skill-mcp-claude --skill r3f-materials安装后在 Claude Code 中输入/r3f-materials确认已加载。
附带文件_meta.jsonreferences/shader-templates.md
详细介绍
R3F 材质
材质定义表面的外观,包括颜色、纹理、反射率、透明度和自定义着色器效果。
快速入门
// Built-in material
<mesh>
<boxGeometry />
<meshStandardMaterial color="hotpink" metalness={0.8} roughness={0.2} />
</mesh>
// Custom shader
<mesh>
<planeGeometry />
<shaderMaterial
uniforms={{ uTime: { value: 0 } }}
vertexShader={vertexShader}
fragmentShader={fragmentShader}
/>
</mesh>
内置材质
材质比较
| 材质 | 光照 | 使用场景 | 性能 |
|---|---|---|---|
MeshBasicMaterial | 无 | UI、无光照、调试 | 最快 |
MeshStandardMaterial | PBR | 通用 3D | 良好 |
MeshPhysicalMaterial | PBR+ | 玻璃、汽车漆 | 较慢 |
MeshLambertMaterial | 漫反射 | 哑光表面 | 快 |
MeshPhongMaterial | 高光 | 闪亮塑料 | 快 |
MeshToonMaterial | 卡通着色 | 风格化效果 | 良好 |
MeshNormalMaterial | 无 | 调试法线 | 最快 |
MeshDepthMaterial | 无 | 深度通道 | 最快 |
MeshBasicMaterial(无光照)
<meshBasicMaterial
color="#ff0000" // Base color
map={texture} // Color texture
transparent={true} // Enable transparency
opacity={0.5} // Transparency level
alphaMap={alphaTexture} // Transparency texture
side={THREE.DoubleSide} // Render both sides
wireframe={true} // Wireframe mode
fog={false} // Ignore scene fog
/>
MeshStandardMaterial(PBR)
<meshStandardMaterial
// Base
color="#ffffff"
map={colorTexture}
// PBR properties
metalness={0.5} // 0 = dielectric, 1 = metal
metalnessMap={metalMap}
roughness={0.5} // 0 = mirror, 1 = diffuse
roughnessMap={roughMap}
// Normal mapping
normalMap={normalTexture}
normalScale={[1, 1]}
// Ambient occlusion
aoMap={aoTexture}
aoMapIntensity={1}
// Displacement
displacementMap={dispMap}
displacementScale={0.1}
// Emission
emissive="#000000"
emissiveMap={emissiveTexture}
emissiveIntensity={1}
// Environment
envMap={cubeTexture}
envMapIntensity={1}
/>
MeshPhysicalMaterial(高级 PBR)
<meshPhysicalMaterial
// Inherits all MeshStandardMaterial props, plus:
// Clearcoat (car paint, lacquer)
clearcoat={1}
clearcoatRoughness={0.1}
clearcoatNormalMap={ccNormal}
// Transmission (glass, water)
transmission={0.9} // 0 = opaque, 1 = fully transmissive
thickness={0.5} // Volume thickness
ior={1.5} // Index of refraction
// Sheen (fabric, velvet)
sheen={1}
sheenRoughness={0.5}
sheenColor="#ff00ff"
// Iridescence (soap bubbles, oil slicks)
iridescence={1}
iridescenceIOR={1.3}
iridescenceThicknessRange={[100, 400]}
/>
MeshToonMaterial(卡通着色)
<meshToonMaterial
color="#6fa8dc"
gradientMap={gradientTexture} // 3-5 color ramp texture
/>
// Create gradient texture
const gradientTexture = useMemo(() => {
const canvas = document.createElement('canvas');
canvas.width = 4;
canvas.height = 1;
const ctx = canvas.getContext('2d')!;
// 4-step toon shading
ctx.fillStyle = '#444'; ctx.fillRect(0, 0, 1, 1);
ctx.fillStyle = '#888'; ctx.fillRect(1, 0, 1, 1);
ctx.fillStyle = '#bbb'; ctx.fillRect(2, 0, 1, 1);
ctx.fillStyle = '#fff'; ctx.fillRect(3, 0, 1, 1);
const texture = new THREE.CanvasTexture(canvas);
texture.minFilter = THREE.NearestFilter;
texture.magFilter = THREE.NearestFilter;
return texture;
}, []);
常用属性(所有材质)
<meshStandardMaterial
// Rendering
transparent={false}
opacity={1}
alphaTest={0} // Discard pixels below threshold
alphaToCoverage={false} // MSAA alpha
// Faces
side={THREE.FrontSide} // FrontSide | BackSide | DoubleSide
// Depth
depthTest={true}
depthWrite={true}
// Stencil
stencilWrite={false}
stencilFunc={THREE.AlwaysStencilFunc}
// Blending
blending={THREE.NormalBlending}
// Other
visible={true}
fog={true}
toneMapped={true}
/>
纹理
加载纹理
import { useTexture } from '@react-three/drei';
function TexturedMesh() {
const [colorMap, normalMap, roughnessMap] = useTexture([
'/textures/color.jpg',
'/textures/normal.jpg',
'/textures/roughness.jpg'
]);
return (
<mesh>
<boxGeometry />
<meshStandardMaterial
map={colorMap}
normalMap={normalMap}
roughnessMap={roughnessMap}
/>
</mesh>
);
}
纹理设置
import { useTexture } from '@react-three/drei';
import * as THREE from 'three';
const texture = useTexture('/texture.jpg', (tex) => {
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
tex.repeat.set(4, 4);
tex.anisotropy = 16; // Sharper at angles
});
ShaderMaterial
通过 GLSL 顶点着色器和片元着色器进行完全控制:
import { useRef } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
const vertexShader = `
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
uniform float uTime;
uniform vec3 uColor;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
float pulse = sin(uTime * 2.0) * 0.5 + 0.5;
vec3 color = mix(uColor, vec3(1.0), pulse * 0.3);
// Simple rim lighting
float rim = 1.0 - dot(vNormal, vec3(0.0, 0.0, 1.0));
color += rim * 0.5;
gl_FragColor = vec4(color, 1.0);
}
`;
function CustomShaderMesh() {
const materialRef = useRef<THREE.ShaderMaterial>(null!);
useFrame(({ clock }) => {
materialRef.current.uniforms.uTime.value = clock.elapsedTime;
});
return (
<mesh>
<sphereGeometry args={[1, 32, 32]} />
<shaderMaterial
ref={materialRef}
vertexShader={vertexShader}
fragmentShader={fragmentShader}
uniforms={{
uTime: { value: 0 },
uColor: { value: new THREE.Color('#ff6b6b') }
}}
/>
</mesh>
);
}
Uniform
Uniform 类型
uniforms={{
// Scalars
uFloat: { value: 1.0 },
uInt: { value: 1 },
uBool: { value: true },
// Vectors
uVec2: { value: new THREE.Vector2(1, 2) },
uVec3: { value: new THREE.Vector3(1, 2, 3) },
uVec4: { value: new THREE.Vector4(1, 2, 3, 4) },
uColor: { value: new THREE.Color('#ff0000') },
// Matrices
uMat3: { value: new THREE.Matrix3() },
uMat4: { value: new THREE.Matrix4() },
// Textures
uTexture: { value: texture },
uCubeTexture: { value: cubeTexture },
// Arrays
uFloatArray: { value: [1.0, 2.0, 3.0] },
uVec3Array: { value: [new THREE.Vector3(), new THREE.Vector3()] }
}}
为 Uniform 添加动画
function AnimatedShader() {
const materialRef = useRef<THREE.ShaderMaterial>(null!);
useFrame(({ clock, mouse }) => {
const uniforms = materialRef.current.uniforms;
uniforms.uTime.value = clock.elapsedTime;
uniforms.uMouse.value.set(mouse.x, mouse.y);
uniforms.uResolution.value.set(window.innerWidth, window.innerHeight);
});
return (
<shaderMaterial
ref={materialRef}
uniforms={{
uTime: { value: 0 },
uMouse: { value: new THREE.Vector2() },
uResolution: { value: new THREE.Vector2() }
}}
// ...
/>
);
}
共享 Uniform
// Create shared uniform object
const globalUniforms = useMemo(() => ({
uTime: { value: 0 },
uGlobalColor: { value: new THREE.Color('#00ff00') }
}), []);
// Update in useFrame
useFrame(({ clock }) => {
globalUniforms.uTime.value = clock.elapsedTime;
});
// Use in multiple materials
<mesh>
<boxGeometry />
<shaderMaterial uniforms={{ ...globalUniforms, uLocalProp: { value: 1 } }} />
</mesh>
<mesh position={[2, 0, 0]}>
<sphereGeometry />
<shaderMaterial uniforms={{ ...globalUniforms, uLocalProp: { value: 2 } }} />
</mesh>
RawShaderMaterial
没有内置 Uniform 或属性,可进行完全控制:
<rawShaderMaterial
vertexShader={`
precision highp float;
// Must declare all inputs manually
attribute vec3 position;
attribute vec2 uv;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`}
fragmentShader={`
precision highp float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(vUv, 0.0, 1.0);
}
`}
/>
材质扩展
扩展现有材质
import { extend } from '@react-three/fiber';
import { shaderMaterial } from '@react-three/drei';
// Create extended material
const GradientMaterial = shaderMaterial(
// Uniforms
{ uColorA: new THREE.Color('#ff0000'), uColorB: new THREE.Color('#0000ff') },
// Vertex
`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
// Fragment
`
uniform vec3 uColorA;
uniform vec3 uColorB;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(mix(uColorA, uColorB, vUv.y), 1.0);
}
`
);
// Register with R3F
extend({ GradientMaterial });
// Use in JSX
function Gradient() {
return (
<mesh>
<planeGeometry args={[2, 2]} />
<gradientMaterial uColorA="#ff0000" uColorB="#0000ff" />
</mesh>
);
}
性能技巧
| 技巧 | 使用时机 |
|---|---|
| 共享材质 | 多个网格具有相同外观时 |
| 使用开销更低的材质 | 远处的物体(Basic 而非 Standard) |
| 限制纹理尺寸 | 移动设备、大型场景 |
| 禁用不需要的功能 | fog={false}、toneMapped={false} |
材质复用
// Define once
const sharedMaterial = useMemo(() => (
<meshStandardMaterial color="red" roughness={0.5} />
), []);
// Reuse (same GPU program)
{items.map((item, i) => (
<mesh key={i} position={item.pos}>
<boxGeometry />
{sharedMaterial}
</mesh>
))}
文件结构
r3f-materials/
├── SKILL.md
├── references/
│ ├── pbr-properties.md # PBR material deep-dive
│ ├── uniform-types.md # Complete uniform reference
│ └── shader-templates.md # Common shader patterns
└── scripts/
├── materials/
│ ├── gradient.ts # Gradient shader material
│ ├── fresnel.ts # Fresnel/rim effect
│ └── dissolve.ts # Dissolve effect
└── utils/
└── uniform-helpers.ts # Uniform animation utilities
参考资料
references/pbr-properties.md— 深入了解 PBR 材质属性references/uniform-types.md— 所有 Uniform 类型及其 GLSL 映射references/shader-templates.md— 常见着色器效果模式
评论
支持 Markdown