公共领域 HTML 3D 库






4.99/5 (29投票s)
一个公共领域的 JavaScript 库,用于简化 HTML 3D 应用程序的开发
引言
本页将介绍我编写的一个开源 JavaScript 库——HTML 3D 库。
该库包含一些类和实用方法,旨在简化 HTML 3D 应用程序(如网站)的开发,这些应用程序在支持使用 HTML5 Canvas 进行 3D 绘图的浏览器中运行。
该库与许多其他库不同,因为它属于公共领域,所以使用它不需要任何许可证。
本页包含有关如何使用 HTML 3D 库的信息、其功能概述以及一个启用了 3D 功能的简单网页示例。
注意:本节和本页的其余部分将主要讨论 HTML 3D 库的 2.0.0-beta3 版本,该版本与库的当前发布版本(1.5.1 版)有很大不同。(更多信息请参见“历史”部分。)
如何使用
- 下载 HTML 3D 库.
解压文件 "h3du_min.js",并在每个将使用该库的 HTML 页面中编写以下代码。
<code> <script type="text/javascript" src="h3du_min.js"></script></code>
在网页的某个地方包含一个 HTML 3D 画布,因为绘制 3D 对象需要一个 3D 画布。您可以设置它的
width
和height
。您还应该给它一个 ID,以便在 JavaScript 代码中更容易地引用它,如本例所示。<code> <canvas width="640" height="480" id="canvas"></canvas></code>
要在 JavaScript 中使用 HTML 3D 库,可以将 JavaScript 代码添加到页面底部,或使用事件监听器,如本例所示
<code> <script> window.addEventListener("load",function(){ var scene=new Scene3D(document.getElementById("canvas")); // We have the 3D scene, use it. (See the example code // at the bottom of this article for a more complete example.) }) </script></code>
类列表
这是该库中可用的大多数 JavaScript 类的概述
H3DU
- 包含 HTML 3D 库中的各种实用方法H3DU.Math
- 包含在 3D 应用中有用的数学方法,如矩阵和向量H3DU.Mesh
- 用于构建 3D 模型的辅助类H3DU.MeshBuffer
- 表示一个 3D 模型H3DU.Meshes
- 包含用于生成常见 3D 模型的方法。H3DU.Material
,H3DU.PbrMaterial
,H3DU.Texture
- 表示 3D 对象外观的纹理和颜色。H3DU.Lights
,H3DU.LightSource
- 表示光源H3DU.Batch3D
- 表示要绘制的形状集合以及投影和视图。H3DU.FrameBufferInfo
- 描述帧缓冲区,或用于渲染图形内容的离屏缓冲区。H3DU.ShaderInfo
- 表示一个 GLSL 着色器程序H3DU.Shape
- 表示具有自身变换和外观的 3D 形状实例H3DU.ShapeGroup
- 表示一组 3D 形状H3DU.BSplineCurve
,H3DU.BSplineSurface
,H3DU.CurveBuilder
,H3DU.SurfaceBuilder
- 支持生成参数化曲线和曲面
以下类与 HTML 3D 画布上下文相关
H3DU.Scene3D
- 持有 HTML 3D 画布上下文(GL 上下文)。H3DU.TextureLoader
- 缓存应用程序加载的纹理,并将其映射到 GL 上下文。
有关所有这些类的更多信息,请参阅我的HTML 3D 库文档。
以下各节详细介绍了使用此库的 3D 应用程序的工作原理。
H3DU.Scene3D
H3DU.Scene3D
类是画布 GL 上下文的渲染器。它以 H3DU.Batch3D
对象的形式渲染成批的 3D 形状。每个 Batch3D
表示一个所谓的“场景图”。它包含将要绘制到屏幕上的 3D 对象,以及相机的投影、相机的位置和照亮 3D 场景的光源。
要创建一个 H3DU.Scene3D
,您首先需要在 JavaScript 中找到 HTML 画布,然后将其传递给 new Scene3D()
。一旦您这样做,H3DU.Scene3D
将使用该画布来绘制 3D 对象。这是一个例子。您还需要创建一个 H3DU.Batch3D
来存放 3D 对象。
<code>// Find the HTML canvas with the ID "canvas". var canvas=document.getElementById("canvas") // Create a 3D scene using that canvas. var scene=new H3DU.Scene3D(canvas); var batch=new H3DU.Batch3D();</code>
“相机”
H3DU.Batch3D
类有一个“投影变换”和“视图变换”的概念。如果我们使用“相机”的概念,投影就像设置相机的焦距和镜头,而视图变换就像设置其位置和方向。H3DU.Batch3D
有设置这个抽象“相机”所有这些属性的方法。其中两个是 perspectiveAspect()
和 setLookAt()
,如下例所示。
<code>// Set the perspective view. Camera has a 45-degree field of view // and will see objects from 0.1 to 100 units away. batch.perspectiveAspect(45,0.1,100); // Move the camera back 40 units. batch.setLookAt([0,0,40]); // Move the camera back 30 units instead, and turn it so it // points at (0, 2, 0), that is, up 2 units. batch.setLookAt([0,0,30], [0,2,0]);</code>
更多信息,请参见“相机”与几何变换。
3D 模型
每个 3D 场景都由“网格”组成,即构成几何三维对象的三角形、线条和点。网格可以很简单,例如一个立方体,也可以非常复杂,例如一个带有房屋的城镇模型。您可以使用 H3DU.Mesh
类创建网格,或使用 H3DU.Meshes
类中的方法创建内置的几何形状。下面的示例展示了如何创建一个立方体网格
<code>// Create a box mesh 10 units in width, 20 units // in height, and 25 units in depth var mesh=H3DU.Meshes.createBox(10,20,25);</code>
以下是其他一些内置的网格方法。本页不解释 Meshes
类中的所有功能或参数;为此,请参阅 Meshes API 文档。
H3DU.Meshes.createSphere(radius)
创建一个具有给定radius
的球体。H3DU.Meshes.createCylinder(base, top, height)
创建一个具有给定base
半径、top
半径和height
的圆柱体。如果base
或top
为0
,则可用于创建圆锥体。H3DU.Meshes.createClosedCylinder(base, top, height)
与createCylinder
类似,但它还覆盖了底部和顶部。H3DU.Meshes.createPartialDisk(inner, outer, start, sweep)
创建一个圆环,半径为outer
,带有一个半径为inner
的孔,从start
度开始,扫描sweep
度。H3DU.Meshes.createDisk(inner, outer)
与使用start
0 和sweep
360 调用createPartialDisk
相同。
有关网格的更多信息,请参阅使用公共领域 HTML 3D 库创建形状。
Shapes
网格创建后,需要将其添加到 3D 场景中才能被渲染。使用 H3DU.Shape
构造函数方法将网格转换为形状。然后您可以设置形状的属性,如颜色、大小和位置。然后,调用 addShape()
将形状添加到 3D 对象批次中。
<code>// Create a shape based on the mesh var shape=new H3DU.Shape(mesh); // Make it red (you can also use the HTML color string // "#FF0000" instead) shape.setColor("red"); // Move it 1 unit along the X axis shape.setPosition(1,0,0); // Add the shape to the scene batch.addShape(shape);</code>
3D 形状的外观在 3D 图形世界中被称为“材质”。它包括纹理(图像)、颜色和光反射参数。Material
类保存了其中一些参数的数据,并且是形状定义的一部分。PbrMaterial
类也做同样的事情,但使用基于物理的着色算法。
以下是关于 Shape
类的一些方法的详细信息。
shape.setPosition(x, y, z)
将形状的位置设置为给定的坐标。shape.setScale(x, y, z)
设置形状沿 x、y 和 z 轴的缩放。示例:(1, 1, 1) 表示不缩放,(2, 1, 1) 表示宽度加倍,(1, 1, 0.5) 表示深度减半。shape.getTransform().setRotation(angle, x, y, z)
根据给定的角度(以度为单位)和旋转轴(x、y 和 z 参数)设置形状的旋转。示例:(40, 1, 0, 0) 表示围绕 X 轴旋转 40 度(旋转轴中 x 为 1)。shape.setColor(color)
给形状一个特定的颜色。color
可以是 HTML 颜色 ("#ff0000")、CSS 颜色 ("red")、RGB 颜色 ("rgb(20, 30, 40)") 或 HSL 颜色 ("hsl(20, 50%, 50%)"),或一组从 0 到 1 的值(示例:[1.0,0.5,0.0]
)。请参阅我的颜色教程。shape.setTexture(name)
为形状赋予一个特定的纹理,其 URL 为name
。纹理应与网页在同一来源(通常意味着在同一目录)。shape.copy()
创建此形状的副本。如果同一个几何网格将在同一个 3D 场景中多次使用,但具有不同的位置和属性,这比调用new H3DU.Shape
更高效。
渲染循环
3D 应用程序的一个重要部分是渲染循环。渲染循环是一段代码块,每秒被调用多次(或每秒多“帧”)以重绘 3D 场景。每一帧,应用程序的状态都会更新,并且 3D 场景会重新渲染以反映该状态。要渲染一个场景,请使用 H3DU.Scene3D.render()
方法,传递一批要渲染的形状。渲染循环是使用 H3DU.renderLoop()
方法创建的。以下是渲染循环的一个例子。
<code>// Set up the render loop H3DU.renderLoop(function(time){ // This will be called once each frame. // Here, we render the scene scene.render(batch); });</code>
渲染循环方法接受一个参数(这里是 "time"),包含自页面启动以来的毫秒数。 这可用于实现与帧率无关的动画。
3D 应用骨架
以下是您可以使用此库编写 HTML 应用程序的最小骨架。
<code><head> <meta charset=utf-8> <meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1"> <script type="text/javascript" src="h3du_min.js"></script> </head> <body style="margin:0px"> <canvas id=canvas style="width:100%; height:100%; overflow: hidden;"></canvas> <script> // Your script goes here </script> </body></code>
演示
以下是展示 HTML 3D 库各种功能的 HTML 网页。每个演示都包含一个访问该演示源代码的链接。
简单演示
- demos/simple.html - 使用此库的简单演示。
- demos/triangle.html - 演示绘制一个三角形。
材质
- demos/selfpulse.html - 演示一个旋转、脉动的盒子。
形状和网格
- demos/compositeMesh.html - 演示将多个网格合并为一个。
- demos/shapes.html - 演示内置形状。
- demos/newshapes.html - 更精美的内置形状演示。
- demos/builtinshapes.html - 内置形状的交互式演示。
- demos/platonic.html - 一个展示五个柏拉图固体的演示。演示了
- 如何构建顶点和索引数组以创建几何网格,以及
- 如何根据 3D 模型的位置将 HTML 元素定位在它们之上。
- demos/clock.html - 一个展示挂钟的演示。
- demos/gears.html - 旋转齿轮的演示。
路径
- demos/marchingdots.html - 一系列点像行军蚁一样沿着路径移动的演示。展示了图形路径的一些功能。
- demos/polyclip.html - 类似于“marchingdots.html”,但现在使用两个圆的并集作为路径来演示多边形裁剪。
- demos/pathtube.html - 由路径曲线形成的管状体的演示。
- demos/pathshapes.html - 由 2D 路径生成的 3D 和 2D 形状的演示。
曲线和曲面
- demos/surfaces.html - 演示使用求值器生成参数化曲面。
- demos/curves.html - 演示使用求值器生成参数化曲线。
- demos/surfacesexpr.html - 演示参数化曲面,带有自定义公式编辑器。
- demos/curvesexpr.html - 演示参数化曲线,带有自定义公式编辑器。
- demos/implicit.html - 演示隐式曲面。
- demos/invoevo.html - 演示绘制某些自定义曲线。
- demos/drawingtoy.html - 绘制一个让人联想到流行绘画玩具的设计。
- demos/bsplinecircles.html - 演示如何使用
BSplineCurve
类生成圆形和椭圆形。
纹理
- demos/textured.html - 演示加载纹理并将其应用于 3D 形状。
- demos/specular.html - 演示使用纹理作为镜面反射贴图。
- demos/normalmap.html - 演示使用法线贴图纹理。
- demos/gradient.html - 演示生成自定义纹理——从一种颜色到另一种颜色的线性渐变。
- demos/skysphere.html - 演示如何使用自定义着色器材质实现 360 度背景纹理——一个天空球。
- demos/procedtexture.html - 演示如何将着色器生成的纹理应用于 3D 形状。
着色器
- demos/squares.html - 演示基于着色器的滤镜。
- demos/raymarch.html - 以下内容的演示
- HTML
script
块中的自定义着色器。 - 用于程序化 3D 内容的“光线步进”技术。
- HTML
- demos/checkerboard.html - 用于生成棋盘格纹理的着色器。
- demos/gradient2.html - “gradient”演示的基于着色器的版本。
- demos/marble.html - 用于生成大理石背景的着色器。
- demos/marble2.html - 另一个用于生成大理石背景的着色器。
- demos/wood.html - 用于生成木纹背景的着色器。
粒子系统
- demos/tris.html - 演示粒子系统。
- demos/fallingballs.html - 演示不同大小的球下落。
加载 3D 模型
- demos/obj.html - 一个对象文件加载器。
- demos/stl.html - 演示加载 3D 模型。
选择对象
- demos/picking.html, demos/picking2.html, demos/picking3.html - 这些演示展示了如何实现对象拾取。
光照
- demos/animation-light.html - 非常像 animation.html,但使用点光源照明。
文本
- demos/textwith3D.html - 演示加载位图字体并用它们显示文本。演示在 3D 动画之上显示位图字体文本。
投影
- demos/perspective.html - 演示透视投影。
- demos/animation-isometric.html - 非常像 animation.html,但演示了等距投影。
杂项
- demos/background.html - 一个以连续绘制的 3D 形状为背景的演示。
- demos/animation.html - 一个演示 3D 形状简单动画的示例。
- demos/starfield.html - 星空演示。
- demos/quatlerp.html - 演示 H3DU.Math.quatNlerp 和 H3DU.Math.quatSlerp 之间的区别,这两个函数都用于插值四元数旋转。
- demos/underlay.html - 展示如何使用 H3DU.RenderPass 在三维内容下绘制二维背景。
示例
以下是使用 HTML 3D 库的 HTML 页面的一个简单示例。它设置了 3D 场景,生成一个 3D 盒子,将其涂成红色,并随着时间的推移每帧旋转它。请看注释;它们更好地解释了代码的每个部分在做什么。另请注意它在页面上使用的 <canvas>
元素。
<code><head> <script type="text/javascript" src="h3du_min.js"></script> </head> <body> <canvas width="600" height="450" id=canvas></canvas> <script> // Create the 3D scene; find the HTML canvas and pass it // to Scene3D. var scene=new H3DU.Scene3D(document.getElementById("canvas")); var sub=new H3DU.Batch3D(); // Set the perspective view. Camera has a 45-degree field of view // and will see objects from 0.1 to 100 units away. .perspectiveAspect(45,0.1,100) // Move the camera back 40 units. .setLookAt([0,0,40]); sub.getLights().setBasic(); // Create a box mesh 10 units in size var mesh=H3DU.Meshes.createBox(10,20,20); // Create a shape based on the mesh and give it a red color var shape=new H3DU.Shape(mesh).setColor("red"); // Add the shape to the scene sub.addShape(shape); // Create a timer var timer={}; // Set up the render loop H3DU.renderLoop(function(time){ // Update the shape's rotation var q=H3DU.Math.quatFromTaitBryan( 360*H3DU.getTimePosition(timer,time,6000), 360*H3DU.getTimePosition(timer,time,12000), 0 ); shape.setQuaternion(q); // Render the scene scene.render(sub); }); //--> </script> </body></code>
历史
版本 2.0.0-beta3
beta 3 相对于 beta 2 的变化包括
- 主库文件已转换为 ECMAScript 的 import/export 约定。使用
rollup
工具帮助生成h3du_min.js
文件。 - 发行版中包含了 HTML 文档。
- H3DU.Math 中的 "Norm" 方法已重命名为使用 "Normalize"。
- extras 文件夹中新增
convex.js
,用于生成一组点的凸包。 - extras 文件夹中新增
interp.js
,提供了一个三次贝塞尔插值函数。 - extras 文件夹中新增
spline.js
,用于生成分段插值曲线。 - 新增了几个演示,包括展示如何使用着色器生成程序化内容的演示。
- H3DU.GraphicsPath 中的几个方法被重新实现。
- H3DU.BezierCurve 和 H3DU.BezierSpline 已被弃用。
- 创建了 H3DU.CurveBuilder 和 H3DU.SurfaceBuilder 类;它们取代了现已弃用的 H3DU.CurveEval 和 H3DU.SurfaceEval 类。
- H3DU.MeshBuffer 包含许多新方法;作为交换,许多在 H3DU.MeshBuffer 中重新实现的 H3DU.Mesh 方法已被弃用。
- H3DU.Mesh 在此版本中被大大削弱;该类只应用于构建网格,而不是存储它们。
- 创建了 H3DU.Curve 和 H3DU.Surface;这些类表示参数化曲线和曲面,并提供在曲线或曲面上给定点查询信息的方法。使几个类派生自这两个类,包括 H3DU.BSplineCurve、H3DU.BSplineSurface 和新类 H3DU.PiecewiseCurve。
- H3DU.RenderPass3D 重命名为 H3DU.RenderPass。
- 从 H3DU.PbrMaterial 中删除了 fromBasic 和 fromBasicTexture 方法。
- 向 H3DU.Semantic 添加了 JOINTS 和 WEIGHTS 常量。
- 初步支持遮挡贴图。
- Material 和 PbrMaterial 中的默认漫反射/反照率现在是 (1,1,1,1)。
- 新的 H3DU.BufferAccessor 类表示单个顶点缓冲区。
- H3DU.Mesh 之外的许多方法现在返回 H3DU.MeshBuffer 而不是 H3DU.Mesh。
- 错误修复。
版本 2.0.0-beta2
beta 2 相对于 beta 1 的变化包括
- 添加了 H3DU.PbrMaterial 类,并在默认着色器中支持基于物理的着色。
- H3DU.Shape 对象默认包含 H3DU.PbrMaterial。
- Extras 文件夹包含一个 glTF 加载器,该加载器是初步且不完整的。
- 如果浏览器支持,H3DU.Scene3D 将创建一个 WebGL 2 渲染上下文。
- H3DU.MeshBuffer 按语义(如位置、法线或纹理坐标)存储顶点数据,而不是按名称。
- 新的 H3DU.Semantic 类包含属性和 uniform 语义的常量。
- 新的 H3DU.TextureInfo 类是一个轻量级类,用于存储纹理的设置,但不存储其数据。
- H3DU.ShaderInfo 类现在可以接受 H3DU.TextureInfo 对象作为 uniform 值。
- H3DU.Material 可以在构造函数中接受一个参数对象,就像它可以在 setParams 方法中一样,类似于新的 H3DU.PbrMaterial 类。
- 向 H3DU.Material 类添加了 fromBasic 和 fromBasicTexture 方法。
- 向 H3DU.Math 类添加了许多新方法,包括用于加减 4 元素向量、钳制向量以及与线性 RGB 颜色相互转换的方法,以及 vec3proj、vec4proj、mat3invert 和 vec3fromWindowPoint 方法。frustumHasBox 方法得到了改进。
- 向 H3DU.ShapeGroup 添加了 shapeCount、getShape、setShape 和 copy 方法。
- 新的 H3DU.CubeMap 类保存了构成立方体贴图的纹理信息。但是,立方体贴图尚未在默认着色器中得到支持(其代码当前被注释掉)
- 在 H3DU.GraphicsPath extra 中,添加了用于高级形状和路径插值的方法,并改进了路径三角剖分的代码。
- H3DU.TextFont extra 支持多通道带符号距离场字体。
- 添加了几个新的演示。
- 删除了一些方法:H3DU.Shape 和 H3DU.ShapeGroup 的 setMaterialParams 方法;TextureLoader 的 mapTexture 和 mapTexturesAll 方法;以及 H3DU.Material 的 forShader 方法。
- 将 H3DU.Transform 中的 setOrientation 和 multOrientation 重命名为 setRotation 和 multRotation,并弃用了旧名称。
- 错误修复。
版本 2.0.0-beta1
- 主库中的所有类都已移至名为
H3DU
的新命名空间。例如,Shape
现在是 H3DU.Shape,Mesh
现在是 H3DU.Mesh。“extras”目录中的许多类也已移至H3DU
命名空间。 Scene3D
,现在是 H3DU.Scene3D,不再意味着是待绘制对象的场景图。这项工作现在属于新的 H3DU.Batch3D 类。Scene3D 的render
方法现在接受一个Batch3D
数组进行渲染。但为了兼容性,允许它管理 3D 模型和坐标系的方法,如makeShape
和setPerspective
,在H3DU.Scene3D
渲染自定义H3DU.Batch3D
之前仍然可以使用。这种兼容性行为将来可能会被移除。- 在使用 H3DU.get3DOr2DContext 方法创建的 WebGL 上下文中,Alpha 通道被禁用。
Scene3D
的 H3DU.Scene3D#useProgram 方法已被弃用,现在什么也不做。- 新的 H3DU.RenderPass 类保存有关如何渲染一批 3D 模型的信息。它取代了
Scene3D
的 H3DU.Scene3D#useFilter 方法,该方法现在什么也不做。 - 新的 H3DU.FrameBufferInfo 类保存有关帧缓冲区的信息;它取代了 H3DU.FrameBuffer。
BufferedMesh
、FrameBuffer
和ShaderProgram
类已被弃用,因为它们与特定的 WebGL 上下文耦合过紧。请改用 H3DU.MeshBuffer、H3DU.FrameBufferInfo 和 H3DU.ShaderInfo,它们不与 WebGL 上下文耦合。- 如果 WebGL 实现支持,渲染可以在内部使用顶点数组对象。
- H3DU.Shape 对象不再与顶点缓冲区耦合。
- H3DU.LightSource 类现在支持光的半径。
- 添加了 H3DU.TextureLoader 类用于加载纹理;该类的单个对象可以从多个 WebGL 上下文加载和上传图像。这与
BufferedMesh
、FrameBuffer
和ShaderProgram
不同,后者与 WebGL 上下文绑定。 GLMath
,现在是 H3DU.Math,已扩展了许多新方法。其文档现在非常详细。新方法包括 H3DU.Math.vec3perp、H3DU.Math.vec3toWindowPoint 和 H3DU.Math.mat4projectVec3。- “extras”文件夹中的两个新类支持 2D 文本渲染和纹理图集(作为精灵表),即 H3DU.TextFont 和 H3DU.TextureAtlas。
- “doc”文件夹包含库的文档,格式为 Markdown 文本文件。
- Camera 类,现在是 H3DU.Camera,已被重写。
- 仓库中包含了一个构建脚本。此构建包含一个在库的 JavaScript 文件上运行的样式检查器。
- 许多类增加了许多方法。一些以前不返回值的方法现在返回调用对象的自身值,例如
H3DU.Scene3D
的clear
方法。 - 新的演示,包括 spinbox.html 和 quatlerp.html。例如,gears.html 演示已从单独的“html-gears”仓库移至此处。其他演示也得到了扩展或重写。演示中添加了视口
meta
标签。 H3DU.toGLColor
中使用的底层代码已被重写。特别是,现在支持“#RRGGBBAA”格式。- JavaScript 源代码更好地遵循统一的代码风格。
- surfaces2d.html 中的实验性 2D 画布渲染器已被放弃。
- 向
H3DU.Scene3D
添加了dispose
方法。 - 向
H3DU.Meshes
添加了createPointedStar
和createLathe
方法。 - 向 H3DU.GraphicsPath(一个 extra)添加了
getBounds
和toLinePath
方法,以及一个添加了计算两个多边形交集、差集、并集和异或的方法的 extra。路径三角剖分现在支持带孔的多边形。 - 创建 H3DU.LightSource 时的默认光照配置是无光照。例外情况是,为了兼容性,当使用 H3DU.Scene3D 而不渲染自定义
Batch3D
时,默认是一个具有其默认值的光源。 - 镜面材质 (H3DU.Material) 的默认值现在是 (0.1, 0.1, 0.1)。光泽度的默认值现在是 32。
- Mesh 类不再支持多种图元类型(线、三角形、点)。仍然支持在同一网格中使用使用相同图元类型的不同模式(例如,
TRIANGLE_FAN
和QUAD_STRIP
)。 - 许多教程都经过了大量编辑以适应新版本。添加了
GraphicsPath
教程。 - 还有大量的错误修复。
- 一个已知问题:当将 H3DU.Camera 与 H3DU.Scene3D 的兼容性行为结合使用时,默认情况下只有场景的一侧会显得被照亮。
参见旧版本历史。