ThreeJS简介介绍

Three.js的学习问题

Three.js的入门是相对简单的,但是当我们真的去学的时候,会发现一个很尴尬的问题:相关的学习资料很少。
通常这种流行的库都有很完善的文档,很多时候跟着官方的文档或官方的入门教程学习就是最好的路线。但Three不是的,它的文档对初学者来说太过简明扼要。
不过官方提供了非常丰富的examples,几乎所有你需要的用法都在某个example中有所体现。但这些example不太适合用来入门,倒是适合入门之后的进一步学习。
这里推荐一些相对较好的教程:

  • Three.js入门指南 :这是一份很好的Three.js 轻量级入门教程,作者文笔很好,基础知识讲解得简明易懂。
  • Three.js开发指南(第一版中文版)
  • Learning Three.js- Second Edition
  • Learning Three.js:The JavaScript 3D Library for WebGL是现在不多的也是最好的Three.js入门书,比较全面地讲解了Three.js的各种功能。 如果有能力的话,建议阅读英文版第二版,出版于2015年,与现在的Three.js区别很小。 中文版翻译自出版于2012年的原书第一版,大部分概念是适用的,但很多细节已经有所改变。
  • Three.js入门教程 :这是对国外一份教程的翻译,一共六篇文章。讲解不多,更多的是展示各个基本功能怎么用。更适合有一些图形基础的同学。

当然,实际的学习过程中这些资料肯定是不太够的,遇到问题还是要自己去查资料。不过这里要提醒一下,Three.js的更新是相当频繁的,现在是r80版本,自2010年4月发布r1以来,这已经是第72个版本了(中间有的版本号跳过了)。因此,在网上找到的资料有些可能是不适合当前版本的,需要注意甄别(前面推荐的资料也都或多或少存在这样的问题)。

剖析源目录结构

  1. 先去下载代码,它的地址是:https://github.com/mrdoob/three.js。 如图所示:
  2. 用解压软件解开刚才的源码包,各个目录如上所示。

Build目录:包含两个文件,three.js 和three.min.js 。这是three.js最终被引用的文件。一个已经压缩,一个没有压缩的js文件。
Docs目录:这里是three.js的帮助文档,里面是各个函数的api,可惜并没有详细的解释。试图用这些文档来学会three.js是不可能的。
Editor目录:一个类似3D-max的简单编辑程序,它能创建一些三维物体。
Examples目录:一些很有趣的例子demo,可惜没有文档介绍。对图像学理解不深入的同学,学习成本非常高。
Src目录:源代码目录,里面是所有源代码。
Test目录:一些测试代码,基本没用。
Utils目录:存放一些脚本,python文件的工具目录。例如将3D-Max格式的模型转换为three.js特有的json模型。
.gitignore文件:git工具的过滤规则文件,没有用。
CONTRIBUTING.md文件:一个怎么报bug,怎么获得帮助的说明文档。
LICENSE文件:版权信息。
README.md文件:介绍three.js的一个文件,里面还包含了各个版本的更新内容列表。

Three.js中的一些概念

要在屏幕上展示3D图形,思路大体上都是这样的:
1、构建一个三维空间
Three中称之为场景(Scene)
2、选择一个观察点,并确定观察方向/角度等
Three中称之为相机(Camera)
3、在场景中添加供观察的物体
Three中的物体有很多种,包括Mesh,Line,Points等,它们都继承自Object3D类
4、将观察到的场景渲染到屏幕上的指定区域
Three中使用Renderer完成这一工作

Scene

场景是所有物体的容器,也对应着我们创建的三维世界。

Camera

坐标系

Camera是三维世界中的观察者,为了观察这个世界,首先我们要描述空间中的位置。 Three中使用采用常见的右手坐标系定位。

ThreeJS简介介绍

三维投影

Three中的相机有两种,分别是正投影相机THREE.OrthographicCamera和透视投影相机THREE.PerspectiveCamera。

ThreeJS简介介绍

正交投影与透视投影的区别如上图所示,左图是正交投影,物体发出的光平行地投射到屏幕上,远近的方块都是一样大的;右图是透视投影,近大远小,符合我们平时看东西的感觉。

