20 | 如何用WebGL绘制3D物体?
月影
该思维导图由 AI 生成,仅供参考
你好,我是月影。这一节课开始,我们学习 3D 图形的绘制。
之前我们主要讨论的都是 2D 图形的绘制,实际上 WebGL 真正强大之处在于,它可以绘制各种 3D 图形,而 3D 图形能够极大地增强可视化的表现能力。
用 WebGL 绘制 3D 图形,其实在基本原理上和绘制 2D 图形并没有什么区别,只不过是我们把绘图空间从二维扩展到三维,所以计算起来会更加复杂一些。
今天,我们就从绘制最简单的三维立方体,讲到矩阵、法向量在三维空间中的使用,这样由浅入深地带你去了解,如何用 WebGL 绘制出各种 3D 图形。
如何用 WebGL 绘制三维立方体
首先,我们来绘制熟悉的 2D 图形,比如矩形,再把它拓展到三维空间变成立方体。代码如下:
上面的 3 段代码,分别对应顶点着色器、片元着色器和基本的顶点信息。通过它们,我们就在画布上绘制出了一个红色的矩形。接下来,要想把 2 维矩形拓展到 3 维,我们的第一步就是要把顶点扩展到 3 维。这一步的操作比较简单,我们只需要把顶点从 vec2 扩展到 vec3 就可以了。
然后,我们需要计算立方体的顶点数据。我们知道一个立方体有 8 个顶点,这 8 个顶点能组成 6 个面。在 WebGL 中,我们就需要用 12 个三角形来绘制它。如果每个面的属性相同,我们就可以复用 8 个顶点来绘制。而如果属性不同,比如每个面要绘制成不同的颜色,或者添加不同的纹理图片,我们还得把每个面的顶点分开。这样的话,我们一共需要 24 个顶点。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
WebGL绘制3D物体技术总结: 本文深入介绍了使用WebGL绘制3D物体的技术细节。首先讨论了绘制3D图形的基本原理,强调了将绘图空间从二维扩展到三维的复杂性。随后详细介绍了通过代码实现绘制简单的三维立方体的步骤,包括顶点着色器、片元着色器和顶点信息的设置。作者还提到了开启深度检测和启用深度缓冲区的重要性,并介绍了使用gl-renderer库来简化这些步骤。文章还讨论了投影矩阵的概念,以及如何通过投影矩阵将WebGL的坐标系从左手系转换为右手系,从而实现正确的坐标显示。接着,展示了如何实现立方体的旋转效果,并介绍了绘制圆柱体的方法。最后,讲解了构造和使用法向量的重要性,并展示了在shader中实现点光源效果的方法。 在顶点着色器中,计算了点光源与几何体法线的夹角余弦,用于在片元着色器中叠加光照效果。通过法向量和法向量矩阵的运用,实现了点光源光照效果。文章还提到了构造非正立方体和绘制正四面体的方法,以及如何在这些几何体上实现点光源光照效果。 总的来说,本文通过具体的代码示例和技术讲解,帮助读者深入了解了WebGL绘制3D物体的基本原理和实现方法,为读者提供了丰富的技术知识和实践经验。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《跟月影学可视化》,新⼈⾸单¥68
《跟月影学可视化》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(6)
- 最新
- 精选
- 阿鑫正四面体光照效果,https://stupidehorizon.github.io/graphics/demo/07_3d_box/ 一开始没注意每个面的法向量方向,结果有的面发向量朝里了,还 debugger 了半天。
作者回复: 赞
2020-08-2823 - H老师写的文章还不错!!!2022-01-071
- 有一种踏实正四面体,就是取正立方体的四个非共棱顶点组成 function tetrahedron(size, colors = [[1, 0, 0, 1]]) { const h = 0.5 * size; const vertices = [ [-h, -h, -h], // 0 [-h, h, -h], // 1 [h, h, -h], // 2 [h, -h, -h], // 3 [-h, -h, h], // 4 [-h, h, h], // 5 [h, h, h], // 6 [h, -h, h], // 7 ]; const positions = []; const color = []; const cells = []; const normal = []; let colorIdx = 0; let cellsIdx = 0; const colorLen = colors.length; function triangle(a, b, c) { [a, b, c].forEach((i) => { positions.push(vertices[i]); color.push(colors[colorIdx % colorLen]); }); cells.push([0, 1, 2].map(i => i + cellsIdx)); const tmp1 = []; const tmp2 = []; const norm = []; cross(norm, subtract(tmp1, vertices[b], vertices[a]), subtract(tmp2, vertices[c], vertices[a])); normalize(norm, norm); normal.push(norm, norm, norm); colorIdx++; cellsIdx += 3; } triangle(1, 4, 6); triangle(1, 6, 3); triangle(1, 3, 4); triangle(6, 4, 3); return { positions, color, cells, normal }; }2024-02-02归属地:上海
- 蹦哒老师、同学们,立方体每个面的颜色为啥不会插值,而是同一个颜色呢?2023-03-06归属地:北京
- JackWang老师,为什么我按照您的方法渲染后,发现圆柱体两个圆经常会被截断啊2022-03-29
- 卖烧烤夫斯基老师是不是隐藏了一些webgl原始的细节。例如缓冲处理,着色器的初始化编译等。2021-03-17
收起评论