Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Three.js教程(1):初识three.js

Three.js教程(1):初识three.js

作者头像
kai666666
发布于 2020-10-19 08:24:07
发布于 2020-10-19 08:24:07
23.5K015
代码可运行
举报
文章被收录于专栏:橙光笔记橙光笔记
运行总次数:15
代码可运行

今天开始我们进入一个新的世界,那就是3D世界。由于我自己也是刚接触到这块内容,所以如果文章中有问题,请尽快在文章最后的留言板中请指出。本教程有配套代码仓库,请点击https://github.com/KaiOrange/three.js-demo


为什么要使用three.js

要回答为什么要使用three.js?首先我们想想什么是three.js?官方给的简绍很简单:JavaScript 3D library,就是一个JavaScript的3D库。前端实现3D效果无非这么几种方式:

1.CSS 3D技术; 2.SVG; 3.WebGL技术; 4.Canvas或者图片等来模拟3D。

其中最后一种是用其他技术或方法去模拟3D效果,前3种才是浏览器真正意义上支持的3D技术。而three.js直接支持前3种渲染方式,可以看出three.js的强大。 大多情况下如果是为了展示3D的效果,那么直接用图片就可以了,如果要动起来的话,视频往往可以胜任。但是如果有交互视频就不行了,前端的3D技术弥补了视频的交互部分。而交互中逻辑性比较多,这样的话JavaScript来做会更有优势,所以WebGL技术就脱颖而出,首先我们来看一个WebGL的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!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>Document</title>
</head>
<body>
  <canvas id="webgl" width="500" height="500"></canvas>
  <script>
    var projectionMatrix = new Float32Array(
      [2.41421, 0, 0, 0,
      0, 2.41421, 0, 0,
      0, 0, -1.002002, -1,
      0, 0, -0.2002002, 0]);
    var modelViewMatrix = new Float32Array(
      [1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      0, 0, -3.333, 1]);

    // Create the vertex data for a square to be drawn
    function createSquare(gl) {
      var vertexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      var verts = [
        .5,  .5,  0.0,
        -.5,  .5,  0.0,
        .5, -.5,  0.0,
        -.5, -.5,  0.0
      ];
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
      var square = {buffer:vertexBuffer, vertSize:3, nVerts:4, primtype:gl.TRIANGLE_STRIP};
      return square;
    }
    function createShader(gl, str, type) {
      var shader;
      if (type == "fragment") {
          shader = gl.createShader(gl.FRAGMENT_SHADER);
      } else if (type == "vertex") {
          shader = gl.createShader(gl.VERTEX_SHADER);
      } else {
          return null;
      }
      gl.shaderSource(shader, str);
      gl.compileShader(shader);
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
          alert(gl.getShaderInfoLog(shader));
          return null;
      }
      return shader;
    }

  var vertexShaderSource =
    "attribute vec3 vertexPos;\n" +
    "uniform mat4 modelViewMatrix;\n" +
    "uniform mat4 projectionMatrix;\n" +
    "void main(void) {\n" +
    "   // Return the transformed and projected vertex value\n" +
    "   gl_Position = projectionMatrix * modelViewMatrix * \n" +
    "   vec4(vertexPos, 1.0);\n" +
    "}\n";

  var fragmentShaderSource =
    "void main(void) {\n" +
    "   // Return the pixel color: always output white\n" +
    "   gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
    "}\n";

    var shaderProgram, shaderVertexPositionAttribute, shaderProjectionMatrixUniform, shaderModelViewMatrixUniform;
    function initShader(gl) {
      // load and compile the fragment and vertex shader
      var fragmentShader = createShader(gl, fragmentShaderSource, "fragment");
      var vertexShader = createShader(gl, vertexShaderSource, "vertex");
      // link them together into a new program
      shaderProgram = gl.createProgram();
      gl.attachShader(shaderProgram, vertexShader);
      gl.attachShader(shaderProgram, fragmentShader);
      gl.linkProgram(shaderProgram);
      // get pointers to the shader params
      shaderVertexPositionAttribute = gl.getAttribLocation(shaderProgram, "vertexPos");
      gl.enableVertexAttribArray(shaderVertexPositionAttribute);

      shaderProjectionMatrixUniform = gl.getUniformLocation(shaderProgram, "projectionMatrix");
      shaderModelViewMatrixUniform = gl.getUniformLocation(shaderProgram, "modelViewMatrix");

      if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
          alert("Could not initialise shaders");
      }
    }
    function draw(gl, obj) {
      // clear the background (with black)
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      gl.clear(gl.COLOR_BUFFER_BIT);
      // set the vertex buffer to be drawn
      gl.bindBuffer(gl.ARRAY_BUFFER, obj.buffer);
      // set the shader to use
      gl.useProgram(shaderProgram);
      // connect up the shader parameters: vertex position and projection/model matrices
      gl.vertexAttribPointer(shaderVertexPositionAttribute, obj.vertSize, gl.FLOAT, false, 0, 0);
      gl.uniformMatrix4fv(shaderProjectionMatrixUniform, false, projectionMatrix);
      gl.uniformMatrix4fv(shaderModelViewMatrixUniform, false, modelViewMatrix);
      // draw the object
      gl.drawArrays(obj.primtype, 0, obj.nVerts);
    }

    window.onload = function (){
      var canvas = document.getElementById("webgl");
      var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
      gl.viewport(0, 0, canvas.width, canvas.height);
      var square = createSquare(gl);
      initShader(gl);
      draw(gl, square);
    }
  </script>
</body>
</html>

这段代码比较长,出来的效果很简单,只是一个小方块(只是一个正方形,还不是正方体)。具体效果如下:

我们来简单的看一下代码吧,代码中通过canvas.getContext("webgl")来获取到WebGL的上下文,对于稍微低版本的浏览器可以使用experimental-webgl来获取,还记得之前canvas吗?当时是通过2d来获取canvas的上下文对象。上述代码中,核心代码是initShader()方法,它初始化了着色器,我们这里用到了2个着色器:fragmentShader和vertexShader。正如他们的命名一样,第一个是片元着色器,第二个是顶点着色器。上述中还有2段String类型的代码,也就是字符串vertexShaderSource和字符串fragmentShaderSource的值,这两段代码是一种被称作GLSL ES的着色器语言(Shading Language),其实WebGL这一套都是来自于一种叫做OpenGL的技术,完全可以理解为WebGL提供了一层API来调用系统底层的OpenGL。也就是说WebGL把字符串的GLSL ES代码变成系统可以执行的OpenGL的代码,期间经过compileShader(),shaderSource(),compileShader(),attachShader()linkProgram()等多个JS方法。

到这里估计你也头大了,什么着色器,什么GLSL ES,什么Shader,把人搞的痛苦地!!!别急,正因为原生的WebGL这么晦涩难懂,所以才有了我们的主角three.js。现在你可以忘掉上面的内容,因为three.js封装的特别好,根本看不到任何WebGL的影子,你再也不需要去了解什么着色器,更不用写GLSL ES,我们先来看一个更高级且更简单的three.js的例子。

初识three.js

three.js可以使用模块化引入,当然也可以直接用script标签来引入。在具体项目中完全可以搭配React和Vue这样的MVVM框架,这里图简单就直接用script标签来引入。当写这篇文章的时候three.js的最新版本是r111,你可以在这里查看最新的版本。

我们首先来运行一下官方给的例子,源代码点击这里

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!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>Document</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>
  <script type="text/javascript" src="../node_modules/three/build/three.js"></script>
  <script type="text/javascript">
    var camera, scene, renderer;
    var geometry, material, mesh;

    function init() {
      camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
      camera.position.z = 1;

      scene = new THREE.Scene();

      geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
      material = new THREE.MeshNormalMaterial();
      mesh = new THREE.Mesh( geometry, material );
      scene.add( mesh );

      renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setSize( window.innerWidth, window.innerHeight );
      document.body.appendChild( renderer.domElement );
    }

    function animate() {
      requestAnimationFrame( animate );
      mesh.rotation.x += 0.01;
      mesh.rotation.y += 0.02;
      renderer.render( scene, camera );
    }

    init();
    animate();
  </script>
</body>
</html>

代码非常少,出来的效果却是很惊艳:

我们来分析一下官方例子的代码,首先创建了一个相机(THREE.PerspectiveCamera),它描述了眼睛看的方向;然后创建了一个场景(THREE.Scene);再之后把小物块(THREE.Mesh)放在场景上;最后渲染出来(THREE.WebGLRenderer)的DOM元素(canvas)追加到body上。animate函数的作用是启动动画,动画的原理就是每次改变一点点,然后重新渲染,这跟Canvas是一模一样的,不了解这块的同学可以看看这篇。 最后我们给出一张图来结束本章,这个就是three.js的基本模式,其中光线我们还没有涉及到:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-12-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
WebGL画点程序v2
本文程序实现画一个点的任务,如下图。其中,点的位置坐标由Javascript传到着色器程序中,而不是直接给定(“硬编码”)在顶点着色器中。
步行者08
2018/10/09
7370
WebGL画点程序v1
本文程序实现画一个点的任务,如下图。其中,点的位置直接给定(“硬编码”)在顶点着色器中。
步行者08
2018/10/09
5820
【愚公系列】2022年09月 微信小程序-WebGL画渐变色正方形
在现实中webgl的用途很多,比如医院运维网站,地铁运维网站,海绵城市,可以以三维网页形式展示出现实状态。
愚公搬代码
2022/09/30
5910
【愚公系列】2022年09月 微信小程序-WebGL画渐变色正方形
WebGL画点程序v3
本文程序实现画一个点的任务,如下图。其中,点的颜色由Javascript传到片元着色器程序中。
步行者08
2018/10/09
7720
【愚公系列】2022年09月 微信小程序-WebGL立体图形的绘制
在现实中webgl的用途很多,比如医院运维网站,地铁运维网站,海绵城市,可以以三维网页形式展示出现实状态。
愚公搬代码
2022/09/28
7870
【愚公系列】2022年09月 微信小程序-WebGL立体图形的绘制
WebGL三角形平移变换
本程序实现一个三角形的平移变换任务,最终效果如下图。 整个程序包含两个文件,分别是: 1. TranslatedTriangle.html <!DOCTYPE HTML PUBLIC "-//W3C/
步行者08
2018/10/09
6260
【WebGL】初探WebGL,我了解到这些
WebGL基于OpenGL ES(嵌入式系统) 一种广泛用于在各种平台上渲染2D和3D图形的标准。它允许开发人员使用JavaScript与用户设备的GPU(图形处理单元)交互,实现硬件加速渲染。
且陶陶
2023/10/16
4440
【WebGL】初探WebGL,我了解到这些
WebGL三角形旋转变换
本程序实现一个三角形的旋转变换任务,最终效果如下图。 整个程序包含两个文件,分别是: 1. RotatedTriangle.html <!DOCTYPE HTML PUBLIC "-//W3C//DT
步行者08
2018/10/09
1.2K0
【愚公系列】2022年09月 微信小程序-WebGL动画的使用
在现实中webgl的用途很多,比如医院运维网站,地铁运维网站,海绵城市,可以以三维网页形式展示出现实状态。
愚公搬代码
2022/09/28
1.2K0
【愚公系列】2022年09月 微信小程序-WebGL动画的使用
【愚公系列】2022年09月 微信小程序-WebGL纹理材质的使用
在现实中webgl的用途很多,比如医院运维网站,地铁运维网站,海绵城市,可以以三维网页形式展示出现实状态。
愚公搬代码
2022/09/28
9671
【愚公系列】2022年09月 微信小程序-WebGL纹理材质的使用
【愚公系列】2022年09月 微信小程序-WebGL画正方形
WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。–百度百科
愚公搬代码
2022/10/05
9030
【愚公系列】2022年09月 微信小程序-WebGL画正方形
高冷的 WebGL
在上一篇文章中,我给大家分享了,如何能快速入门Threejs。Threejs是一个用于在浏览器中绘制3D图形的JS库,其底层实际是对浏览器提供的WebGL Api进行了封装。作为一个好奇宝宝,看到了T
周明礼
2017/05/17
5.4K0
高冷的 WebGL
WebGL基础笔记
片元着色器(Fragment Shader):顶点之间的轮廓中的所有像素都会经过片元着色器处理。(并行处理)
赤蓝紫
2023/01/02
1.2K0
WebGL基础笔记
three.js 着色器材质之初识着色器
说起three.js,着色器材质总是绕不过的话题,今天郭先生就说一说什么是着色器材质。着色器材质是很需要灵感和数学知识的,可以用简短的代码和绘制出十分丰富的图像,可以说着色器材质是脱离three.js的另一块知识,因此它十分难讲,我们只能在一个一个案例中逐渐掌握着色器语言的使用技巧。
郭先生的博客
2020/08/31
3.2K0
three.js 着色器材质之初识着色器
【实战】用 WebGL 创建一个在线画廊
本文中所用到的大多数套路也可以用在其他 WebGL 库中,例如 Three.js[2] 或 Babylon.js[3] 中,但是需要一些小小的调整。
疯狂的技术宅
2021/03/16
3.1K0
three.js中的矩阵变换(模型视图投影变换)
我在《WebGL简易教程(五):图形变换(模型、视图、投影变换)》这篇博文里详细讲解了OpenGL\WebGL关于绘制场景的图形变换过程,并推导了相应的模型变换矩阵、视图变换矩阵以及投影变换矩阵。这里我就通过three.js这个图形引擎,验证一下其推导是否正确,顺便学习下three.js是如何进行图形变换的。
charlee44
2020/05/08
6.1K0
WebGL 概念和基础入门
本文首发于政采云前端团队博客:WebGL 概念和基础入门 https://www.zoo.team/article/webglabout
政采云前端团队
2021/08/12
4.4K0
几个简单的小例子手把手带你入门webgl
各位同学们大家好,又到了周末写文章的时间,之前群里有粉丝提问, 就是shader不是很理解。然后今天他就来了, 废话不多说,读完今天的这篇文章你可以学到以下几点:
coder_koala
2021/09/18
1.4K0
几个简单的小例子手把手带你入门webgl
WebGL基础教程:第一部分
WebGL是一种基于OpenGL的浏览器内置3D渲染器,它可以让你在HTML5页面中直接显示3维内容。 在本教程中,我会介绍你使用此框架所需的所有基础内容。
前端达人
2019/01/12
2.8K0
WebGL基础教程:第一部分
Three.js系列: 在元宇宙看电影,享受 VR 视觉盛宴
本文 gihtub 地址: https://github.com/hua1995116/Fly-Three.js
秋风的笔记
2022/12/05
3.2K0
Three.js系列: 在元宇宙看电影,享受 VR 视觉盛宴
相关推荐
WebGL画点程序v2
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验