文章目录

  • 前言
  • 一、WebGL是什么
  • 二、WebGL渲染管线
    • 1 获取坐标元素
    • 2 顶点着色器
    • 3 图元装配
    • 4 光栅化阶段
    • 5 片元着色器
  • 三、 绘制一个三角形
    • 1 初始化一个HTML
    • 2 创建画布
    • 3 创建着色器
    • 4 创建主程序
    • 5 传递数据并绘制
    • 效果

前言

作为gis专业的前端开发人员,工作中少不了与三维场景打交道,像cesium、threejs、mapbox-gl等前端渲染库底层都是封装了WebGL,本文以从一个基础的三角形开始入门WebGL的学习


一、WebGL是什么

WebGL 是一组基于 JavaScript 语言的图形规范,浏览器厂商按照这组规范进行实现,为 Web 开发者提供一套3D图形相关的 API。通过JavaScript和GLSL语言对电脑的显卡(GPU)进行操作,从而在屏幕上绘制出各种各样的3D应用。

二、WebGL渲染管线

不同与传统的前端开发,WebGL程序虽然也使用JavaScrip进行数据的传递与开发,但是却需要GLSL语言实现与GPU的通信(GPU是不认JavaScript的),为了将三维数据显示在浏览器的屏幕上,WebGL有一套固定的流程,这个流程称为渲染管线。
渲染管线大致可以分为以下几个步骤:

1 获取坐标元素

由JavaScript处理着色器需要的顶点坐标、颜色、纹理等信息,并负责为着色器提供这些数据

2 顶点着色器

Webgl实际是控制GPU的渲染,GPU上运行的代码是一对着色器:顶点着色器和片元着色器,着色器在运行时会依次调用顶点着色器和片元着色器。接收 JavaScript 传递过来的顶点信息,将顶点绘制到对应坐标:

 gl_Position = vec4(x, y, z, 1);

gl_Position 接收一个 4 维向量表示的坐标,即(X, Y ,Z ,W),W 不等于 0,这个坐标是在裁剪坐标系中,我们称它为裁剪坐标,裁剪坐标W一般情况赋1就可以。他的原点在屏幕中心,X轴正方向向右,Y轴正方向向上,范围都是[-1,1]。

3 图元装配

图元装配指的是将设置的点、纹理、颜色组装为可渲染多边形的过程。比如将三个顶点装配成三角形图元,顶点着色器执行了三次。

4 光栅化阶段

光栅化阶段指将装配好的图元进行像素填充,同时在这个过程中可能还会将一些已经装配好但是不在屏幕显示范围内(遮挡、放大溢出屏幕、背面)的部分裁剪掉以提高WebGL的运行效率。

5 片元着色器

为片元内部的像素填充颜色信息。其运行的次数由图形的片元数决定

步骤3 4对于开发者来说是无法直接控制的,WebGL会自动帮助完成这些工作

三、 绘制一个三角形

1 初始化一个HTML

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>webgl</title><meta name="viewport" content="width=device-width, initial-scale=1.0" /><style>body {margin: 0;padding: 0;}canvas {width: 100%;height: 100%;}</style>
</head><body><canvas id="canvas"></canvas>
</body>
</html>

2 创建画布

WebGL程序是基于Canvas绘制的,因此需要先添加Canvas对象,使用vsCode编辑器的话,在html中加入/** @type {HTMLCanvasElement} */会出现canvas代码的智能提示。

<script>
/** @type {HTMLCanvasElement} *///------------------------------------------------------创建画布// 获取canvas元素对象let canvas = document.getElementById('canvas');// 设置canvas宽高canvas.width = window.innerWidth;canvas.height = window.innerHeight;// 获取webgl绘图上下文const gl = canvas.getContext('webgl');if (!gl) {throw new Error('WebGL not supported');}// 第一次创建webgl绘图上下文时,需要设置窗口大小gl.viewport(0, 0, canvas.width, canvas.height)

3 创建着色器

GLSL与语言与C语言有些类似,必须放在main函数中,attribute在GLSL中是一个关键字,它只能用于顶点着色器中,用来声明在GLSL中的全局变量,用来存储定点信息。

