第九章 Three.js 高级材质与着色器 (二)

9.4 自定义着色器

Three.js允许我们使用自定义着色器来创建独特的视觉效果。自定义着色器使用GLSL(OpenGL Shading Language)编写,通过ShaderMaterial来应用。

示例代码:
javascript 复制代码
// 顶点着色器
const vertexShader = `
varying vec2 vUv;
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;

// 片段着色器
const fragmentShader = `
uniform sampler2D uTexture;
varying vec2 vUv;
void main() {
    gl_FragColor = texture2D(uTexture, vUv);
}
`;

// 加载纹理
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('path/to/texture.jpg');

// 创建自定义着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
    uniforms: {
        uTexture: { type: 't', value: texture }
    },
    vertexShader: vertexShader,
    fragmentShader: fragmentShader
});

// 创建一个立方体并应用自定义着色器材质
const geometry = new THREE.BoxGeometry();
const cube = new THREE.Mesh(geometry, shaderMaterial);
scene.add(cube);

// 渲染循环
function animate() {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
}
animate();

9.5 使用Shaders实现特效

通过自定义着色器,我们可以实现各种特效,如波浪、火焰等。以下是一个简单的波浪效果示例。

示例代码:
javascript 复制代码
// 顶点着色器
const vertexShader = `
uniform float time;
varying vec2 vUv;
void main() {
    vUv = uv;
    vec3 pos = position;
    pos.z += sin(pos.x * 10.0 + time) * 0.1;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`;

// 片段着色器
const fragmentShader = `
varying vec2 vUv;
void main() {
    gl_FragColor = vec4(vUv, 0.5 + 0.5 * sin(vUv.x * 10.0), 1.0);
}
`;

// 创建自定义着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
    uniforms: {
        time: { type: 'f', value: 0 }
    },
    vertexShader: vertexShader,
    fragmentShader: fragmentShader
});

// 创建一个平面几何体并应用自定义着色器材质
const geometry = new THREE.PlaneGeometry(2, 2, 32, 32);
const plane = new THREE.Mesh(geometry, shaderMaterial);
scene.add(plane);

// 渲染循环
function animate() {
    requestAnimationFrame(animate);
    shaderMaterial.uniforms.time.value += 0.05; // 更新时间
    renderer.render(scene, camera);
}
animate();

9.6 后处理效果

Three.js中可以使用后处理效果(Post-Processing)来实现屏幕后处理,如模糊、色调分离等。这通常使用EffectComposer和各种Pass来实现。

示例代码:
javascript 复制代码
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { DotScreenShader } from 'three/examples/jsm/shaders/DotScreenShader.js';

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建场景、相机和物体
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 创建EffectComposer
const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));

// 创建并添加后处理Pass
const effect1 = new ShaderPass(DotScreenShader);
effect1.uniforms['scale'].value = 4;
composer.addPass(effect1);

// 渲染循环
function animate() {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    composer.render(); // 使用composer而不是renderer来渲染场景
}
animate();

通过这一章的学习,读者应该能够创建和使用高级材质,自定义着色器,并实现各种复杂的视觉效果。这些技巧将帮助你在Three.js项目中实现更为复杂和精美的渲染效果。

相关推荐
Highcharts.js37 分钟前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格
Java后端的Ai之路43 分钟前
【AIAgent开发】-Agent工具封装成CLI(纯干货!!!)
java·javascript·人工智能·agent·cli
薛定谔的猫-菜鸟程序员1 小时前
Electron开发超详细教程(从入门到放弃)
前端·javascript·electron
Martina_03212 小时前
AI生成3D模型一合并网格,材质就串色?用6步检查材质槽、UV与图集重映射
图像处理·人工智能·3d·材质·uv·游戏策划·1024程序员节
htzyl2062 小时前
前端阶梯——第四十三章、实战二:待办清单To-Do
前端·javascript·html
程序员大阳2 小时前
HTML+CSS+JS对话式实战(1)-开篇:认识我们要做的社团活动发布平台
javascript·css·html·实战·系统·平台·社团活动发布
速易达网络3 小时前
Three.js 动画入门教学:从场景搭建到流畅动效
开发语言·javascript·ecmascript
Hilaku3 小时前
CORS 到底在保护谁?90% 的前端理解错了跨域的本质
前端·javascript·程序员
阿琳a_4 小时前
b-map-viewer:面向 Vue 3 的地图可视化 SDK,从接入到展示再到交互分析
前端·javascript·vue.js·gis·数据可视化·地图