突然想学学webGL,所以做个记录。
Threejs,一个 基于WebGL 的 JavaScript 3D库 ,封装了WebGL,提供了一系列简单的API便于处理WebGL。
相关概念
场景:scene, 所有物体的容器
相机:camera,设置观察场景的角度和位置
渲染器:renderer, 负责将场景渲染到画布上
使用步骤
本质是使用Three的一系列API创建对象,然后相互组合。
1、下载并引入three.js文件
2、创建场景scene对象
3、创建相机camera对象,并根据参数进行设置
4、创建渲染器renderer对象,渲染器使用js添加到页面中
5、创建物体对象,并把物体对象添加到场景中
6、调用渲染器对象的render函数开始渲染,如果需要不断刷新则需要创建一个函数,并在函数中执行requestAnimationFrame函数,该函数由threejs提供,用于把页面再渲染一次
详细步骤
代码效果是创建一个不断旋转的正方体
1、引入three.js文件
html
<script src="js/three.js"></script>
2、创建场景scene对象
javascript
// 场景 所有物体的容器
var scene = new THREE.Scene();
3、创建相机camera对象,并根据参数进行设置
javascript
// 相机 决定了场景中那个角度的景色会显示出来
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;
PerspectiveCamera 是threejs提供的 透视相机 , 用于3D场景渲染的相机类型,它模拟了人眼观察世界的方式 , 远处的物体看起来比近处的物体小,且遵循透视缩短规律。
构造函数参数:
fov
(Field of View,视野):定义相机视锥体的垂直角度,以弧度为单位。通常设置为如75度这样的值。aspect
(宽高比):视锥体的宽高比,通常是渲染窗口的宽除以高。如果不指定,Three.js会在渲染时自动调整。near
:近裁剪面距离相机的距离。任何比这个距离近的物体都不会被渲染。far
:远裁剪面距离相机的距离。任何比这个距离远的物体都不会被渲染。
属性:
position
:相机的位置,一个THREE.Vector3
对象。rotation
:相机的旋转角度,一个包含x
、y
和z
属性的对象,每个属性都是一个THREE.Euler
对象。up
:相机的上方向向量,一个THREE.Vector3
对象,默认为(0, 1, 0)
,即Y轴向上。
Vector3 三维向量 , 接受三个参数来定义对象的 x、y 和 z ,分别对应 x、y 和 z轴上的值
4、创建渲染器renderer对象,渲染器使用js添加到页面中
javascript
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
5、创建物体对象,并把物体对象添加到场景中
javascript
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color:0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
CubeGeometry 几何立方体 ,较新版本BoxGeometry替换
构造函数参数:
width
(宽度):x方向上的长度。height
(高度):y方向上的长度。depth
(深度):z方向上的长度。widthSegments
(宽度分段):沿x轴的方向,将面分成多少份。默认值是1。heightSegments
(高度分段):沿y轴的方向,将面分成多少份。默认值是1。depthSegments
(深度分段):沿z轴的方向,将面分成多少份。默认值是1。
MeshBasicMaterial 基本材质类型(可以理解为皮肤) ,不考虑光源(想象一个手电筒照在物体上,物体根据光照展示不同效果,这就是光源,实际用起来也是js对象)的影响, 适合用于不需要光照效果的场景 。
构造函数是一个 包含材质属性的对象。
属性:
color
:材质的颜色,默认为白色(0xffffff
)。可以是一个整数,表示十六进制颜色值。map
:基础颜色贴图,可以用来替代材质的颜色。可以是一个THREE.Texture
对象。alphaMap
:透明度贴图,可以用来定义材质的透明度。可以是一个THREE.Texture
对象。emissive
:自发光颜色,默认为黑色(0x000000
)。即使在没有光源的情况下,也会显示这个颜色。emissiveMap
:自发光贴图,可以用来定义自发光的颜色。可以是一个THREE.Texture
对象。opacity
:材质的全局透明度,默认为 1(不透明)。transparent
:是否开启透明模式,默认为false
。如果设置为true
,则需要设置opacity
或者使用alphaMap
。side
:指定材质在哪一面渲染,可以是THREE.FrontSide
(正面)、THREE.BackSide
(背面)或THREE.DoubleSide
(双面)。wireframe
:是否启用线框模式,默认为false
。visible
:是否渲染该材质,默认为true
。depthTest
:是否进行深度测试,默认为true
。depthWrite
:是否写入深度缓冲区,默认为true
。blending
:混合模式,默认为THREE.NormalBlending
。可以设置为THREE.AdditiveBlending
、THREE.SubtractiveBlending
等。vertexColors
:是否启用顶点颜色,默认为THREE.NoColors
。可以设置为THREE.VertexBasicColors
、THREE.VertexColors
或THREE.FaceColors
。flatShading
:是否使用平滑着色,默认为false
。如果设置为true
,则每个面片都将使用平均法线。
Mesh 三维网格对象 ,用于结合了一个几何体和一个或多个材质,并可以被添加到场景中进行渲染
6、调用渲染器对象的render函数开始渲染,如果需要不断刷新则需要创建一个函数,并在函数中执行requestAnimationFrame函数,该函数由threejs提供,用于把页面再渲染一次
javascript
function render() {
// requestAnimationFrame 执行一次参数中的函数,把页面再次渲染一次
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
// 渲染器渲染
/**
render( scene, camera, renderTarget, forceClear )
scene:前面定义的场景
camera:前面定义的相机
renderTarget:渲染的目标,默认是渲染到前面定义的render变量中
forceClear:每次绘制之前都将画布的内容给清除,即使自动清除标志autoClear为false,也会清除
*/
renderer.render(scene, camera);
}
完整代码
如果代码报错,应该是Three版本问题
html
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/three.js"></script>
</head>
<body>
<script>
/* 画一个不断旋转的立体正方体 */
// 场景 所有物体的容器
var scene = new THREE.Scene();
// 相机 决定了场景中那个角度的景色会显示出来
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// 渲染器 使用相机将场景渲染到网页
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 物体添加到场景中
// CubeGeometry 定义一个几何体
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color:0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
function render() {
// requestAnimationFrame 执行一次参数中的函数,把页面再次渲染一次
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
// 渲染器渲染
/**
render( scene, camera, renderTarget, forceClear )
scene:前面定义的场景
camera:前面定义的相机
renderTarget:渲染的目标,默认是渲染到前面定义的render变量中
forceClear:每次绘制之前都将画布的内容给清除,即使自动清除标志autoClear为false,也会清除
*/
renderer.render(scene, camera);
}
render();
</script>
</body>