跟月影学可视化
月影
前奇虎360奇舞团团长,可视化UI框架SpriteJS核心开发者,《JavaScript王者归来》作者
立即订阅
4051 人已学习
课程目录
已更新 22 讲 / 共 45 讲
0/4登录后,你可以任选4讲全文学习。
课前必学 (2讲)
开篇词 | 不写网页的前端工程师,还能干什么?
免费
预习 | Web前端与可视化到底有什么区别?
图形基础篇 (4讲)
01 | 浏览器中实现可视化的四种方式
02 | 指令式绘图系统:如何用Canvas绘制层次关系图?
03 | 声明式图形系统:如何用SVG图形元素绘制可视化图表?
04 | GPU与渲染管线:如何用WebGL绘制最简单的几何图形?
数学篇 (5讲)
05 | 如何用向量和坐标系描述点和线段?
06 | 可视化中你必须要掌握的向量乘法知识
07 | 如何用向量和参数方程描述曲线?
08 | 如何利用三角剖分和向量操作描述并处理多边形?
09 | 如何用仿射变换对几何图形进行坐标变换?
视觉基础篇 (8讲)
10 | 图形系统如何表示颜色?
11|图案生成:如何生成重复图案、分形图案以及随机效果?
12 | 如何使用滤镜函数实现美颜效果?
13 | 如何给简单的图案添加纹理和复杂滤镜?
14 | 如何使用片元着色器进行几何造型?
15 | 如何用极坐标系绘制有趣图案?
16 | 如何使用噪声生成复杂的纹理?
17 | 如何使用后期处理通道增强图像效果?
视觉高级篇 (2讲)
18 | 如何生成简单动画让图形动起来?
19 | 如何用着色器实现像素动画?
特别放送 (1讲)
加餐一 | 作为一名程序员,数学到底要多好?
跟月影学可视化
15
15
1.0x
00:00/00:00
登录|注册

04 | GPU与渲染管线:如何用WebGL绘制最简单的几何图形?

月影 2020-06-29
你好,我是月影。今天,我们要讲 WebGL。
WebGL 是最后一个和可视化有关的图形系统,也是最难学的一个。为啥说它难学呢?我觉得这主要有两个原因。第一,WebGL 这种技术本身就是用来解决最复杂的视觉呈现的。比如说,大批量绘制复杂图形和 3D 模型,这类比较有难度的问题就适合用 WebGL 来解决。第二,WebGL 相对于其他图形系统来说,是一个更“开放”的系统。
我说的“开放”是针对于底层机制而言的。因为,不管是 HTML/CSS、SVG 还是 Canvas,都主要是使用其 API 来绘制图形的,所以我们不必关心它们具体的底层机制。也就是说,我们只要理解创建 SVG 元素的绘图声明,学会执行 Canvas 对应的绘图指令,能够将图形输出,这就够了。但是,要使用 WebGL 绘图,我们必须要深入细节里。换句话说就是,我们必须要和内存、GPU 打交道,真正控制图形输出的每一个细节。
所以,想要学好 WebGL,我们必须先理解一些基本概念和原理。那今天这一节课,我会从图形系统的绘图原理开始讲起,主要来讲 WebGL 最基础的概念,包括 GPU、渲染管线、着色器。然后,我会带你用 WebGL 绘制一个简单的几何图形。希望通过这个可视化的例子,能够帮助你理解 WebGL 绘制图形的基本原理,打好绘图的基础。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《跟月影学可视化》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥29.9
立即订阅
登录 后留言

