Three.js入门——画星空(star field)
Three.js是一个很流行的3D JavaScript库。这里有一个three.js的入门教程,在浏览器窗口中画出星空。我按照教程重新实现了一遍,这里的这篇博客把教程大致翻译了一遍。我的demo。
变量
定义全局变量:
// three.js的主要部分
var camera, scene, renderer,
// 跟踪鼠标位置
mouseX = 0, mouseY = 0,
// 一个数组,用于存储我们的粒子
particles = [];
// 初始化
init();
初始化three.js
为了使用three.js,我们需要在init()函数中设置三个主要的对象:
- scene(场景): 场景中包含了所有的3D对象数据
- camera(相机): 相机有位置(position),旋转(rotation)和视野属性(field of view)
- renderer(渲染器): 决定场景中的一个物体在照相机的视角看来是什么样子
照相机(Camera)
```
function init() {
// 照相机参数
camera = new THREE.PerspectiveCamera(80, window.innerWidth/window.innerHeight, 1, 4000);
// 将相机向后(即屏幕外)移
camera.position.z = 1000;
```
Camera构造器的第一个参数是视野(field of view)。这是一个角度,越大,则表示虚拟的相机镜片越宽。
第二个参数是输出的宽和高之比。这个值必须与CanvasRenderer相一致。
相机只能看见一定范围之内的物体,这个范围是由near和far来确定的,在这里分别为1和4000。因而任何比1近的物体或者比4000远的物体是不会被渲染的。
在默认情况下相机位于3D世界的起始位置(origin)0,0,0(我的上一篇博客用CSS3绘制一个旋转的立方体中有关于origin的介绍)。但是你创建的3D物体也会放置在这一点,因而默认值用处并不大。我们需要将相机向后移动一点,即给其一个正的z值(由屏幕内指向外侧)。在这里将其移动1000。
场景(Scene)
```
// the scene contains all the 3D object data
scene = new THREE.Scene();
scene.add(camera);
注意必须将相机加入到场景中。
```
渲染器(Renderer)
```
// 加入CanvasRenderer,由渲染器决定场景中的物体看起来如何,并将其画出
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器的canvas domElement加入到body中
document.body.appendChild(renderer.domElement);
```
这里的CanvasRenderer创建了它自己的DOM元素,这是一个普通的2D canvas对象,我们需要把它加入到文件的body部分才能看见它。我们想让它充满整个浏览器窗口,所以将它的大小设置为window.innerWidth和window.innerHeight。
渲染循环
接下来我们需要做的是产生粒子,加入鼠标移动监听器(mousemove listener)来追踪鼠标位置,最后设定间隔每秒调用update函数30次。
makeParticles();
// add the mouse move listener
document.addEventListener('mousemove', onMouseMove, false);
// 每秒渲染30次
setInterval(update, 1000/30);
其中的`update`函数如下:
function update() {
updateParticles();
// 从相机的视角渲染场景
renderer.render(scene, camera);
}
updateParticles
函数会在后面加以解释,它的作用是将粒子向前移动。
直到renderer.render()
方法调用之前,你是不会看见任何3D物体的。渲染器(renderer)会把所有的东西画到canvas上,它决定了场景中的物体在相机的视角看来是什么样子的。
粒子(Particles)
Three.js有三种主要类型的3D对象:三角形(triangles),直线(lines)和粒子(particles)。粒子表示的是3D空间中的一个点,因而最容易使用。它们可以被渲染成2D的图片,比如一个简单的圆或矩形,或是位图图片。关于粒子有一点很重要,它们从任何角度看起来都是一样的,当然根据距离的远近大小会发生变化。
创建粒子
// creates a random field of Particle object
function makeParticles() {
var particle, material;
// 将z坐标从-1000(最远处)逐步增加至1000(相机所在处)
// 每一个位置加入一个随机的粒子
for (var zpos = -1000; zpos < 1000; zpos += 20) {
// 创建一个粒子材质,向其传入颜色及我们定义的粒子渲染函数
material = new THREE.ParticleCanvasMaterial( {
// color: 0xffffff,
color: getRandomColor(),
program: particleRender
});
// 创建粒子
particle = new THREE.Particle(material);
// 赋给它一个位于-500至500之间的随机x和y值
particle.position.x = Math.random() * 1000 - 500;
particle.position.y = Math.random() * 1000 - 500;
particle.position.z = zpos;
// 将其放大一点
particle.scale.x = particle.scale.y = 10;
// 把它加入到场景中
scene.add(particle);
// 将粒子加入到我们的particles数组中
particles.push(particle);
}
}
在for循环中zpos以20为步长从-1000增加至1000。
在循环中,我们创建一个新的材质(material)然后新建一个粒子。粒子有一个position属性,它有x, y, z三个值。
我们给每一个粒子一个随机的x和y位置,将它的z位置设置为zpos。
接着将粒子加入到particles数组中,保证能够跟踪所有的粒子并在update循环中对它们进行操作。
创建粒子材质(particle material)
所有的3D对象都有材质对象,材质定义了它们是如何画出来的,颜色及透明度之类的属性。我们是这样定义的每个粒子的材质对象:
material = new THREE.ParticleCanvasMaterial( {
color: 0xffffff,
program: particleRender
});
three.js并没有内置圆形粒子材质,所以需要告诉它如何去画一个圆。我们是通过给particleRender传递必要的canvas绘图API来做到这一点的。
function particleRender(context) {
context.beginPath();
context.arc(0, 0, 1, 0, 2*Math.PI, true);
context.fill();
}
把一个函数传递给材质(material)似乎有点奇怪,但这实际上是一个非常灵活的系统。它获得了canvas上下文的引用,所以我们可以画出任何想要的形状。同时canvas的坐标系统将会根据粒子进行缩放和平移,因此我们只需要以起点(origin)为中心画图即可。
对于粒子的颜色,可以选取一个固定的颜色,也可以选取随机的颜色。
function getRandomColor() {
var r = 255*Math.random()|0,
g = 255*Math.random()|0,
b = 255*Math.random()|0;
// return 'rgb(' + r + ',' + g + ',' + b + ')';
return '0x' + parseInt(r, 16) + parseInt(g, 16) + parseInt( b, 16);
}
移动粒子
现在来看一下updateParticles函数,它将会在我们每个的更新周期中调用,就在我们进行渲染之前。
// 根据鼠标位置移动所有的粒子
function updateParticles() {
// 对每个粒子进行迭代处理
for (var i = 0; i < particles.length; i++) {
particle = particles[i];
// 根据mouseY值进行移动
particle.position.z += mouseY * 0.1;
// 如果粒子过近,将其移至后面
if (particle.position.z > 1000)
particle.position.z -= 2000;
}
}
鼠标越低,mouseY值越大,粒子移动速度越快。
最后的效果如图,上下移动鼠标,粒子移动速度会发生变化。
原文链接:http://www.wukai.me/2015/11/15/star-field/
Three.js入门——画星空(star field)的更多相关文章
- React.js入门笔记
# React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...
- 【JavaScript】——JS入门
结束XML之旅,開始JavaScript的学习,看视频.了解了她的前世今生,还是为她捏了把汗啊! 看了部分视 频了,简单的总结一下吧! JavaScript是什么? JavaScript是一种基于面向 ...
- d3.js 入门指南
说到数据可视化,我们会行到很多优秀的框架,像echarts.highcharts,这些框架很优雅,健壮,能满足我们对可视化的大部分需求,但是缺点也很明显,就是这些框架几乎是不可定制化的,当遇到特殊的需 ...
- Vue.js 入门:从零开始做一个极简 To-Do 应用
Vue.js 入门:从零开始做一个极简 To-Do 应用 写作时间:2019-12-10版本信息:Vue.js 2.6.10官网文档:https://cn.vuejs.org/ 前言 学习 Vue ...
- 《Three.js 入门指南》3.0 - 代码构建的最基本结构。
3.0 代码构建的最基本结构 说明: 我们必需首先知道,Three.js 的一些入门级概念: 我们需要知道,OpenGL 是一套三维实现的标准,为什么说是标准,因为它是跨平台,跨语言的.甚至CAD以及 ...
- 1. web前端开发分享-css,js入门篇
关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...
- Ember.js入门教程、博文汇总
第一章 对象模型 Ember.js 入门指南——类的定义.初始化.继承 Ember.js 入门指南——类的扩展(reopen) Ember.js 入门指南——计算属性(compute properti ...
- JS入门之ActiveXObject对象(转载)
JS入门之ActiveXObject对象 此对象提供自动化对象的接口. function ActiveXObject(ProgID : String [, location : String] ...
- Node.js 入门手册:那些最流行的 Web 开发框架
这篇文章与大家分享最流行的 Node.js Web 开发框架.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编 ...
随机推荐
- BZOJ 1426: 收集邮票 数学期望 + DP
Description 有n种不同的邮票,皮皮想收集所有种类的邮票.唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且 买到的邮票究竟是n种邮票中的哪一种是等概率的,概率均为1/n.但是由于凡凡 ...
- 【Shell编程】Shell程序设计
1.Shell简介 作为Linux灵感来源的Unix系统最初是没有图形化界面的,所有的任务都是通过命令行来实现的.因此,Unix的命令行系统得到了很大的发展,逐步成为一个功能强大的系统. Sh ...
- SSL/TLS 加密新纪元 - Let's Encrypt
转自: https://linux.cn/article-6565-1.html SSL/TLS 加密新纪元 - Let's Encrypt 根据 Let's Encrypt 官方博客消息,Let's ...
- 【Leetcode】【简单】【169求众数】【JavaScript】
题目 169. 求众数 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [ ...
- 获取url
首先要知道Location这个对象以及这个对象中的一些属性: href:设置或返回完整的url.如本博客首页返回http://www.cnblogs.com/wymninja/ host:设置或返回主 ...
- tween.js缓动(补间动画)
一.理解tween.js 如果看到上面的已经理解了,可以跳过下面的部分.下面为对Tween.js的解释 下面就介绍如何使用这个Tween了,首先b.c.d三个参数(即初始值,变化量,持续时间)在缓动开 ...
- 【ABCD组】Scrum meeting 5
前言 第5次会议在6月17日由组长在教9 405召开. 主要对下一步的工作进行说明安排,时长90min. 主要内容 分配下阶段任务,争取在这阶段完成软件的设计阶段 任务分配 姓名 当前阶段任务 贡献时 ...
- 《奋斗吧!菜鸟》 第八次作业:Alpha冲刺 Scrum meeting 1
项目 内容 这个作业属于哪个课程 任课教师链接 作业要求 https://www.cnblogs.com/nwnu-daizh/p/11012922.html 团队名称 奋斗吧!菜鸟 作业学习目标 A ...
- QT中tableview不能更新数据,why?
model->select(); //model->removeColumn(0);++++++++++++++++++++ //model->setHeaderData(model ...
- 【[Offer收割]编程练习赛15 C】过河问题
[题目链接]:http://hihocoder.com/problemset/problem/1516 [题意] [题解] 状态压缩DP+bfs 这个过河问题能用bfs来搞.涨知识了; 首先; 16个 ...