1)正交投影相机

ThreeJS简介介绍

这里补充一个视景体的概念:视景体是一个几何体,只有视景体内的物体才会被我们看到,视景体之外的物体将被裁剪掉。这是为了去除不必要的运算。

正交投影相机的视景体是一个长方体,OrthographicCamera的构造函数是这样的:

OrthographicCamera( left, right, top, bottom, near, far )

Camera本身可以看作是一个点,left则表示左平面在左右方向上与Camera的距离。另外几个参数同理。于是六个参数分别定义了视景体六个面的位置。

可以近似地认为,视景体里的物体平行投影到近平面上,然后近平面上的图像被渲染到屏幕上。

2)透视投影相机

ThreeJS简介介绍

透视投影相机的视景体是个四棱台,它的构造函数是这样的:

PerspectiveCamera( fov, aspect, near, far )

fov对应着图中的视角,是上下两面的夹角。aspect是近平面的宽高比。在加上近平面距离near,远平面距离far,就可以唯一确定这个视景体了。
透视投影相机很符合我们通常的看东西的感觉,因此大多数情况下我们都是用透视投影相机展示3D效果。

Objects

有了相机,总要看点什么吧?在场景中添加一些物体吧。
Three中供显示的物体有很多,它们都继承自Object3D类,这里我们主要看一下Mesh和Points两种。
1)Mesh
我们都知道,计算机的世界里,一条弧线是由有限个点构成的有限条线段连接得到的。线段很多时,看起来就是一条平滑的弧线了。
计算机中的三维模型也是类似的,普遍的做法是用三角形组成的网格来描述,我们把这种模型称之为Mesh模型。

ThreeJS简介介绍

这是那只著名的斯坦福兔子。它在3D图形中的地位与数字图像处理领域中著名的lena是类似的。
看这只兔子,随着三角形数量的增加,它的表面越来越平滑/准确。
在Three中,Mesh的构造函数是这样的:

Mesh( geometry, material )

geometry是它的形状,material是它的材质。
不止是Mesh,创建很多物体都要用到这两个属性。下面我们来看看这两个重要的属性。
2)Geometry
Geometry,形状,相当直观。Geometry通过存储模型用到的点集和点间关系(哪些点构成一个三角形)来达到描述物体形状的目的。
Three提供了立方体(其实是长方体)、平面(其实是长方形)、球体、圆形、圆柱、圆台等许多基本形状;
你也可以通过自己定义每个点的位置来构造形状;
对于比较复杂的形状,我们还可以通过外部的模型文件导入。
3)Material
Material,材质,这就没有形状那么直观了。
材质其实是物体表面除了形状以为所有可视属性的集合,例如色彩、纹理、光滑度、透明度、反射率、折射率、发光度。
这里讲一下材质(Material)、贴图(Map)和纹理(Texture)的关系。
材质上面已经提到了,它包括了贴图以及其它。
贴图其实是’贴’和’图’,它包括了图片和图片应当贴到什么位置。
纹理嘛,其实就是’图’了。
Three提供了多种材质可供选择,能够自由地选择漫反射/镜面反射等材质。
4)Points
讲完了Mesh,我们来看看另一种Object——Points。
Points其实就是一堆点的集合,它在之前很长时间都被称为ParticleSystem(粒子系统),r68版本时更名为PointCloud,r72版本时才更名为Points。更名主要是因为,Mr.doob认为,粒子系统应当是包括粒子和相关的物理特性的处理的一套完整体系,而Three中的Points简单得多。因此最终这个类被命名为Points。
5)Light
神说:要有光!
光影效果是让画面丰富的重要因素。
Three提供了包括环境光AmbientLight、点光源PointLight、 聚光灯SpotLight、方向光DirectionalLight、半球光HemisphereLight等多种光源。
只要在场景中添加需要的光源就好了。
6)Renderer
在场景中建立了各种物体,也有了光,还有观察物体的相机,是时候把看到的东西渲染到屏幕上了。这就是Render做的事情了。
Renderer绑定一个canvas对象,并可以设置大小,默认背景颜色等属性。
调用Renderer的render函数,传入scene和camera,就可以把图像渲染到canvas中了。

让画面动起来

