Three.js 着色器使用教程:进阶指南

在 Three.js 的三维场景构建中,着色器(Shader)是极为强大的工具,能显著提升场景渲染效果,创造独特视觉体验。本文假定你已掌握 Three.js 基础,将深入探讨着色器在 Three.js 中的运用。

理解着色器

着色器是运行在 GPU 上的小程序,分为顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。顶点着色器处理几何体顶点,常用于控制物体形状、位置和方向;片段着色器处理每个像素颜色,决定物体表面最终呈现颜色。在 Three.js 中,通过自定义着色器可实现复杂光影效果、材质模拟等。

在 Three.js 中使用自定义着色器

1. 创建着色器材质

使用ShaderMaterial类创建自定义着色器材质。需提供顶点着色器和片段着色器代码字符串。

js 复制代码
const vertexShader = `
    void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
`;
const fragmentShader = `
    void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
`;
const shaderMaterial = new THREE.ShaderMaterial({
    vertexShader,
    fragmentShader
});

上述代码中,顶点着色器仅进行常规坐标变换,将顶点位置转换到屏幕空间。片段着色器将所有像素设置为红色。

2. 应用材质到几何体

将创建的ShaderMaterial应用到几何体上,与使用普通材质类似。

js 复制代码
const geometry = new THREE.BoxGeometry(1, 1, 1);
const mesh = new THREE.Mesh(geometry, shaderMaterial);
scene.add(mesh);

此时,场景中立方体将呈现红色。

示例:实现简单的渐变效果

修改片段着色器实现从顶部蓝色到底部绿色的渐变效果。

js 复制代码
const vertexShader = `
    void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
`;
const fragmentShader = `
    varying vec2 vUv;
    void main() {
        vec4 topColor = vec4(0.0, 0.0, 1.0, 1.0);
        vec4 bottomColor = vec4(0.0, 1.0, 0.0, 1.0);
        float interpolate = vUv.y;
        gl_FragColor = mix(topColor, bottomColor, interpolate);
    }
`;
const shaderMaterial = new THREE.ShaderMaterial({
    vertexShader,
    fragmentShader
});
// 在顶点着色器中传递纹理坐标
const geometry = new THREE.BoxGeometry(1, 1, 1);
geometry.setAttribute('uv', new THREE.BufferAttribute(new Float32Array([
    0, 0,  1, 0,  1, 1,  0, 1
]), 2));
const mesh = new THREE.Mesh(geometry, shaderMaterial);
scene.add(mesh);

这里,在顶点着色器中未做太多修改。片段着色器引入vUv变量(用于存储纹理坐标),通过vUv.y值(范围 0 - 1)对顶部蓝色和底部绿色进行线性插值,实现渐变效果。需注意,要为几何体设置uv属性传递纹理坐标信息。

传递 Uniform 变量

Uniform 变量是在着色器中可在每一帧更新的全局变量。如传递时间变量实现动画效果。

js 复制代码
const vertexShader = `
    uniform float time;
    void main() {
        vec3 newPosition = position;
        newPosition.y += sin(time + position.x) * 0.2;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
    }
`;
const fragmentShader = `
    void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
`;
const shaderMaterial = new THREE.ShaderMaterial({
    vertexShader,
    fragmentShader,
    uniforms: {
        time: { value: 0 }
    }
});
function animate() {
    requestAnimationFrame(animate);
    shaderMaterial.uniforms.time.value += 0.05;
    renderer.render(scene, camera);
}
animate();

在上述代码中,顶点着色器引入time uniform 变量,根据时间和顶点x坐标修改顶点y坐标,实现波浪状动画效果。在animate函数中每一帧更新time uniform 变量值。

总结

通过上述示例,你了解了在 Three.js 中创建和使用自定义着色器、实现渐变效果及传递 uniform 变量。着色器功能强大,可实现复杂材质、光影和动画效果。深入研究着色器语言(GLSL)语法和特性,能为 Three.js 场景开发带来更多创意和可能。

相关推荐
Pop–38 分钟前
Vue3 el-tree:全选时只返回父节点,半选只返回勾选中的节点(省-市区-县-镇-乡-村-街道)
开发语言·javascript·vue.js
滿40 分钟前
Vue3 + Element Plus 动态表单实现
javascript·vue.js·elementui
钢铁男儿1 小时前
C# 方法(值参数和引用参数)
java·前端·c#
阿金要当大魔王~~1 小时前
面试问题(连载。。。。)
前端·javascript·vue.js
yuanyxh1 小时前
commonmark.js 源码阅读(一) - Block Parser
开发语言·前端·javascript
进取星辰1 小时前
22、城堡防御工事——React 19 错误边界与监控
开发语言·前端·javascript
ドロロ8062 小时前
element-plus点击重置表单,却没有进行重置操作
javascript·vue.js·elementui
海盐泡泡龟3 小时前
ES6新增Set、Map两种数据结构、WeakMap、WeakSet举例说明详细。(含DeepSeek讲解)
前端·数据结构·es6
t_hj3 小时前
Ajax案例
前端·javascript·ajax
bigHead-4 小时前
9. 从《蜀道难》学CSS基础:三种选择器的实战解析
前端·css