这不是完整教程,更像笔记
参考 Three.js Essentials这本书,有很多地方直接复制翻译的内容
Three.js 的函数有有用到异步加载,当制作复杂的3d视图有加载本地图片及其他文件时应该建立本地服务器,否则直接运行html文件时浏览器会提示加载错误:
XMLHttpRequest cannot load file:///F:/phptools/Apache2.2/htdocs/threejs/data/wpi.csv. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
我使用的是Apache,但是对于Three.js本地调试,不需要太复杂的网络服务器环境,可以使用Python搭建
使用Python运行Web服务器
最简单的方法 检查您是否安装了Python,只需python在命令行中键入即可。如果你看到如下输出,你就有了安装了Python,您可以使用它来运行简单的Web服务器:
复制
> python
Python 2.7.3 (default, Apr 10 2013, 05:09:49)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
键入以下代码:
> python -m SimpleHTTPServer
输出将如下面的代码片段所示:
Serving HTTP on 0.0.0.0 port 8000...
这将启动端口8000上的Web服务器,它允许您从运行此命令的目录访问所有文件。
还可以安装其他Node.js以及便携网络服务器Mongoose
如果无法安装本地Web服务器,则会有最终的替代方案。可以直接从浏览器打开文件(或在浏览器窗口中拖放文件)。对于很多例子,这将直接工作; 但是,一旦需要加载外部资源的纹理或其他功能,由于浏览器的安全设置,这种方法将停止工作。可以更改此安全策略,以便使用这些功能的示例也可以正常工作。有关如何做到这一点的一个很好的解释,请参见Three.js网站:https://github.com/mrdoob/three.js/wiki/How-to-run-things-locally。
现在创建Three.js Web应用程序
在script标签中做的第一件事就是设置了一些全局变量。
// 全局变量
var renderer;
var scene;
var camera;
var control;
var cube;
使用init()初始化
function init() {
// Three.js 初始化代码
}
window.onload = init();
使用该window.onload功能,告诉浏览器在加载文档完成时调用init()该功能。、
该完整init():
function init() {
addscene();//添加场景
addcube();//添加立方体
addplane();//添加地面
addlight();//添加光线
initgui();//初始化dat.gui控件
addStatsObject();//添加帧率显示控件
render();//启动渲染
console.log('Log statement from the init function');//控制台调试可以省略,加上可以在浏览器的控制台看到cube的具体信息
console.log(cube);
}
初始化函数
function addscene(){
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 20;
camera.position.y = 20;
camera.position.z = 20;
camera.lookAt(scene.position);
document.body.appendChild(renderer.domElement);
}
在前面的代码片段中,我们创建了三个基本的Three.js对象。首先,我们创建了一个THREE.Scene对象。这个对象是容纳所有要渲染的对象的容器。接下来,我们创建了一个THREE.WebGLRenderer对象。这是我们将用于渲染创建的THREE.Scene对象的Three.js 对象。最后,THREE.PerspectiveCamera对象决定了我们看到的内容。init()函数的最后一个调用是调用render()函数,如下面的代码所示:
function addcube(){
var cubeGeometry = new THREE.CubeGeometry(6, 4, 6);
var cubeMaterial = new THREE.MeshLambertMaterial({
color: "red"
});//需要光
//cubeMaterial = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cubeMaterial.transparent = true;//设置为ture来改变透明度,默认1
cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
scene.add(cube);
}
添加了立方cube 材质为THREE.MeshLambertMaterial这种材质需要光照才会显示
cube.castShadow = true; 设置ture来呈现阴影
function addplane(){//plane ground
var planeGeometry = new THREE.PlaneGeometry(30, 20);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0xcccccc
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
plane.position.y = -2;
plane.position.z = 0;
scene.add(plane);
}
function addlight(){
//shadow
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(10, 20, 20);
spotLight.castShadow = true;
scene.add(spotLight);
}
添加地面以及光照 光照使用点光源spotLight.castShadow = true; 阴影
function render() {
// render using requestAnimationFrame
cube.material.opacity = control.opacity;
cube.material.opacity = control.opacity;
stats.update();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
使用renderer.render()功能可视化场景。使用requestAnimationFrame函数来设置一个渲染循环。通过requestAnimationFrame功能,在浏览器最好情况下调用附带的函数(render在这种情况下是函数)。这提供了更平滑的体验和更好的表现。当循环执行时,就可以动态的改变cub的属性cube.material.opacity = control.opacity;cube.material.opacity = control.opacity;然后进行新的渲染,这里的值来自dat.gui控件的值
function initgui(){
control = new function() {
this.rotationSpeed = 0.005;
this.opacity = 0.6;
this.color = cube.material.color.getHex();
};
addControlGui(control);
}
function addControlGui(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed', -0.01, 0.01);
gui.add(controlObject, 'opacity', 0.1, 1);
gui.addColor(controlObject, 'color');
}
这里的control为全局变量,更改后值实时的传递到render()函数中,这样实现使用控件动态改变cube的属性
以下完整html代码
<!DOCTYPE html>
<html>
<head>
<title>simple 3d</title>
<style>
body {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}/*无边框*/
canvas {
width: 100%;
height: 100%;
}/*布满屏幕*/
</style>
</head>
<body>
</body>
<script src="../js/three.js"></script>
<!--three.js主要的文件-->
<script src="../js/dat.gui.min.js"></script>
<!--dat.gui.js控件,用于调整属性-->
<script src="../js/stats.min.js"></script>
<!--stats.js显示帧率及其他信息-->
<!--以下代码创建场景物体摄像机-->
<script>
var renderer;
var scene;
var camera;
var control;
var cube;
function init() {
addscene();
addcube();
addplane();
addlight();
initgui();
addStatsObject();
render();
console.log('Log statement from the init function');
console.log(cube);
}
function addscene(){
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 20;
camera.position.y = 20;
camera.position.z = 20;
camera.lookAt(scene.position);
document.body.appendChild(renderer.domElement);
}
function addcube(){
var cubeGeometry = new THREE.CubeGeometry(6, 4, 6);
var cubeMaterial = new THREE.MeshLambertMaterial({
color: "red"
});//need light
//cubeMaterial = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
cubeMaterial.transparent = true;//when you want to chang opacity ,you should set this ture.
cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
scene.add(cube);
}
function addplane(){//plane ground
var planeGeometry = new THREE.PlaneGeometry(30, 20);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0xcccccc
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
plane.position.y = -2;
plane.position.z = 0;
scene.add(plane);
}
function addlight(){
//shadow
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(10, 20, 20);
spotLight.castShadow = true;
scene.add(spotLight);
}
function render() {
// render using requestAnimationFrame
cube.material.opacity = control.opacity;
cube.material.color = new THREE.Color(control.color);
document.getElementById('otherinfo').innerHTML = ""+"::"+"";
stats.update();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
window.onload = init();
function initgui(){
control = new function() {
this.rotationSpeed = 0.005;
this.opacity = 0.6;
this.color = cube.material.color.getHex();
};
addControlGui(control);
}
function addControlGui(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed', -0.01, 0.01);
gui.add(controlObject, 'opacity', 0.1, 1);
gui.addColor(controlObject, 'color');
}
function addStatsObject() {
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
}
</script>
</html>