目录
自动添加的 Uniforms 和 Attributes
ShaderMaterial
RawShaderMaterial
GLSL 预处理
ShaderMaterial
RawShaderMaterial
使用场景
ShaderMaterial
RawShaderMaterial
代码示例对比
使用 ShaderMaterial
使用 RawShaderMaterial
常见问题与注意事项
总结
在 Three.js 中,RawShaderMaterial
和 ShaderMaterial
都是用于自定义着色器的材质类,但它们的核心区别在于 Three.js 对着色器代码的预处理程度。以下是它们的详细对比:
自动添加的 Uniforms 和 Attributes
ShaderMaterial
-
Three.js 会 自动添加 常用的内置 uniforms 和 attributes,例如:
-
projectionMatrix
(相机投影矩阵) -
modelViewMatrix
(模型视图矩阵) -
viewMatrix
(视图矩阵) -
normalMatrix
(法线矩阵) -
cameraPosition
(相机位置) -
光照、雾效等参数(如果启用相关功能)。
-
-
你不需要在着色器代码中手动声明这些变量,Three.js 会隐式注入它们。
RawShaderMaterial
-
不会自动添加任何内置变量,所有 uniforms 和 attributes 必须手动声明。
-
你需要自己传递所有必需的参数(如矩阵、相机位置等)。
GLSL 预处理
ShaderMaterial
-
Three.js 会自动在着色器代码顶部插入一些预定义内容,例如:
javascript">precision highp float; // 自动设置精度 #include <common> // 包含 Three.js 的通用 GLSL 代码块
-
支持 Three.js 的 GLSL 代码块(如
#include <fog_pars_vertex>
)。
RawShaderMaterial
-
不进行任何预处理,所有 GLSL 代码必须完整且自包含。
-
必须手动设置精度(如
precision highp float;
)。 -
无法直接使用 Three.js 的内置 GLSL 代码块。
使用场景
ShaderMaterial
-
推荐大多数情况使用,尤其是需要 Three.js 内置功能(如光照、雾效)时。
-
适合快速开发,减少重复代码。
RawShaderMaterial
-
适用于需要 完全控制着色器代码 的高级场景。
-
适合学习 WebGL 底层原理,或需要避免 Three.js 隐式行为干扰的情况。
代码示例对比
使用 ShaderMaterial
javascript">const material = new THREE.ShaderMaterial({
vertexShader: `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
});
-
无需声明
projectionMatrix
或modelViewMatrix
,Three.js 已自动处理。
使用 RawShaderMaterial
javascript">const material = new THREE.RawShaderMaterial({
vertexShader: `
precision highp float;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
attribute vec3 position;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
});
-
必须手动声明所有 uniforms 和 attributes(如
projectionMatrix
、position
)。 -
必须手动设置精度(
precision highp float;
)。
常见问题与注意事项
-
错误处理:
使用RawShaderMaterial
时,若忘记声明必要的 uniforms/attributes,会导致着色器编译失败,但 Three.js 可能不会明确提示具体原因。 -
性能差异:
两者性能几乎无差异,最终都会被编译为 WebGL 着色器程序。 -
兼容性:
如果从ShaderMaterial
切换到RawShaderMaterial
,需确保着色器代码中不再依赖 Three.js 的隐式变量(如vNormal
、vViewPosition
等)。
总结
特性 | ShaderMaterial | RawShaderMaterial |
---|---|---|
内置变量支持 | 自动添加 | 需手动声明 |
GLSL 预处理 | 自动插入精度、代码块 | 完全手动编写 |
适合场景 | 常规需求、快速开发 | 完全控制、学习 WebGL 底层 |
代码复杂度 | 低 | 高 |
选择依据:
-
如果需要快速实现常见效果(如光照、雾效),用
ShaderMaterial
。 -
如果需要彻底掌控着色器逻辑,或避免 Three.js 的隐式行为,用
RawShaderMaterial
。