当我们谈论3D可视化时,我们在谈论什么(一)?

WebGL

简介:WebGL(全写Web Graphics Library)是一种3D绘图协议,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0(OpenGL for Embedded Systems,OpenGL嵌入式版本,针对手机、游戏机等设备相对较轻量级的版本)结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。

Three.js

简介:Three.js是WebGL的JavaScript 3D库,其对WebGL提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本,成为前端开发者完成3D绘图的得力工具。

three.js官方文档 :threejs.org/

three.js中文文档 : www.webgl3d.cn/

一、threejs三大组件(场景-scene,相机-camera,渲染器-renderer)

场景(Scenes)

场景是所有物体的容器,场景只有一种。

场景的构造函数是:

csharp 复制代码
var scene = new THERR.Scene()

Fog(线性雾):

ini 复制代码
scene.fog = new THREE.Fog(0xcce0ff, 10, 500)

照相机(Cameras)

定义了三维空间到二维屏幕的投影方式,投影方式主要分为正交投影和透视投影。

1.正交投影:正交投影照相机获得的结果对于在三维空间内平行的线,投影到二维空间中也一定是平行的。

2.透视投影:透视投影照相机获得的结果是类似人眼在真实世界中看到的有"近大远小"的效果。

一般说来,对于制图、建模软件通常使用正交投影,这样不会因为投影而改变物体比例;而对于其他大多数应用,通常使用透视投影,因为这更接近人眼的观察效果,以下详细介绍透视投影。

透视投影照相机(Perspective Camera)的构造函数是:

csharp 复制代码
var camera = new THREE.PerspectiveCamera(fov, aspect, near, far)

让我们通过一张透视照相机投影的图来了解这些参数。

透视图中,灰色的部分是视景体,是可能被渲染的物体所在的区域,在该视景体以外的物体将不会被渲染。

fov是视景体竖直方向上的张角(是角度制而非弧度制),如侧视图所示。

aspect等于width / height,是照相机水平方向和竖直方向长度的比值,通常设为Canvas的横纵比例。

near照相机到视景体最近的距离,为正值。

far照相机到视景体最远的距离,为正值。

渲染器(Renderers)

渲染器的作用就是将相机拍摄出的画面在浏览器中呈现出来。渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。three.js中有很多种类的渲染器,例如webGLRenderer、canvasRenderer、SVGRenderer,通常使用的是webGLRenderer渲染器。 webGLRenderer渲染器的构造函数是:

ini 复制代码
renderer = new THERR.WebGLRenderer()

创建完渲染器之后,需要调用render方法将之前创建好的场景和相机相结合从而渲染出来,即调用渲染器的render方法:

scss 复制代码
复制代码
renderer.render(scene,camera)

了解了three.js完成3D绘图的三大要素之后,便可以在页面中创建场景,并利用相机将场景渲染到网页上。

首先需要下载three.js库,并引用到自己的代码中,以下为三种引入方式,选择合适的方式在自己的项目中。

javascript 复制代码
<script src="lib/three.js"></script>  //ES5
const THREE=require('three')  //CommonJS/AMD
import * as THREE from 'three'   //ES6
javascript 复制代码
复制代码
// 创建场景
var scene = new THREE.Scene(); 
// 创建透视相机
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 
// 创建一个 WebGL 渲染器
var renderer = new THREE.WebGLRenderer({
       alpha: true,// 默认情况下为黑色场景,此处设置为透明(即白色场景)
}); 
// 设置渲染器为全屏
renderer.setSize(window.innerWidth, window.innerHeight); 
// 添加到网页中
document.body.appendChild(renderer.domElement);

完成上述各个步骤之后,我们在网页上看到的只有一块静态的白色场景,看不到任何东西,接下来通过一些基础图像的学习和了解,以呈现一些图形效果。

二、图像的表示

绘制的前期准备工作已经做完,接下来要做的就是把想要绘制的物体添加到场景中。在计算机世界中,3D世界是由点组成,两个点能够组成一条直线,三个不在一条直线上的点就能够组成一个三角面片,无数个三角面片就能够组成各种各样形状的物体,通常把这种网格模型叫做Mesh模型。Mesh模型是三维开发中使用的最为广泛的型。

Geometries(几何图形)

