46. Three.js案例-创建颜色不断变化的立方体模型
46. Three.js案例-创建颜色不断变化的立方体模型
实现效果
知识点
Three.js基础组件
WebGLRenderer
THREE.WebGLRenderer
是Three.js提供的用于渲染场景的WebGL渲染器。它支持抗锯齿处理,可以设置渲染器的大小和背景颜色。
- 构造器
antialias
: 是否开启抗锯齿,默认为false。setSize(width, height)
: 设置渲染器的宽度和高度。setClearColor(color, alpha)
: 设置渲染器的背景颜色和透明度。
Scene
THREE.Scene
是Three.js中的场景对象,所有的物体都需要添加到场景中才能被渲染。
- 方法
add(object)
: 向场景中添加物体。
PerspectiveCamera
THREE.PerspectiveCamera
是透视相机,模拟人眼的视角效果。
- 构造器
fov
: 视野角度(Field of View),通常设置为45度。aspect
: 宽高比,通常是窗口宽度除以高度。near
: 近裁剪面距离。far
: 远裁剪面距离。
- 属性
position
: 相机的位置。lookAt(vector)
: 设置相机看向的目标位置。
ShaderMaterial
ShaderMaterial
THREE.ShaderMaterial
允许用户自定义着色器,通过编写GLSL代码来控制物体的外观。
- 构造器
uniforms
: 传递给着色器的统一变量。time
: 时间变量,类型为浮点数。resolution
: 分辨率变量,类型为二维向量。
vertexShader
: 顶点着色器代码。fragmentShader
: 片元着色器代码。
顶点着色器
顶点着色器负责计算每个顶点的位置,并将一些数据传递给片元着色器。
varying vec2 vUv;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
片元着色器
片元着色器负责计算每个像素的颜色。
uniform float time;
uniform vec2 resolution;
varying vec2 vUv;
void main( void ) {
vec2 position = -1.0 + 2.0 * vUv;
float red = abs(sin(position.x * position.y + time / 5.0));
float green = abs(sin(position.x * position.y + time / 4.0));
float blue = abs(sin(position.x * position.y + time / 3.0));
gl_FragColor = vec4(red, green, blue, 1.0);
}
Mesh
THREE.Mesh
是网格对象,由几何体和材质组成。
- 构造器
geometry
: 几何体,如BoxGeometry
。material
: 材质,如ShaderMaterial
。
动画
使用requestAnimationFrame
函数实现动画效果,不断更新物体的旋转角度和时间变量。
function animate() {
myMesh.rotation.y = myStep += 0.01;
myMesh.rotation.x = myStep;
myMesh.rotation.z = myStep;
myMesh.material.uniforms.time.value += 0.1;
requestAnimationFrame(animate);
myRenderer.render(myScene, myCamera);
}
代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="ThreeJS/three.js"></script>
<script src="ThreeJS/jquery.js"></script>
</head>
<body>
<div id="myContainer"></div>
<script id="myVertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="myFragmentShader" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution;
varying vec2 vUv;
void main( void ) {
vec2 position = -1.0 + 2.0 * vUv;
float red = abs(sin(position.x * position.y + time / 5.0));
float green = abs(sin(position.x * position.y + time / 4.0));
float blue = abs(sin(position.x * position.y + time / 3.0));
gl_FragColor = vec4(red, green, blue, 1.0);
}
</script>
<script type="text/javascript">
var myRenderer = new THREE.WebGLRenderer({antialias: true});
myRenderer.setSize(window.innerWidth, window.innerHeight);
myRenderer.setClearColor('white', 1.0);
$('#myContainer')[0].appendChild(myRenderer.domElement);
var myScene = new THREE.Scene();
var myCamera = new THREE.PerspectiveCamera(45,
window.innerWidth / window.innerHeight, 10, 130);
myCamera.position.x = 30;
myCamera.position.y = 30;
myCamera.position.z = 30;
myCamera.lookAt(new THREE.Vector3(0, 0, 0));
var myShaderMaterial = new THREE.ShaderMaterial({
uniforms: {
time: {type: "f", value: 1.0},
resolution: {type: "v2", value: new THREE.Vector2()},
},
vertexShader: $('#myVertexShader')[0].textContent,
fragmentShader: $('#myFragmentShader')[0].textContent
});
var myBoxGeometry = new THREE.BoxGeometry(16, 16, 16);
var myMesh = new THREE.Mesh(myBoxGeometry, myShaderMaterial);
myScene.add(myMesh);
var myStep = 0;
function animate() {
myMesh.rotation.y = myStep += 0.01;
myMesh.rotation.x = myStep;
myMesh.rotation.z = myStep;
myMesh.material.uniforms.time.value += 0.1;
requestAnimationFrame(animate);
myRenderer.render(myScene, myCamera);
}
animate();
</script>
</body>
</html>
演示链接
示例链接