现在,一个静态的画面已经可以得到了,怎么才能让它动起来?
很简单的想法,改变场景中object的位置啊角度啊各种属性,然后重新调用render函数渲染就好了。
那么重新渲染的时机怎么确定?
HTML5为我们提供了requestAnimFrame,它会自动在每次页面重绘前调用传入的函数。
如果我们一开始这样渲染:

function render()
{
    renderer.render(scene, camera);
}

只需要改成这样:

function render()
{
    requestAnimationFrame(render);
    object.position.x += 1;
    renderer.render(scene, camera);
}

object就可以动起来了!

举个例子

下面我们用一个简单的例子来梳理一下这个过程。
首先写一个有Canvas元素的页面吧。

DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>立方体title>
    <script src="http://sqimg.qq.com/qq_product_operations/mma/javanli_test/lib/three.min.js">script>
    <style type="text/css">
        html, body {
            margin: 0;
            padding: 0;
        }
        #three_canvas {
            position: absolute;
            width: 100%;
            height: 100%;
        }
    style>
head>
<body>
    <canvas id="three_canvas">canvas>
body>
html>

下面来做Javascript的部分
首先初始化Renderer

function initRenderer() {
    width = document.getElementById('three_canvas').clientWidth;
    height = document.getElementById('three_canvas').clientHeight;
    renderer = new THREE.WebGLRenderer({
        //将Canvas绑定到renderer
        canvas: document.getElementById('three_canvas')
    });
    renderer.setSize(width, height);//将渲染的大小设为与Canvas相同
    renderer.setClearColor(0xFFFFFF, 1.0);//设置默认颜色与透明度
}

初始化场景:

function initScene() {
    scene = new THREE.Scene();
}

初始化相机:

function initCamera() {
    //简单的正交投影相机,正对着视口的中心,视口大小与Canvas大小相同。
    camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, 1, 1000);
    //设置相机的位置
    camera.position.x = 0;
    camera.position.y = 0;
    camera.position.z = 200;
    //设置相机的上方向
    camera.up.x = 0;
    camera.up.y = 1;
    camera.up.z = 0;
    //设置相机聚焦的位置(其实就是确定一个方向)
    camera.lookAt({
        x: 0,
        y: 0,
        z: 0
    });
}

要唯一确定一个相机的位置与方向,position、up、lookAt三个属性是缺一不可的。
这里我们创建了一个正交投影相机,这里我将视景体大小与屏幕分辨率保持一致只是为了方便,这样坐标系中的一个单位长度就对应屏幕的一个像素了。
我们将相机放在Z轴上,面向坐标原点,相机的上方向为Y轴方向,注意up的方向和lookAt的方向必然是垂直的(类比自己的头就知道了)。
下面添加一个立方体到场景中:

function initObject() {
    //创建一个边长为100的立方体
    var geometry = new THREE.CubeGeometry(100, 100, 100);
    object = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
    scene.add(object);
}

注意我们使用了法向材质 MeshNormalMaterial,这样立方体每个面的颜色与这个面对着的方向是相关的,更便于观察/调试。
在这个简单的demo里我不打算添加光影效果,而法向材质对光也是没有反应的。 最后来创建一个动画循环吧

function render() {
    requestAnimationFrame(render);
    object.rotation.x += 0.05;
    object.rotation.y += 0.05;
    renderer.render(scene, camera);
}

每次重绘都让这个立方体转动一点点。 当页面加载好时,调用前面这些函数就好了。

function threeStart() {
    initRenderer();
    initCamera();
    initScene();
    initObject();
    render();
}
window.onload = threeStart();

参考资料

WebGL中文网
WebGL中文教程网