在下列着色器中未经定义直接使用gl_Position、gl_FragColor两个变量,他们均为webgl中的内置变量

  • gl_Position:顶点的裁剪坐标,最终经过一系列坐标转换成为屏幕坐标。
  • gl_FragColor:片元颜色(r, g, b, a) ,webgl中每一项的取值都是【0.0,1.0】,GPU 会为片元进行上色。
//------------------------------------------------------创建着色器// 创建顶点着色器let vertexShader = gl.createShader(gl.VERTEX_SHADER)// 创建顶点着色器的代码GLSLgl.shaderSource(vertexShader, `attribute vec4 a_Position;void main() {gl_Position = a_Position;}`)// 编译顶点着色器gl.compileShader(vertexShader)if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {console.error(gl.getShaderInfoLog(vertexShader));throw new Error('could not compile vertexShader');}// 创建片元着色器let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)// 创建片元着色器的代码GLSLgl.shaderSource(fragmentShader, `void main(){gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`)// 编译片元着色器gl.compileShader(fragmentShader)if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {console.error(gl.getShaderInfoLog(fragmentShader));throw new Error('could not compile fragmentShader');}

通过以上代码,完成了对顶点着色器和片元着色器的创建

4 创建主程序

创建主程序的代码是很固定的,就是按照这个流程来

//------------------------------------------------------创建主程序// 创建程序let program = gl.createProgram();console.log(program)// 程序关联顶点着色器和片元着色器gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);// 链接程序gl.linkProgram(program);// 使用程序进行渲染gl.useProgram(program);if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {console.log(gl.getProgramInfoLog(program));throw new Error('could not link shaders');}

5 传递数据并绘制

在这里通过创建缓冲区的方式绘制三角形,流程如下

//------------------------------------------------------传递数据并绘制// 创建顶点缓冲区对象let vertexBuffer = gl.createBuffer()// 绑定顶点缓冲区对象gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);// 向顶点缓冲区对象写入数据let vertices = new Float32Array([0.0, 0.5, // 顶点着色器补全为(0.0,0.5,0.0,1.0)-0.5, -0.5,0.5, -0.5])gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);// 获取顶点着色器中a_Position变量的位置let a_Position = gl.getAttribLocation(program, 'a_Position');// 顶点缓冲区对象分配给a_Position变量gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);// 启用顶点着色器的a_Position变量gl.enableVertexAttribArray(a_Position);// 绘制三角形gl.drawArrays(gl.TRIANGLES, 0, 3);<script>

这里第一次写的话的确会觉得很绕,主要有两点:首先,GLSL不能直接把数据写到缓冲区里去,所以,我们必须以gl.ARRAY_BUFFER作为中转,把它绑定至缓冲区,然后对这个中转传递数据;第二点:gl.vertexAttribPointer()方法的第一个参数同样不能直接指给attribute变量,需要指给a_Position对应的attribute,然后将缓冲区分配给a_Position,以此传给attribute变量。

效果


可以看到,如果完全按照WebGL的流程来,即使是绘制一个最简单的元素也需要写很多代码,因此,很多方法完全可以封装起来,在《WebGL编程指南》中就直接提供了工具函数,学习WebGL的话这本书是一定要买的(非广告哈~)