three.js给出了很多方法去生成固定的网格形状,比如长方体(BoxGeometry)、球体(SphereGeometry)、圆形(CircleGeometry)等等。还有根据具体坐标生成具体形状的方法,可以借助第三方建模软件(SketchUp)建模之后导入,目前支持的模型格式有.obj(最常用),.dae,.ctm,.ply,.stl,.wrl,.vtk等。Three.js有一系列支持外部导入文件的函数,是在three.js库之外的,使用前需要单独下载。(例如:OrbitControls-控制器、OBJLoader-加载.obj 文件、MTLLoader-加载.mtl文件)。

Materials(材质)

three.js给出了很多种直接生成材质的方法,其中比较常用的有MeshBasicMaterial(对光照无感,给几何体一种简单的颜色或显示线框),MeshLambertMaterial(对光照有反应,无光源则不会显示,用于创建暗淡的不发光的物体)、MeshPhongMaterial(对光照有反应,无光源不会显示,用于创建金属类米昂凉的物体)等等。物体之所以能被人眼看见,一种是它自身的材料就能发光,不需要借助外界光源;另一种是自身材料不发光,需要反射环境中的光。对于自身不发光的物体,需要个场景添加光源从而达到可视的效果。

Lights(灯光)

three.js中可以创建出很多不同类型的光源,比如环境光AmbientLight(它的颜色会添加到整个场景和所有对象的当前颜色上),点光源PointLight(这种光源放出的光线来自同一点,且辐射方向四面八方,如蜡烛发出的光),方向光DirectionalLight(也称作无限光,从这种光源发出的光线可以看做是平行的,如太阳光),聚光灯SpotLight(这种光源的光线从一个椎体中射出,在被照射的物体上产生聚光的效果,如手电筒发出的光。)有光源就缺少不了阴影,在Three.js中,能形成阴影的光源只有DirectionalLight和SpotLight;而相对地,能表现阴影效果的材质只有LambertMaterial和PhongMaterial。three.js中渲染阴影的开销比较大,所以默认物体是没有阴影的,需要单独开启。开启阴影的方法:

  • 将渲染器的shadowMapEnabled属性设置为true(告诉渲染器可以渲染隐形)
  • 将物体及光源的castShadow属性设置为true(告诉物体及光源可以透射阴影)
  • 将接收该阴影的物体的receiveShadow属性设置为true(告诉物体可以接收其他物体的阴影)

在了解了关于图形的基本知识之后,在上面的代码的基础上添加简单图像。

scss 复制代码
var geometry = new THREE.BoxGeometry(1,1,1); // 创建一个长宽高都为1个单位的立方体
var material = new THREE.MeshBasicMaterial({color: 0x00ff00}); // 创建材质,对光照无感
var cube = new THREE.Mesh(geometry, material); // 创建一个立方体网格(mesh),将材质包裹在立方体上
scene.add(cube); // 将立方体网格添加到场景中

camera.position.z = 5; // 指定相机位置
function render() {
requestAnimationFrame(render); // 让浏览器执行参数中的函数,不断循环(浏览器一个新的API)
renderer.render(scene, camera); // 结合场景和相机进行渲染,即用摄像机拍下此刻的场景
}
render();

render()函数中添加以下代码使上面再场景中添加的正方体运动起来。

ini 复制代码
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;

Controls(控制器)

轨道控制插件OrbitControls.js可以实现场景用鼠标交互,让场景动起来,控制场景的旋转、平移和缩放。由于OrbitControls.js是一个插件,所以在three.js 中使用时,需要单独引入该文件。

ini 复制代码
复制代码
controls = new THREE.OrbitControls(camera);// 初始化控制器
controls.target.set(0, 0, 0);// 设置控制器的焦点,使控制器围绕这个焦点进行旋转
controls.minDistance = 80;// 设置移动的最短距离(默认为零)
controls.maxDistance = 400;// 设置移动的最长距离(默认为无穷)
controls.maxPolarAngle = Math.PI / 3;//绕垂直轨道的距离(范围是0-Math.PI,默认为Math.PI)
controls.update();// 照相机转动时,必须更新该控制器

配置该插件之后实现的效果:

操控 效果
按住鼠标左键并移动 摄像机围绕场景中心旋转
转动鼠标滑轮或按住中键并移动 放大或缩小
按住鼠标右键并移动 在场景中平移
上、下、左、右方向键 在场景中平移

Loaders(加载器)

用来加载不同格式的文件,主要介绍 在Three.js中,要加载三维模型文件,可以使用GLTF格式。GLTF是一种基于JSON的开放标准,用于3D模型的交换和运行时加载。本篇文章将详细讲解如何使用Three.js加载GLTF模型。

