3D基本原理
为了实现3D图像的动态展示有三个要点:
三维场景包括三维模型、光源、相机三个部分构成。
从最简单的情形来说,三维模型由网格(mesh)和材质(material)组成。网格则一般由若干个图元(一般是空间中的三角形)拼接而成。网格表面还要考虑本身的纹理和对光源的反射情况。所以3D模型的数据主要是顶点信息和网格表面材质信息。
光源就是在空间中人为添加光照信息,例如方向,强度,光色等。没有光源,渲染出来的3D场景将一片漆黑。
相机相当于场景的一个观察点。相机在建立时就要确定,视角,远平面,近平面,纵横比四个参数。根据这些参数可以确定一个可视区域。3D模型必须在可视区域(view frustum)内。否则将不会被屏幕捕捉。
将场景以2D的形式显示
要想将场景以2D的形式显示出来,实际就是将空间中的点映射为平面的像素值。这个过程需要考虑两个关系:
模型和相机之间的关系:这个变换关系由两个矩阵控制,其中一个矩阵表示了相机所在位置和方向,另一个矩阵控制了从3D到2D的投影参数。模型和相机的关系决定空间中的某一点是否会被渲染。
光源和材质的关系: 光源和材质的关系决定这一点的像素值会是多少。着色器将会结合该点的材质(包括对光的反射率)和光照强度,判断该点的颜色。
当3D数据发生改变时,可以近乎无延迟的对2D图像更新渲染
上述复杂的映射过程,实际是交给着色器来完成的,着色器往往是一种基于gpu的程序(所谓硬件加速)。保证了渲染的低延迟。
https://codepen.io/AlexZ33/pe...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Example01.01-Basic skeleton </title>
<style>
body{
margin:0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="WebGL-output">
</div>
<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
<script>
function init() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE);
renderer.setSize(window.innerWidth,window.innerHeight);
//创建轴(axes)对象,并调用scene.add方法将轴添加到场景中
var axes = new THREE.AxisHelper(20);
scene.add(axes);
//定义平面
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
//创建材质来设置平面外观
var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
//将对象planeGeometry 和 planeMaterial 合并到名为plane的网格对象中
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x = -0.5*Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
scene.add(plane);
var cubeGeometry = new THREE.BoxGeometry(4,4,4);
var cubeMaterial = new THREE.MeshBasicMaterial({color:0xff0000,wireframe:true});
var cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;
scene.add(cube);
var sphereGeometry = new THREE.SphereGeometry(4,20,20);
var sphereMaterial = new THREE.MeshBasicMaterial({color:0x7777ff,wireframe:true});
var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x = 20;
sphere.position.y = 4;
sphere.position.z = 2;
scene.add(sphere);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
document.getElementById("WebGL-output")
.appendChild(renderer.domElement);
renderer.render(scene,camera);
};
window.onload = init;
</script>
</body>
</html>请输入代码
接下来我们会用光照、阴影、材质和动画来美化。
首先添加光源:
//添加点光源
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
scene.add(spotLight);
因为使用的是THREE.MeshBasicMaterial
所以不会对光源有反应,基本材质只会使用指定的颜色来渲染物体。
因此,替换THREE.MeshBasicMaterial
为THREE.MeshLamberMaterial
现在我们来添加阴影效果:
因为渲染阴影需要消耗大量计算资源,所以默认下是不会渲染阴影的。
因此,我们需要:
renderer.setClearColor(new THREE.Color(0xeeeeee,1.0));
render.setSize(window.innerWidth,window.innerHeight);
renderer.shadowMapEnabled = true;//告诉渲染器需要阴影效果
以上没有明确指定哪个物体投射阴影,哪个物体接受阴影。
示例中,我们将相应的属性设置为true
来指定球体和立方体在地面上投射阴影:
plane.receiveShadow = true;
cube.castShadow = true;
sphere.castShadow = true;
spotLight.castShadow = true;
可参考实例
https://codepen.io/Yakudoo/pe...
参考
《Three.js 开发指南》
3D机房前端学习笔记
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。