Original: https://www.cnblogs.com/fps2tao/p/16531471.html
Author: 与f
Title: ThreeJS简介介绍

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/549136/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 山果湾农文旅/自然教育 商业计划书

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/LittleHann/p/16295816.htmlAu…

    技术杂谈 2023年5月31日
    0109
  • 【LEETCODE】70、字符匹配1023 Camelcase Matching

    最近做leetcode总感觉自己是个智障,基本很少有题能自己独立做出来,都是百度。。。 不过终于还是做出了一题。。。而且速度效率还可以 哎,加油吧,尽量锤炼自己 package y…

    技术杂谈 2023年7月24日
    070
  • 两个平板打天下-将中国看做一个城市圈,漉战移动互联网、高铁时代

    旧有两把菜刀闹革命,今有两个平板打天下。最近搞了个七寸平板手机,用了几天,很是满意,即可打电话,又可刷微博微信,又可看电子书、PDF,还可以打游戏,重度应用下也能支撑10小时。恰逢…

    技术杂谈 2023年6月1日
    067
  • shell编程-杨辉三角简单实现

    shell编程-杨辉三角问题: 概述:中国古代数学家在数学的许多重要领域中处于遥遥领先的地位。中国古代数学史曾经有自己光辉灿烂的篇章,而杨辉三角的发现就是十分精彩的一页。杨辉三角形…

    技术杂谈 2023年7月24日
    0107
  • 十、包机制与JavaDoc

    一、包机制 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间。包语句的语句格式为: package pkg1[. pkg2[. pkg3…]]; 一般使用公司域名…

    技术杂谈 2023年6月21日
    096
  • 机器学习系统或者SysML&DL笔记(一)

    前言 在使用过TVM、TensorRT等优秀的机器学习编译优化系统以及Pytorch、Keras等深度学习框架后,总觉得有必要从 理论上对这些系统进行一些分析,虽然说在实践中学习是…

    技术杂谈 2023年7月11日
    083
  • H3C 什么是漫游

    posted @2019-09-22 22:21 樊伟胜 阅读(609 ) 评论() 编辑 Original: https://www.cnblogs.com/fanweishen…

    技术杂谈 2023年5月30日
    0106
  • python数据可视化-matplotlib入门(3)-利用随机函数生成变化图形2

    鉴于上一篇中最后三个问题: 1、上述程序是否能进行优化(比如功能相同的) 2、创建三个3个实例,用了3个语句,能否建一个函数,只输入一个数n,就自动创建n个实例?同时,每个实例的n…

    技术杂谈 2023年7月25日
    066
  • Android系统中有哪些日志信息和工具

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    技术杂谈 2023年7月10日
    075
  • asp 遍历文件夹

    转载请注明出处:http://www.cnblogs.com/cloudgamer/ 如有任何建议或疑问,欢迎留言讨论。 如果觉得文章不错的话,欢迎点一下右下角的推荐。 程序中包含…

    技术杂谈 2023年5月30日
    0110
  • 继承中的初始化和加载

    继承关系中的执行顺序代码 package onjava8.extend; /** * &#x7EE7;&#x627F;&#x5173;&#x7CFB…

    技术杂谈 2023年7月25日
    073
  • Threejs之基础场景脚本

    一个完整的3D环境包含以下元素: 1.场景(Scene):是物体、光源等元素的容器,2.相机(Camera):控制视角的位置、范围以及视觉焦点的位置,一个3D环境中只能存在一个相机…

    技术杂谈 2023年5月31日
    085
  • springboot小结

    创建一个SpringBoot项目 创建项目注意点 然后选中自己需要的依赖 不过后期还可以自己导入不过比较麻烦 分析各种包 不过的文件夹需要自己建 图标写成这样放到public下面就…

    技术杂谈 2023年7月11日
    069
  • quartz框架(五)-Trigger相关内容

    上篇博文,博主介绍了Job的相关内容。本篇博文,博主将介绍Trigger相关的内容。 Trigger是触发器的意思,它只定义Trigger相关属性的Get方法。一个Trigger只…

    技术杂谈 2023年7月24日
    072
  • RISCV学习-1 RISCV模拟器

    最近有个项目需要用到RISCV开发板,没拿到开发板之前,先尝试配置一个虚拟机环境1、配置riscv-toolchain git clone https://github.com/r…

    技术杂谈 2023年6月1日
    078
  • centos7 安装python3 小白教程-CV大法

    centos7,默认系统自带python2.7的版本,这个版本被系统很多程序所依赖,所以不建议删除,如果使用最新的Python3那么我们知道编译安装源码包和系统默认包之间是没有任何…

    技术杂谈 2023年7月10日
    063
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球