1. 下载GLTF模型

在开始之前,请确保您已经有一个GLTF模型文件。您可以从三维模型网站或者其他资源库中下载GLTF模型文件。例如,您可以在Sketchfab上找到数百万个免费和付费的3D模型,这些模型都支持GLTF格式。

2. 加载GLTF模型

下面是加载GLTF模型的基本步骤:

  1. 首先,我们需要创建一个场景(scene)和相机(camera)。
ini 复制代码
ini
复制代码
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
  1. 然后,我们需要添加一个渲染器(renderer)并设置它的尺寸。
ini 复制代码
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
  1. 接着,我们需要使用GLTFLoader()函数加载GLTF模型,并给它提供一个回调函数来处理加载完成后的动作。
javascript 复制代码
var loader = new THREE.GLTFLoader();
loader.load('model.gltf', function (gltf) {
    var model = gltf.scene;
    scene.add(model);
}, undefined, function (error) {
    console.error(error);
});

在上述代码中,GLTFLoader()函数会加载'model.gltf'文件,并在加载完成后将模型添加到场景中。如果加载失败,则回调函数将打印错误信息。

  1. 最后,我们需要循环渲染场景,使3D模型得以显示。
scss 复制代码
function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}
render();

上述render()函数使用了requestAnimationFrame()函数来持续渲染场景,从而使3D模型得以出现在屏幕中。

3. 添加光源

如果模型缺乏照明效果,则可能看起来非常笨拙和不真实。因此,我们需要向场景添加几个光源。

例如:

ini 复制代码
var ambientLight = new THREE.AmbientLight( 0xffffff, 0.5 );
scene.add( ambientLight );

var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
scene.add( directionalLight );

上述代码添加了一个环境光和一个定向光源。环境光将场景中的所有物体都照亮,而定向光源则模拟了阳光照射的效果,可以产生更加真实的阴影和高光效果。

4. 动画控制

如果模型具有动画效果,则可以使用Three.js提供的AnimationMixer()AnimationClip()函数控制它。

例如:

ini 复制代码
ini
复制代码
var mixer = new THREE.AnimationMixer(model); // model为之前加载的模型
var clips = gltf.animations;
clips.forEach( function ( clip ) {
    mixer.clipAction( clip ).play();
});

上述代码将导入GTLF模型的所有动画,并通过mixer.clipAction()函数使其播放。

Textures(纹理)

纹理是一个2D图片(甚至也有1D和3D的纹理),它可以用来添加物体的细节;可以想象纹理是一张绘有砖块的纸,无缝折叠贴合到你的3D的房子上,这样你的房子看起来就像有砖墙外表了。

ini 复制代码
复制代码
var textureCube = new THREE.CubeTextureLoader().load(urls);
scene.background = textureCube;

模型格式

在three.js中,主流的模型格式主要包括以下几种:

  1. glTF (GL Transmission Format)

    • 特点:开放标准的3D文件格式,以JSON格式(.gltf)或二进制格式(.glb)存储模型信息。
    • 优势:轻量级、高效,支持几何形状、材质、动画和场景信息等,并优化了应用程序读取效率和减少渲染模型的运行时间。
    • 备注:three.js官方推荐使用的格式,广泛应用于3D内容的高效传输和加载。
  2. FBX (Autodesk Filmbox)

    • 特点:由Autodesk开发的通用3D模型格式,支持复杂的3D模型、动画和骨架。
    • 优势:广泛兼容性,尤其在Max、Maya、Softimage等软件间进行模型、材质、动作和摄影机信息的互导。
    • 备注:商业格式,尤其在Autodesk家族的软件中兼容最好。
  3. OBJ (Wavefront Object)

    • 特点:广泛使用的3D模型格式,保存3D模型的几何形状、材质和纹理信息。
    • 优势:简单直观,易于理解和使用。
    • 备注:通常与MTL(材质库)文件一起使用,以描述模型的材质属性。
  4. STL (Stereolithography)

    • 特点:常用的3D打印文件格式,将3D模型表示为一系列平面三角形。
    • 优势:用于描述3D物体的表面形状,尤其适用于3D打印。
    • 备注:不直接包含材质和动画信息。
  5. Collada (COLLAborative Design Activity)

    • 特点:用于交换3D模型和场景数据的开放标准格式。
    • 优势:包含几何形状、材质、动画、光照和物理特性等信息。
    • 备注:虽然较旧,但仍然是跨平台3D格式的一种选择。

