文章目录

  • 前言
  • webgl基本环境搭建
    • webgl上下文
    • gl.clearColor()、gl.clear()
    • canvas填充示例
  • 着色器绘制图形
    • 着色器使用流程
    • 封装初始化着色器代码
  • 开始绘制
    • gl.drawArrays()
    • 绘制点示例
    • gl.viewport()设置窗口大小
    • gl_Position齐次坐标
  • 不足
  • 总结

前言

webgl基本图形绘制上下文,步骤,涉及的方法,含义,实现效果等


webgl基本环境搭建

webgl上下文

实现webgl程序时,首先要创立允许webgl运行的环境,这个环境一般被称为webgl绘图上下文,是基于canvas标签创立的

 // 获取webgl上下文let canvas = document.getElementById('canvas');const gl = canvas.getContext('webgl');

gl.clearColor()、gl.clear()

gl.clearColor(r,g,b,a):设置背景色

  • r: 红色分量[0.0, 1.0]
  • g: 绿色分量[0.0, 1.0]
  • b: 蓝色分量[0.0, 1.0]
  • a: 透明度[0.0, 1.0]

gl.clearColor(r,g,b,a)中的参数取值范围都在0.0~1.0之间,若超出的话不会报错,会自动设置为边界值。背景色一旦设置,除非再次调用该方法,否则不会改变


gl.clear(buffer):将指定的缓冲区设置为预设的值

  • buffer:所要清空的缓存类型,枚举如下
    – gl.COLOR_BUFFER_BIT: 将颜色缓存清空,采用之前定义的背景色(gl.clearColor())填充
    – gl.DESPTH_BUFFER_BIT: 清除深度缓存,深度用来表示物体在三维世界的前后顺序,体现在遮挡效果上
    – gl.STENCIL_BUFFER_BIT: 模版缓存

canvas填充示例

综上,用一个最简单的示例总结以上方法,屏幕上将会出现由webgl渲染的,被黄色填充的区域

<!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: 500px;height: 500px;}</style>
</head><body><canvas id="canvas"></canvas><script>/** @type {HTMLCanvasElement} */// 获取webgl上下文let canvas = document.getElementById('canvas');const gl = canvas.getContext('webgl');if (!gl) {throw new Error('WebGL not supported');}// 设置背景色gl.clearColor(1.0, 1.0, 0.0, 1.0)// 清空缓冲区gl.clear(gl.COLOR_BUFFER_BIT)</script>
</body>
</html>

着色器绘制图形

在之前的文章对着色器的使用过程有过比较详细的介绍,这里会更系统介绍着色器使用步骤以及涉及的方法

着色器使用流程


其对应代码如下所示:

     // 创建顶点着色器let vertexShader = gl.createShader(gl.VERTEX_SHADER)// 创建顶点着色器的代码GLSLgl.shaderSource(vertexShader, `void main() {gl_Position = vec4(0.0, 0.0, 0.0, 1.0);gl_PointSize = 20.0;}`)// 编译顶点着色器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');}// 创建程序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');}

封装初始化着色器代码

着色器的使用流程固定,可以将初始着色器的代码封装使用,会更加轻便

function initShader(gl, vertex, fragment) {// 创建顶点着色器let vertexShader = gl.createShader(gl.VERTEX_SHADER)// 创建顶点着色器的代码GLSLgl.shaderSource(vertexShader, vertex)// 编译顶点着色器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, fragment)// 编译片元着色器gl.compileShader(fragmentShader)if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {console.error(gl.getShaderInfoLog(fragmentShader));throw new Error('could not compile fragmentShader');}// 创建程序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');}return program}

开始绘制

gl.drawArrays()

gl.drawArrays(mode, first, count): 执行顶点着色器,按照mode模式绘制图形

  • mode:绘制的方式,常见的类型包括以下几种,详细的可以参照这里
    – gl.Points: 绘制点,count>0
    – gl.Lines: 绘制线,count>1
    – gl.TRIANGLES: 绘制三角形,count>2

  • first:从第几个点开始绘制

  • count:使用几个点进行绘制

当函数gl.drawArrays()执行过程中,顶点着色器供执行了count次,每当执行完顶点着色器,片元着色器都会立即出发执行,如此往复。
`

绘制点示例

结合上述示例,我们绘制一个点在canvas中央

     let canvas = document.getElementById('canvas');// 获取webgl绘图上下文const gl = canvas.getContext('webgl');if (!gl) {throw new Error('WebGL not supported');}canvas.width = window.innerWidth;canvas.height = window.innerHeight;gl.viewport(0, 0, canvas.width, canvas.height)// 设置背景色gl.clearColor(1.0, 1.0, 0.0, 1.0)// 清空缓冲区gl.clear(gl.COLOR_BUFFER_BIT)const vertex =  `void main() {gl_Position = vec4(0.0, 0.0, 0.0, 1.0);gl_PointSize = 20.0;}`const fragment =  `void main(){gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`// 使用shaderinitShader(gl, vertex, fragment)// 绘制三角形gl.drawArrays(gl.POINTS, 0, 1);

示例:

gl.viewport()设置窗口大小

当我设置canvas画布未铺满全屏时,使用顶点着色器会出现坐标偏移的情况:

在获取webgl上下文时,可先通过gl.viewport()设置窗口大小

canvas.width = window.innerWidth // 500;
canvas.height = window.innerHeight // 500;
gl.viewport(0, 0, canvas.width, canvas.height)

gl_Position齐次坐标

我们在设置顶点着色器位置时,其值为一个四维向量

void main() {gl_Position = vec4(0.0, 0.0, 0.0, 1.0);gl_PointSize = 20.0;}

gl_Position实际上是一个四维向量,对应的是齐次坐标,齐次坐标的前两项对应浏览器的屏幕坐标,其中心位于(0.0,0.0)处,前两项坐标均处于[-1.0,1.0]之间,如下图:

不足

虽然采用上述方法实现了绘制点,但是存在一个明显的问题:绘制的坐标全是静态写死在顶点着色器程序中,无法在javascript中灵活传递坐标。为此可以使用attribute和uniform变量灵活传递变量。

总结

webgl基本环境搭建

  • webgl上下文
  • gl.clearColor()、gl.clear()
  • canvas填充示例

着色器绘制图形

  • 着色器使用流程
  • 封装初始化着色器代码

绘制图形

  • gl.drawArrays()
  • 绘制点示例
  • gl.viewport()设置窗口大小gl_Position齐次坐标

不足

绘制的坐标全是静态写死在顶点着色器程序中,无法在javascript中灵活传递坐标。为此可以使用attribute和uniform变量灵活传递变量

webgl图形绘制流程相关推荐

  1. WebGL(三)——学习Canvas及简单图形绘制

    WebGL(三)--学习Canvas及简单图形绘制 Canvas简介 canvas是HTML5新增的一个可以使用javascript脚本在其中绘制图像的HTML元素(容器),它可以用来制作图像.动画, ...

  2. Android开发笔记(一百五十三)OpenGL绘制三维图形的流程

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...

  3. android绘制过程3d图形,Android开发之OpenGL绘制三维图形的流程

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...

  4. 学废了系列 - WebGIS vs WebGL图形编程

    前工作中有不少涉及到地图的项目,我参加了几次技术评审,前端伙伴们在 WebGIS 方面的知识储备稍有不足,这次分享的主要目的是科普一些在前端领域比较常用的 WebGIS 知识.另外,我之前的工作中积攒 ...

  5. citra 图形设置_功能强大的图形绘制软件

    Canvas Draw mac是一款功能强大的图形绘制软件,轻松帮助您与同事轻松共享项目.Canvas Draw内置大量模板和素材,包括一套全面的矢量对象和高级光栅图像编辑工具,可让你将单一文档中的适 ...

  6. letswave教程:脑电数据图形绘制、批处理以及脚本生成

    letswave教程:脑电数据图形绘制.批处理以及脚本生成 1 单主题图形生成 1.1 打开图形模块 1.2 创建子图 1.3 添加内容 1.4 设置轴参数 1.5 导出图形 2 多主题图形生成 2. ...

  7. 计算机图形学绘制多边形代码_《GPU编程与CG语言之阳春白雪下里巴人》- 第二章(GPU 图形绘制管线)...

    第二章 GPU 图形绘制管线 万事开头难,每门科学都是如此. ------ 马克思 图形绘制管线描述 GPU 渲染流程,即"给定视点.三维物体.光源.照明模式,和纹理等元素,如何绘制一幅二维 ...

  8. webgl图形平移、缩放、旋转

    文章目录 前言 平移 图示 代码示例 缩放 图示 代码示例 旋转 公式推导 代码示例 总结 前言 在webgl中将图形进行平移.旋转.缩放的操作称为变换或仿射变换,图形的仿射变换涉及到顶点位置的修改, ...

  9. 基于P5JS创意图形绘制

    基于P5JS创意图形绘制 使用p5,webgl等工具,尽量重现所给gif图库中的图像. 所选临摹图形为 主要过程 选用了P5JS在线编辑器进行实现,可以浏览P5JS网站并复制附件txt的代码查看效果. ...

最新文章

  1. mysql 事务 查询 范围加锁_MySQL死锁系列-常见加锁场景分析
  2. imwrite()函数
  3. 计算机无法安装手机数据线,连接电脑,详细教您手机数据线连接电脑没反应该怎么解决...
  4. Vue.js——vue-resource全攻略
  5. 高清监控如何选择交换机
  6. Android NDK 使用第三方静态库(转)
  7. 华为EMUI10带来开发者福音:一次开发多端部署
  8. 【渺小与伟大】这几张可视化图,颠覆你的认知!
  9. WebLogic的下载和安装
  10. 拯救者Y7000(2018)装黑苹果及90%驱动
  11. 吴恩达 - 机器学习课程笔记(持续更新)
  12. MOS管自举电路工作原理以及升压自举电路结构图分析
  13. threejs 管子_使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课...
  14. Python教你18个高效编程的方法
  15. MySQL索引(详细,1万字长文)
  16. jquery+css实现流星雨特效
  17. VUE项目学习(一):搭建VUE前端项目
  18. 线性回归方程b保留几位小数_实验室原始数据怎么保留最准确?(一)
  19. MySQL 8.0 执行 insert 插入数据非常缓慢的问题及解决方法
  20. 千锋Java第九周总结

热门文章

  1. ArxGIS 利用Samples工具箱实现点转面
  2. 最优雅的数据结构之一——字典树Trie(Java)
  3. 2023年陕西高考,理科状元竟然有四位同学!
  4. 根据verilog画出对应的电路图
  5. 亲测可用云e办项目的接口文档21年10月更新
  6. BIM模型文件下载——办公空间模型
  7. BIM模型文件下载——热交换机机房模型
  8. I/O 是什么意思?
  9. 【Linux】Linux权限
  10. Win10 系统替换 macOS 苹方字体 - 提升文字清晰度与显示渲染效果