RawShaderMaterial 这个材质没有私有属性,全部属性由材质基类与着色器材质属性 继承
RawShaderMaterial 可以让你在 Three.js 中直接编写自己的 GLSL(着色器语言)代码,以实现自定义的渲染效果。相比于 ShaderMaterial,RawShaderMaterial 不会自动处理一些默认的着色器内容,所有的逻辑都需要你自己编写。这为你提供了更大的灵活性,但也要求你对 WebGL 和 GLSL 有一定的理解。
Three.js 提供了很多现成的材质(如 MeshBasicMaterial, MeshStandardMaterial 等),这些材质内部封装了大量的渲染逻辑,开发者只需要简单设置参数即可。但有时,你可能希望实现一些特殊的渲染效果,这时 RawShaderMaterial 就非常有用。
这个材质最最要的是要了解顶点着色器与片元着色器
- 在three 中所有的几何体 所有的几何体都是有三角形组成,而顶点是指的这些三角形,顶点着色器的 每一个顶点都会经过 顶点着色器的main计算位置? 下面是一个使用顶点着色器改变顶点位置的例子
- 在three 中所有的颜色都经过 片元着色器中的 main 计算得出当前像素点的颜色值然后渲染出来,下面是一个使用片元着色器渲染像素的例子.
// 立方体的 8 个顶点
V0 = (1, 1, 1)
V1 = (1, -1, 1)
V2 = (-1, 1, 1)
V3 = (-1, -1, 1)
V4 = (1, 1, -1)
V5 = (1, -1, -1)
V6 = (-1, 1, -1)
V7 = (-1, -1, -1)
// 面 1:由顶点 V0、V1、V2 和 V2、V1、V3 组成。
// 面 2:由顶点 V0、V4、V5 和 V0、V5、V1 组成。
// (依此类推,为其他面定义三角形)
const topPoint = `
uniform float time;
attribute vec3 position;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main() {
// 基于顶点位置和时间的波动效果
vec3 newPosition = position;
newPosition.z += sin(newPosition.x * 4.0 + time) * 0.8; // X 方向上的波动
newPosition.z += sin(newPosition.y * 4.0 + time) * 0.2; // Y 方向上的波动
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
`
const colorFn = `
void main() {
gl_FragColor = vec4(0.3, 0.6, 1.0, 1.0); // 蓝色
}
`
// 创建自定义的顶点和片元着色器材质
const material = new THREE.RawShaderMaterial({
vertexShader: topPoint,
fragmentShader: colorFn,
side: THREE.DoubleSide,
uniforms: {
time: { value: 0.0 }
}
});
// 定义立方体的顶点
const vertices = new Float32Array([
1, 1, 1, // V0
1, -1, 1, // V1
-1, 1, 1, // V2
-1, -1, 1, // V3
1, 1, -1, // V4
1, -1, -1, // V5
-1, 1, -1, // V6
-1, -1, -1 // V7
]);
// 定义立方体的面(每个面由两个三角形组成)
const indices = new Uint16Array([
0, 1, 2, 2, 1, 3, // 前面
4, 5, 6, 6, 5, 7, // 后面
0, 2, 4, 4, 2, 6, // 左面
1, 5, 3, 3, 5, 7, // 右面
2, 3, 6, 6, 3, 7, // 上面
0, 4, 1, 1, 4, 5 // 下面
]);
// 创建 BufferGeometry
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// 创建网格并添加到场景中
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);