webgl渲染管线、缓冲区绘制三角形相关推荐

  1. WebGL(五)——WEBGL缓冲区,绘制三角形

    WebGL(五)--WEBGL缓冲区,绘制三角形 在 WebGL(四)-- 第一个WEBGL程序 一篇中,留了一个问题, 像下面这样的写法,字符串拼接真的很让人觉得麻烦: 关于改进: 缓冲区对象 缓冲 ...

  2. 第二章 创建webGL设备和绘制缓冲区呈现 Context Creation and Drawing Buffer Presentation

    第二章 创建webGL设备和绘制缓冲区呈现 Context Creation and Drawing Buffer Presentation     在开始使用webGL API之前您先要从现有的HT ...

  3. Metal之渲染绘制三角形

    准备工作 Metal渲染的构建流程, 请参考:Metal之简单渲染动态切换屏幕颜色 Metal三角形的渲染显示与渲染构建流程大体一致, 本文主要介绍以下方面的修改和实现: ① metal渲染文件 ② ...

  4. 【OpenGL】绘制三角形

    [OpenGL]绘制三角形 效果展示 准备条件 图形渲染管线的各个阶段概览 创建着色器程序与绘制OpenGL图元 参考资料 效果展示 准备条件 首先已经通过[OpenGL]使用OpenGL创建窗口使用 ...

  5. OpenGL ES基础教程,绘制三角形(补充,附代码)

    简介 OpenGL OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言.跨平台的编程接口规格的专业的图形程序接口.它用于三维图像(二维亦可),是一个功能强大,调用方 ...

  6. 【OpenGL学习】绘制三角形

    绘制三角形 上节中完成了窗口的绘制,这节我们主要实现在窗口中完成一个最简单的三角形的绘制,同样,要完成一个三角形的绘制,需要以下内容: Vertex Array 存放顶点数据的数组(实际上存放的是顶点 ...

  7. 【OpenGL】十五、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_FAN 三角形扇 )

    文章目录 一.绘制 GL_TRIANGLE_FAN 三角形 1.绘制 3 个点的情况 2.绘制 4 个点的情况 3.绘制 5 个点的情况 4.绘制 6 个点的情况 二.相关资源 一.绘制 GL_TRI ...

  8. 【OpenGL】十四、OpenGL 绘制三角形 ( 绘制 GL_TRIANGLE_STRIP 三角形 | GL_TRIANGLE_STRIP 三角形绘制分析 )

    文章目录 一.绘制 GL_TRIANGLE_STRIP 三角形 二.GL_TRIANGLE_STRIP 三角形绘制分析 三.相关资源 一.绘制 GL_TRIANGLE_STRIP 三角形 该模式绘制首 ...

  9. 【OpenGL】十三、OpenGL 绘制三角形 ( 绘制单个三角形 | 三角形绘制顺序 | 绘制多个三角形 )

    文章目录 一.绘制三角形 二.三角形绘制顺序 1.绘制正面 2.三个点逆时针方向排列 3.三个点顺时针方向排列 4.设置点的正面方向 三.绘制多个三角形 四.相关资源 一.绘制三角形 三角形绘制即绘制 ...

最新文章

  1. 众方网络电话VOIP FREEGO EIS系统命令
  2. C#语言使用多态(接口与override) ——帮您剔除对面向对象多态性的疑惑
  3. 有些窗口底部被任务栏挡住了_开始使用 Tint2 吧,一款 Linux 中的开源任务栏
  4. 百度地图与谷歌地图 (常识、区别,更倾向于使用百度地图,纠错信息比谷歌多)...
  5. 即将开播!联想可能成为罗永浩直播带货的首批合作者
  6. Xna环境在PC平台下的功能扩展
  7. SNW2010中国大会 ZDNet现场报道
  8. 面试突击41:notify是随机唤醒吗?
  9. 四阶龙格库塔法解一维扩散方程
  10. 中国智慧能源行业行情监测及未来动向规划预测报告2022-2028年
  11. Java实现pdf打印文件
  12. ISO/IEC 27701:2019(隐私信息安全管理扩展要求和指南)解读(一)
  13. 如何写一个NES模拟器(一)
  14. 认识kata-containers
  15. 选用数显仪表要注意的问题
  16. Javascript中LenB的计算(ASP)
  17. 小马哥---高仿三星Galaxy J100H主板型号J7210国外版 刷机拆机图
  18. omap3530 linux串口驱动,omap3530(Cortex-A8)硬件平台软件调试笔记
  19. 安装Chrome Restlet Client插件
  20. 加工Altium Designer的PCB出现大部分丝印丢失

热门文章

  1. C语言循环结构之for循环
  2. Only one ConfirmCallback is supported by each RabbitTemplate
  3. 可用性测试易用性和有用性_选择您的可用性测试和参与者
  4. c语言简单心形代码(c语言简单心形代码手机版)
  5. 怎样做好一场高转化的直播?直播间高转化活动如何策划?
  6. 播动师,流量结构,合理规划流量分布
  7. DateTime.Now.ToString(yyyy/MM/dd) 输出的结果是 2006-03-16
  8. 《自然》杂志:人工智能学会触觉,爱抚亲昵指日可待
  9. postgis3.0.1
  10. 【脚本项目源码】Python制作桌面宠物,这么可爱的萌宠你不想拥有吗?