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 场景开发带来更多创意和可能。

相关推荐
清幽竹客34 分钟前
vue-37(模拟依赖项进行隔离测试)
前端·vue.js
vvilkim34 分钟前
Nuxt.js 页面与布局系统深度解析:构建高效 Vue 应用的关键
前端·javascript·vue.js
滿39 分钟前
Vue3 父子组件表单滚动到校验错误的位置实现方法
前端·javascript·vue.js
专注VB编程开发20年39 分钟前
javascript的类,ES6模块写法在VSCODE中智能提示
开发语言·javascript·vscode
夏梦春蝉2 小时前
ES6从入门到精通:模块化
前端·ecmascript·es6
拓端研究室3 小时前
视频讲解:门槛效应模型Threshold Effect分析数字金融指数与消费结构数据
前端·算法
工一木子4 小时前
URL时间戳参数深度解析:缓存破坏与前端优化的前世今生
前端·缓存
半点寒12W5 小时前
微信小程序实现路由拦截的方法
前端
某公司摸鱼前端6 小时前
uniapp socket 封装 (可拿去直接用)
前端·javascript·websocket·uni-app
要加油哦~6 小时前
vue | 插件 | 移动文件的插件 —— move-file-cli 插件 的安装与使用
前端·javascript·vue.js