`
varying vec2 vUv;
varying vec3 vPosition;
void main(){
gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
vUv=uv;
vPosition=position;
const fragmentShader = `
uniform float uTime;
varying vec2 vUv;
vec3 background(vec2 uv){
float dist=length(uv-vec2(.5));
vec3 bg=mix(vec3(.3),vec3(.0),dist);
return bg;
void main(){
vec3 bg=background(vUv);
vec3 color=bg;
gl_FragColor=vec4(color,1.);
const geometry = new THREE.BoxGeometry(1, 1, 1)
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
uniforms: {
uTime: {
value: 0
const mesh = new THREE.Mesh(geometry, shaderMaterial)
scene.add(mesh)
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
requestAnimationFrame(render)
</script>
</body>
</html>
- 顶点着色器中。
projectionMatrix
是投影变换矩阵,modelViewMatrix
是相机坐标系的变换矩阵,position
顶点坐标,都是three.js
定义好的。 - 片元着色器中。通过
background
函数计算出当前顶点的颜色,交由片元自动计算各个顶点之间的渐变。
- 这是一个比较复杂的过程。本节只了解如何使用别人写好的公式绘制图形。
- 下面的操作都是在片元着色器中。
float sdBox(vec3 p,vec3 b){
vec3 q=abs(p)-b;
return length(max(q,0.))+min(max(q.x,max(q.y,q.z)),0.);
- 有了方块,就需要一个光线步进函数来展示它。
float rayMarch(vec3 ro,vec3 rd,float end,int maxIter){
float d0 = 0.;
for(int i=0;i<maxIter;i++){
vec3 pos=ro+d0*rd;
float ds=sdBox(pos,vec3(.3));
d0+=ds;
if(ds >= end || ds < 0.01){
break;
return d0;
void main(){
vec3 eye = vec3(0.,0.,2.5);
vec3 ray = normalize(vec3(vUv,-eye.z));
float end = 5.;
int maxIter=256;
float depth = rayMarch(eye,ray,end,maxIter);
if(depth < end){
vec3 pos = eye + depth * ray;
color = pos;
- 让方块动起来。
- 开始我们定义了
uTime
全局变量,通过修改它来实现旋转方块。 - 矩阵函数。
mat4 rotationMatrix(vec3 axis,float angle){
axis=normalize(axis);
float s=sin(angle);
float c=cos(angle);
float oc=1.-c;
return mat4(oc*axis.x*axis.x+c,oc*axis.x*axis.y-axis.z*s,oc*axis.z*axis.x+axis.y*s,0.,
oc*axis.x*axis.y+axis.z*s,oc*axis.y*axis.y+c,oc*axis.y*axis.z-axis.x*s,0.,
oc*axis.z*axis.x-axis.y*s,oc*axis.y*axis.z+axis.x*s,oc*axis.z*axis.z+c,0.,
0.,0.,0.,1.);
vec3 rotate(vec3 v,vec3 axis,float angle){
mat4 m=rotationMatrix(axis,angle);
return(m*vec4(v,1.)).xyz;
- 修改
rayMarch
函数,在加载方块之前先旋转方块。这里要注意rotate()
函数需要在rayMarch()
函数之前加载。
float rayMarch(vec3 ro,vec3 rd,float end,int maxIter){
vec3 pos=ro+d0*rd;
vec3 p1=rotate(pos,vec3(1.),uTime);
float ds=sdBox(p1,vec3(.3));
- 修改方块的位置。
vec2 centerUv(vec2 uv){
uv=2.*uv-1.;
float aspect=1;
uv.x*=aspect;
return uv;
vec2 cUv=centerUv(vUv);
vec3 ray=normalize(vec3(cUv,-eye.z));
- 本节是对
GLSL语言
的简单应用,通过各种公式使用着色器来绘制立方体。three.js
的源码也是在控制着色器,所以想要深入理解three.js
就必须要学会如何使用GLSL语言
。
简介着色器材质可以自定义几何体面的颜色。进一步学习后就会知道,three.js就是对GLSL语言进行了多方面的封装,下面我们就使用着色器语言来绘制一个正方体。开始绘制绘制一个有着色器材质的几何体<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <title>学习</title> </head> <body
使用HTML5和WebGL对Web的3D动画和可视化进行编程
这本书是关于什么的?
WebGL使在浏览器中创建3D图形成为可能,而不必使用Flash和Java之类的插件。 但是,对WebGL进行编程既困难又复杂。 使用Three.js,无需学习WebGL,就可以使用JavaScript以直观的方式创建精美的3D图形。 通过这本书,您将学习如何利用WebGL和现代浏览器的全部潜能,直接在浏览器中创建和制作精美的3D场景并为其设置动画。 它从Three.js中使用的基本概念和构建块开始。 从那以后,它将使用大量示例和代码示例来扩展这些主题。 您将学习使用材质和纹理从外部创建的模型创建或加载逼真的3D对象。 您将发现如何使用内置在相机控件中的Three.js轻松控制相机,这将使您能够在创建的3D场景中飞行或行走。 然后,您将
Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。你可以在它的主页上看到许多精彩的演示。不过,这款引擎目前还处在比较不成熟的开发阶段,其不够丰富的 API 以及匮乏的文档增加了初学者的学习难度(尤其是文档的匮乏)three.js的代码托管在github上面。
http://github.com/mrdoob/three.js/
我们来看实例吧
<!DOCTYPE html>
<meta charset="utf-8" />
<title></title>
</head>