这些格式在three.js中都有较好的支持和应用,每种格式都有其特定的应用场景和优势。根据项目的具体需求和目标,可以选择合适的模型格式进行使用。同时,three.js也支持通过自定义加载器来扩展对其他格式的支持。

ps:

1:为什么要用这些模型 而不是用three.js 直接开发3D?

使用已经建模的模型文件(如glTF格式)而不是直接在Three.js中编程创建模型,有几个主要的优点:

  1. 节省时间和资源:使用建模软件(如Blender、Maya等)创建复杂的3D模型通常比在Three.js中编程创建要快得多。专业的建模工具提供了丰富的工具和功能,可以轻松地创建复杂的几何体、设置材质、添加动画等,这些是用Three.js直接编写代码难以实现的。
  2. 专业的设计和质量:建模软件由专业的3D艺术家和设计师使用,他们可以创建高质量、逼真的模型和场景。这些模型经过精心设计和优化,可以提供更好的视觉效果和性能表现,而不需要开发人员从头开始编写和优化每一个细节。
  3. 标准化和复用:glTF作为一种通用的3D模型格式,可以在多个平台和应用程序之间进行交换和共享。这意味着你可以使用来自不同来源的现成模型,避免重复工作并节省开发时间。
  4. 分工合作:在大型项目中,通常会有专门的团队负责建模和设计,而另一些团队负责实现和集成。使用标准化的模型格式可以促进团队之间的协作和沟通。

虽然Three.js提供了强大的API来动态地创建和操作3D对象,但直接在代码中创建复杂的模型通常需要更多的时间和专业知识。因此,将建模和编程分开,使用现成的模型文件可以在开发过程中提供更高效和专业的解决方案。

2:为什么PCD不是主流模型?

PCD不是three.js中的主流模型格式。虽然PCD(Point Cloud Data)是一种用于存储点云数据的格式,在计算机视觉和图形学中有其特定的应用场景,但在three.js中,它并不是被广泛支持的主流模型格式。

以下是对PCD格式和three.js主流模型格式的详细解释:

  1. PCD格式

    • PCD是一种由Eastman Kodak开发的图片储存格式,主要用于在CD-ROM上保存图片。它支持24位颜色,最大的图象像素是2048*3072。PCD格式通常用于存储和处理点云数据,这在三维重建、机器人视觉等领域中非常有用。
    • 然而,在three.js中,PCD并不是一种直接支持的格式。虽然可以通过编写自定义的加载器来加载PCD文件,但这需要额外的开发工作,并且可能不如使用three.js直接支持的格式那样方便和高效。
  2. three.js的主流模型格式

    • three.js主要支持glTF(GL Transmission Format)作为3D模型的格式。glTF是一种开放标准的3D文件格式,旨在提高3D内容的传输效率。它支持几何形状、材质、动画和场景信息等,并且具有广泛的工具支持,包括许多3D建模软件和渲染引擎。
    • 除了glTF之外,three.js还支持其他常见的3D模型格式,如FBX、OBJ、STL等。这些格式在three.js中都有良好的支持和广泛的应用。

综上所述,虽然PCD是一种有用的点云数据格式,但在three.js中,它并不是主流的模型格式。相反,glTF是three.js中最为推荐和支持的3D模型格式。

unity3D Or three.js

一、Unity3D和three.js简介

Unity3D是一款跨平台的游戏引擎,可以用于开发2D和3D游戏。它提供了一个可视化的开发环境,包含了强大的编辑器和工具,使开发者可以方便地创建游戏场景、添加物体、设置物理效果、编写脚本等。Unity3D支持多种平台,包括PC、移动设备、主机等,可以发布到不同的平台上。

Three.js是一个基于WebGL的JavaScript库,用于创建3D图形和动画。它提供了一系列易于使用的API,可以在网页上实现各种3D效果,包括渲染3D模型、创建光影效果、添加动画等。Three.js可以与HTML、CSS和JavaScript等Web技术无缝集成,可以在现代浏览器上直接运行。

很显然,二者有着不同的应用场景和技术约束,下面为老铁们一一阐释。

二、桌面端or浏览器端

Unity3D是跨平台的游戏引擎,可以发布到多个平台,包括Windows、Mac、Linux等桌面端以及iOS、Android等移动端。如果你的应用需要运行在桌面端,那么Unity3D是一个不错的选择。

