前往小程序,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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
EasyCVR级联到上级平台后, 上级平台不显示通道是什么原因?
EasyCVR视频融合平台可在复杂的网络环境中,将各种品牌及类型的前端监控等设备进行统一汇聚、整合、集中管理。平台支持协议包括:国标GB/T28181、RTMP、RTSP/Onvif等协议,以及海康大华的私有协议与SDK。在视频功能上,平台可提供直播、录像、告警、级联、对讲等功能。
TSINGSEE青犀视频
2022/10/21
3660
EasyCVR国标协议接入的通道,在线通道部分播放异常是什么原因?
EasyCVR平台支持多协议、多类型的设备接入,拥有灵活丰富的视频能力,可实现的功能包括视频实时监控直播、云端录像、云存储、回放与检索、智能告警、视频快照、视频转码与分发、平台级联等。平台支持设备通过国标GB28181、RTMP、RTSP/Onvif、海康SDK、大华SDK、Ehome等协议接入,对外可分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。
TSINGSEE青犀视频
2022/06/24
3230
智能安防视频平台EasyCVR出现通道列表为空情况的原因是什么?
EasyCVR平台基于云边端一体化架构,支持将分散的视频资源统一汇聚与管理,实现对视频资源的处理与分发、直播、录像、回看、存储、智能分析等。近期我们正在对EasyCVR进行新功能的拓展,比如服务器集群、视频轮巡、H.265转码H.264、电子地图与轨迹跟踪等等,欢迎大家关注我们的更新。
TSINGSEE青犀视频
2022/07/26
3260
如何解决EasyCVR视频融合平台视频列表通道叠加情况?
EasyCVR支持海量视频汇聚管理,可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、智能分析等视频服务。平台支持设备通过国标GB28181、RTMP、RTSP/Onvif、海康SDK、大华SDK、Ehome等协议接入,对外可分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。
TSINGSEE青犀视频
2022/09/16
3580
视频融合平台EasyCVR设备管理分页显示有异常,是什么原因?
EasyCVR视频融合云服务支持多协议、多类型设备的接入,包括国标GB/T28181、RTMP、RTSP/Onvif协议,以及厂家私有协议,如:海康SDK、大华SDK、海康Ehome等。平台可对前端接入的设备进行统一管理,并能支持采用设备树对设备进行分组、分级、用户与角色权限管理,可支持设备状态监测、云端运维等功能,实现对海量接入资源的集中控制与权限分配。
TSINGSEE青犀视频
2022/09/28
2430
EasyCVR使用大华SDK接入时录像显示失败是什么原因?该如何解决?
EasyCVR视频融合云服务支持多协议、多类型设备的接入,包括国标GB/T28181、RTMP、RTSP/Onvif协议,以及厂家私有协议,如:海康SDK、大华SDK、海康Ehome等。平台可对前端接入的设备进行统一管理,并能支持采用设备树对设备进行分组、分级、用户与角色权限管理,可支持设备状态监测、云端运维等功能,实现对海量接入资源的集中控制与权限分配。
TSINGSEE青犀视频
2022/10/31
3990
EasyCVR级联向上级注册时,上级平台通道显示为0是什么原因?
EasyCVR具备强大的视频接入、汇聚与管理、视频分发、设备管理、用户及角色权限管理等能力。平台可对前端接入的设备进行统一集中管理,并能支持采用设备树对设备进行分组、分级管理、设备状态监测、云端运维等,实现对海量接入资源的集中控制与权限分配。平台可将接入的流媒体进行处理、转码、分发、分析等,可分发的视频流包括RTSP、RTMP、FLV、HLS、WebRTC等格式。
TSINGSEE青犀视频
2022/08/30
6310
AI云边端EasyCVR平台新功能解析:支持为角色选择多级分组
EasyCVR平台可支持多类型设备、多协议方式接入,具体包括:国标GB28181协议、RTMP、RTSP/Onvif、海康Ehome,以及海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石SDK等,可覆盖市面上绝大多数的视频源设备。平台基于云边端协同架构,可对前端接入设备进行统一管理,并能支持采用设备树对设备进行分组、分级管理,支持设备状态监测、云端运维等功能,实现对海量接入资源的集中控制与权限分配。
TSINGSEE青犀视频
2022/11/08
5070
下级平台级联安防视频汇聚融合EasyCVR平台,层级显示不正确是什么原因?
视频汇聚平台安防监控EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。
TSINGSEE青犀视频
2023/07/28
1860
设备通过海康ehome接入到EasyCVR后,通道数量显示不全是什么原因?
EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。
TSINGSEE青犀视频
2023/06/28
2250
EasyCVR添加RTMP_PUSH通道与RTSP通道名重复,系统提示推流名重复是什么原因?
EasyCVR平台可拓展性强、部署轻松、视频能力丰富,支持海量视频设备接入、视频汇聚与管理、转码与分发、告警上报、平台级联、智能分析等等。平台采用设备树对设备进行分组分级管理,对整合的视频监控资源的应用需求给予相应的操作权限,实现视频监控资源的最大化应用。
TSINGSEE青犀视频
2022/08/11
2760
EasyCVR视频广场模块分组列表中,点击设备提示“通道未开启”是什么原因?
EasyCVR平台支持海量视频汇聚管理,能兼容多类型的设备接入,可覆盖市面上大多数的视频源设备,包括各种IPC、NVR、视频服务器、单兵设备、编码器设备等。平台可对前端接入设备进行统一管理,并能支持采用设备树对设备进行分组、分级管理,可支持设备状态监测、云端运维等功能,实现对海量接入资源的集中控制与权限分配。
TSINGSEE青犀视频
2022/09/23
2700
AI智慧安监平台EasyCVR调用编辑通道接口,录像计划却被删除是什么原因?
EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。为了便于用户集成与二次开发的需求,我们也提供了丰富的API接口供大家使用,有需要的用户可以查看官方的API文档库。
TSINGSEE青犀视频
2023/05/15
1900
双网卡设备通过HIKSDK接入EasyCVR平台显示离线是什么原因?
EasyCVR视频融合平台基于云边端协同架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理,可支持多协议接入,包括市场主流标准协议与厂家私有协议及SDK,如:国标GB28181、RTMP、RTSP/Onvif、海康Ehome、海康SDK、宇视SDK等(具体见下图)。平台能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。
TSINGSEE青犀视频
2023/03/31
4730
EasyCVR升级版本后如何保证录像平稳播放?
EasyCVR视频融合云平台可支持多协议、多设备接入,包括国标GB28181、RTMP、RTSP/Onvif、海康SDK、大华SDK、Ehome等协议,同时也能分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。平台兼容性强、开放度高,功能可灵活拓展,也支持MySQL数据库。
TSINGSEE青犀视频
2022/10/28
2540
EasyCVR分组列表出现分组通道为空现象,是什么原因?
EasyCVR视频融合云服务支持海量视频汇聚管理,能兼容多类型的设备接入,平台可对前端接入设备进行统一管理,并能支持采用设备树对设备进行分组、分级、用户与角色权限管理,可支持设备状态监测、云端运维等功能,实现对海量接入资源的集中控制与权限分配。
TSINGSEE青犀视频
2022/09/27
5280
EasyCVR级联EasyCVR出现通道频繁掉线是什么原因?
EasyCVR作为TSINGSEE青犀视频开发的视频融合云服务平台,不仅支持国标GB28181协议、RTSP/Onvif、RTMP等标准协议,还支持HIKSDK、大华SDK、海康Ehome等厂家私有协议与SDK。平台支持海量视频汇聚管理,可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、智能分析等视频服务。比如通过级联功能,EasyCVR可以将平台通道通过国标协议接入到上级平台,实现资源的有效共享和互通。
TSINGSEE青犀视频
2022/06/09
3380
AI智能安防监控EasyCVR视频融合平台播放鉴权功能的介绍及配置
EasyCVR视频融合平台基于云边端协同架构,支持海量视频汇聚管理,在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。平台可支持多协议接入,包括市场主流标准协议与厂家私有协议及SDK,如:国标GB28181、RTMP、RTSP/Onvif、海康Ehome、海康SDK、宇视SDK等(具体见下图)。
TSINGSEE青犀视频
2023/04/11
5200
EasyCVR视频融合平台Ehome巡检机制介绍
EasyCVR具备较强的视频能力,可支持海量设备接入、汇聚与管理、视频监控、视频录像、云存储、回放与检索、智能告警、平台级联等功能。平台可支持多协议接入,包括市场主流标准协议(国标GB/T28181协议、RTMP、RTSP/Onvif)与厂家私有协议和SDK(海康Ehome、海康SDK、大华SDK、华为SDK、宇视SDK、乐橙SDK、萤石SDK)等,可覆盖市面上大多数的视频源设备。
TSINGSEE青犀视频
2023/02/09
4480
EasyCVR级联时,上级平台云台控制无响应是什么原因?
EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。平台可实现的视频能力有:视频监控直播、云端录像、云存储、录像检索与回看、云台控制、智能告警、平台级联、集群、电子地图、H.265视频自动转码、智能分析等。
TSINGSEE青犀视频
2023/06/02
1740
推荐阅读
EasyCVR级联到上级平台后, 上级平台不显示通道是什么原因?
3660
EasyCVR国标协议接入的通道,在线通道部分播放异常是什么原因?
3230
智能安防视频平台EasyCVR出现通道列表为空情况的原因是什么?
3260
如何解决EasyCVR视频融合平台视频列表通道叠加情况?
3580
视频融合平台EasyCVR设备管理分页显示有异常,是什么原因?
2430
EasyCVR使用大华SDK接入时录像显示失败是什么原因?该如何解决?
3990
EasyCVR级联向上级注册时,上级平台通道显示为0是什么原因?
6310
AI云边端EasyCVR平台新功能解析:支持为角色选择多级分组
5070
下级平台级联安防视频汇聚融合EasyCVR平台,层级显示不正确是什么原因?
1860
设备通过海康ehome接入到EasyCVR后,通道数量显示不全是什么原因?
2250
EasyCVR添加RTMP_PUSH通道与RTSP通道名重复,系统提示推流名重复是什么原因?
2760
EasyCVR视频广场模块分组列表中,点击设备提示“通道未开启”是什么原因?
2700
AI智慧安监平台EasyCVR调用编辑通道接口,录像计划却被删除是什么原因?
1900
双网卡设备通过HIKSDK接入EasyCVR平台显示离线是什么原因?
4730
EasyCVR升级版本后如何保证录像平稳播放?
2540
EasyCVR分组列表出现分组通道为空现象,是什么原因?
5280
EasyCVR级联EasyCVR出现通道频繁掉线是什么原因?
3380
AI智能安防监控EasyCVR视频融合平台播放鉴权功能的介绍及配置
5200
EasyCVR视频融合平台Ehome巡检机制介绍
4480
EasyCVR级联时,上级平台云台控制无响应是什么原因?
1740
相关推荐
EasyCVR级联到上级平台后, 上级平台不显示通道是什么原因?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验