精选留言(16)

  • Cailven
    补充:vs不仅仅只有postion值,一般通过attribute 进行属性赋值。在图形学管顶点操作叫做VAO(vertex array object),而vao操作的float数据底层是vbo。不过如果用了threejs后很多图元操作就依赖引擎直接就解决了,但在Threejs中依然可以通过shaderMatiral通过setAttribute给bufferGeometry的顶点赋值。

    不过个人在这几年的图形学学习中觉得vs相对还是简单的,fs对于像素的操作很像当年给photoshop写滤镜的过程。不过如果真的是玩片元着色炫技可以看看shadertoy里关于用remaching技术构建距离场用体素算法在片元里构建另一个三维引擎的效果。希望月影大大回头可以针对这方面有所加餐。感谢!

    不过这课程来的太晚,如果几年前能早点接触到这门课,估计会在图形学方面少走很多弯路,谢谢月影大大。

    作者回复: VAO是一种组织顶点数据的方式,也是webgl里面常用的方式,它的好处之一是不用每次操作都一一绑定每一组不同的顶点数据。这些属于具体webgl使用上的问题,随着专栏的课程内容深度会有更多介绍。shadertoy很不错的平台,在后面介绍像素处理的课程里会看到一部分shadertoy上比较有趣的例子。

    2020-06-29
    12
  • 筑梦师刘渊
    作业一
    查了下资料,webgl支持的图元类型有七种,分别是 gl.POINTS(点), gl.LINES(线段), gl.LINE_STRIP(线条), gl.LINE_LOOP(回路), gl.TRIANGLES(三角形), gl.TRIANGLE_STRIP(三角带), gl.TRIANGLE_FAN(三角扇)。
    要绘制空心三角形,gl.LINE_STRIP(线条)、gl.LINES(线段)、 gl.LINE_LOOP(回路)都可以实现。 但是gl.LINES(线段)需要写入六个顶点([-1, -1, 0, 1, 0, 1, 1, -1, 1, -1,-1, -1]), gl.LINE_STRIP(线条)也需要写入四个顶点([-1, -1, 0, 1, 1, -1,-1, -1]),而gl.LINE_LOOP(回路),只需要是三个顶点([-1, -1, 0, 1, 1, -1]),因此gl.LINE_LOOP(回路)是最佳选择

    作业二
    a. 先封装一个生成多边形顶点坐标数组的函数
    function createCircleVertex(x, y, r, n) {
        const sin = Math.sin;
        const cos = Math.cos;
        const perAngel = (2 * Math.PI) / n;
        const positionArray = [];
        for (let i = 0; i < n; i++) {
            const angel = i * perAngel;
            const nx = x + r * cos(angel);
            const ny = y + r * sin(angel);
            positionArray.push(nx, ny);
        }
        return new Float32Array(positionArray);
    }
    b. 封装一个生成正多角星顶点的数组函数
    function create2CircleVertex(x, y, r, R, n) {
        const sin = Math.sin;
        const cos = Math.cos;
        const perAngel = Math.PI / n;
        const positionArray = [];
        for (let i = 0; i < 2 * n; i++) {
            const angel = i * perAngel;
            if (i % 2 !== 0) {
                const Rx = x + R * cos(angel);
                const Ry = y + R * sin(angel);
                positionArray.push(Rx, Ry);
            } else {
                const rx = x + r * cos(angel);
                const ry = y + r * sin(angel);
                positionArray.push(rx, ry);
            }
        }
        return new Float32Array(positionArray);
    }
    1. 正四边形 const points = createCircleVertex(0, 0, 0.5, 4);
    2. 正五边形 const points = createCircleVertex(0, 0, 0.5, 5);
    3. 正六角星 const points = create2CircleVertex(0, 0, 0.3, 0.6, 6);

    以上要绘制空心用gl.LINE_LOOP图元,实心用gl.TRIANGLE_FAN图元
    1)空心:gl.drawArrays(gl.LINE_LOOP, 0, points.length / 2);
    2)实心:gl.drawArrays(gl.TRIANGLE_FAN, 0, points.length / 2);

    作者回复: 很棒!

    2020-06-30
    8
  • 宁康
    正n边型,r是外接圆半径

    getPolygonPoints( n, r ){
          const stepAngle = 2*Math.PI / n
          let initAngle = 0
          const pointArray = []
          for(let i = 0; i < n; i++) {
            // 存储x坐标
            pointArray.push(r * Math.cos(initAngle))
            // 存储y坐标
            pointArray.push(r * Math.sin(initAngle))

            initAngle += stepAngle
          }

          return pointArray
        }

    // 正十边型坐标点
    const ponitsArray = getPolygonPoints(10, 1)

    const ponits = new Float32Array(ponitsArray)

    gl.drawArrays(gl.TRIANGLE_FAN, 0, ponits.length / 2)

    作者回复: 赞~

    2020-06-29
    3
  • Kevin
    实现了一个正多边形的样例,动态修改边数。
    https://codesandbox.io/s/practice-canvas-vme4k?file=/src/pages/RegularPolygonWebGL.vue

    作者回复: 赞

    2020-07-16
    2
  • xiao豪
    老师,将数据存入缓存再拿出来是有什么意义呢?

    作者回复: 因为webgl实际上是JS与GPU进行交互,所以要先将JS的数据存入缓存,在webgl程序运行的时候底层从缓存中读取数据给shader,在shader中完成图形绘制。所以是一读一写的过程

    2020-07-06
    2
  • Kevin
    问题一:
    绘制空心三角形使用回路线条:gl.LINE_LOOP
        gl.drawArrays(gl.LINE_LOOP, 0, points.length / 2);

    WebGL可绘制的图元有以下7种,来源网络查找:https://www.jianshu.com/p/1e750f20ec23

    点 gl.POINTS
    线段 gl.LINES
    线条 gl.LINE_STRIP
    回路线条 gl.LINE_LOOP
    三角形 gl.TRIANGLES
    三角带 gl.TRIANGLE_STRIP
    三角扇 gl.TRIANGLE_FAN

    作者回复: 嗯嗯

    2020-07-15
    1
  • 我母鸡啊!
    作业1 : gl.drawArrays传入gl.LINE_LOOP

    作者回复: 嗯嗯

    2020-07-03
    1
  • 我母鸡啊!
    所以在webgl中最小的图元是三角形?

    作者回复: 点、线段和三角形

    2020-07-03
    1
  • miaomiao
    月影老师,你好,有个问题想请教下,如果我想实现12条心电波形折线图,每条波形图的每个脉搏段会依据脉搏类型展示不同的颜色,用户交互:用户可以选择特定的脉搏段,统一修改这个脉搏段类型,这样类型变化,12条心电图的对应脉搏段颜色也变化。这种用canvas好还是webgl好?用canvas的话,需要去获取用户选定的范围,对画布元素进行局部重绘,目前有没有可以只通过更改数据,根据数据变化进行自动重绘的图形库?

    作者回复: 这种canvas和webgl都行,spritejs可以根据数据变化自动重绘,你可以试试。有什么问题直接问我或者仓库提issue

    2020-07-03
    1
    1
  • 量子蔷薇
    我在codepen写了作业,https://codepen.io/quantum-rose/pen/QWyqexL
    不确定自己对WebGL绘图的机制理解对了没,关于封装复用代码那部分,感觉我可能复用了一些不需要复用的代码。期待之后的学习!
    我的六角星只有描边,本质是在不清空画布的情况下画了两个三角形,不知道有没有更好的做法,如果是实心六角星,把我的代码中drawStar函数里的LINE_LOOP换成TRIANGLE_FAN就能画出来,但是其他n角星并不能正确画出来。

    作者回复: 很棒,六角星这么实现是不错的思路。另一种思路是把顶点计算出来之后做三角剖分,在后续课程中很快就会学习到啦。

    2020-06-30
    1
  • 宁康
    1、gl_Position 设置顶点,这个我查了一下,第四个值设置为2.0也可以实现缩小一倍。
    gl_Position = vec4(position, 0.0, 2.0);

    2、空心三角形:
    gl.drawArrays(gl. LINE_LOOP, 0, ponits.length / 2)

    3、绘制多边形
    a.定义多边形的(x, y)坐标
    const ponits = new Float32Array([
            -1, -1,
            0, -2,
            1, -1,
            1, 1,
            -1, 1
          ])
    b.绘制多边形
    gl.drawArrays(gl.TRIANGLE_FAN, 0, ponits.length / 2)

    作者回复: 不错~

    2020-06-29
    1
  • 莫轩竹
    请问编写glsl有什么智能提示插吗,我用的vscode?
    2020-08-01
  • Rexxar
    请问老师:
    gl_Position = vec4(position, 1.0, 1.0);
    在一个三维坐标系中用一个四维向量描述位置?
    这思维向量里的三个参数position, 1.0, 1.0应该怎么理解?

    作者回复: 因为是齐次坐标,所以w是1

    2020-07-29
  • 我母鸡啊!
    冲冲冲!!! 快更新吧!
    2020-07-03
  • 王子晨
    老师请问用webGL绘制复杂的图形,会不会设置多个顶点和片元着色程序?还是说一直在修改一个顶点和片元着色程序?

    作者回复: 会创建多个webgl program 对象,每个对象对应一个顶点着色器和一个片元着色器。只要切换 webgl program 就行

    2020-07-01
    1
  • ailan
    老师,您好。我一开始未设置画布大小,画出的是等腰直角三角形;设置宽高相等时才能画出与示例相同的等腰三角形。那我是否可以这样理解,X轴的1单位长度 / Y轴的1单位长度 = 画布的宽 / 画布的高?

    作者回复: 可以,因为默认的canvas样式宽高是300*150,所以就变成2:1

    2020-06-29
收起评论
16
返回
顶部