hree.js是基于Web技术的,可以在现代浏览器上运行,适用于开发浏览器端应用。如果你的应用主要是在浏览器中展示,那么Three.js是一个合适的选择。

当然二者是可以互通的,unity3d可以打包成web端,three.js也给可以分装成桌面端,但是这种打包和封装是以一部分性功能牺牲为代价的。

比如,unity3D打包成weib端,

将Unity3D应用打包成Web端时可能会遇到以下一些问题:

  1. 性能问题: Unity3D应用通常会占用较多的系统资源,包括CPU和内存。在Web端运行时,由于浏览器的限制,性能可能会受到一定程度的限制。特别是对于较复杂的3D场景和效果,可能需要进行优化以提高性能。
  2. 兼容性问题:不同浏览器对WebGL的支持程度有所不同,可能会导致在某些浏览器上无法正常运行或者出现兼容性问题。需要进行兼容性测试,并根据不同浏览器的特性进行适配。
  3. 文件大小问题: Unity3D应用打包成Web端后,可能会产生较大的文件大小。这对于用户来说可能会导致加载时间较长,特别是对于低带宽或移动网络环境的用户。需要进行文件压缩和优化,以减小文件大小并提高加载速度。
  4. 安全性问题:由于Unity3D应用在Web端运行,可能会涉及到一些安全性问题,例如跨域访问、数据传输的加密等。需要进行相应的安全性处理,以保护用户数据和应用的安全性。
  5. 用户体验问题:Web端应用通常需要考虑用户体验和界面适配的问题。需要确保应用在不同浏览器和设备上能够正常运行,并提供良好的用户交互和界面设计。

总之,将Unity3D应用打包成Web端时,需要注意性能、兼容性、文件大小、安全性和用户体验等问题。通过优化和适配,可以最大程度地提高应用在Web端的运行效果和用户体验。

二、单平台or跨平台

在这方面unity3D具备优势,unity3D是跨平台的,可以运行在Windows、Mac、Linux等桌面端以及iOS、Android等移动端。

three.js通常运营在web端,所以在web端十分有优势。

基于以上,如果要求跨平台,选择unity3D,如果仅运行在浏览器端,选择three.js。

三、C#和JavaScript

Unity3D和Three.js分别使用不同的语言进行开发。

  1. Unity3D: Unity3D使用C#(C Sharp)作为主要的编程语言。C#是一种面向对象的编程语言,由微软开发并广泛用于开发各种应用程序,包括游戏开发。在Unity3D中,开发者可以使用C#来编写游戏逻辑、交互和脚本等。
  2. Three.js: Three.js是一个基于WebGL的JavaScript库,用于在浏览器中创建和展示3D图形。因此,开发Three.js应用主要使用JavaScript编程语言。JavaScript是一种广泛使用的脚本语言,用于开发Web应用程序。在Three.js中,开发者可以使用JavaScript来创建和控制3D场景、对象、动画等。

如果公司有经验丰富丰富的前端人员,上手three.js是非常快的,一般来讲除了游戏公司,其他公司都不会单独养个unity3D人员的。

四、功能优先还是展示优先

如果功能优先是项目的主要考虑因素,那么选择Unity3D可能更合适。Unity3D是一款强大的游戏引擎,具有丰富的功能和工具,可以用于开发复杂的3D应用。它提供了强大的物理引擎、碰撞检测、动画系统等功能,适用于开发需要复杂交互和逻辑的项目。Unity3D还支持多平台发布,可以在不同的设备和操作系统上运行。

如果展示优先是项目的主要考虑因素,那么选择Three.js可能更合适。Three.js是一个基于WebGL的JavaScript库,可以在浏览器中创建和展示3D图形。它提供了简单易用的API,可以快速创建和渲染3D场景,支持各种效果和动画。Three.js的优势在于可以直接在浏览器中展示,无需安装额外的插件,适用于需要广泛分发和展示的项目。

五、性能和时间成本问题

如果需要实现高性能的渲染和特效,以及更接近原生应用的体验,那么选择Unity3D可能更合适。Unity3D使用底层的图形API和优化技术,可以实现更高效的渲染和处理。

根据项目的预算和时间限制,选择合适的工具可以帮助降低开发成本和加快开发进度。Unity3D提供了丰富的资源和社区支持,可以加速开发过程

参考:juejin.cn/post/684490...

相关推荐
清灵xmf5 分钟前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据12 分钟前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_3901617720 分钟前
防抖函数--应用场景及示例
前端·javascript
334554321 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript