webgl图形绘制流程
文章目录
- 前言
- 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>2first:从第几个点开始绘制
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图形绘制流程相关推荐
- WebGL(三)——学习Canvas及简单图形绘制
WebGL(三)--学习Canvas及简单图形绘制 Canvas简介 canvas是HTML5新增的一个可以使用javascript脚本在其中绘制图像的HTML元素(容器),它可以用来制作图像.动画, ...
- Android开发笔记(一百五十三)OpenGL绘制三维图形的流程
从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...
- android绘制过程3d图形,Android开发之OpenGL绘制三维图形的流程
从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...
- 学废了系列 - WebGIS vs WebGL图形编程
前工作中有不少涉及到地图的项目,我参加了几次技术评审,前端伙伴们在 WebGIS 方面的知识储备稍有不足,这次分享的主要目的是科普一些在前端领域比较常用的 WebGIS 知识.另外,我之前的工作中积攒 ...
- citra 图形设置_功能强大的图形绘制软件
Canvas Draw mac是一款功能强大的图形绘制软件,轻松帮助您与同事轻松共享项目.Canvas Draw内置大量模板和素材,包括一套全面的矢量对象和高级光栅图像编辑工具,可让你将单一文档中的适 ...
- letswave教程:脑电数据图形绘制、批处理以及脚本生成
letswave教程:脑电数据图形绘制.批处理以及脚本生成 1 单主题图形生成 1.1 打开图形模块 1.2 创建子图 1.3 添加内容 1.4 设置轴参数 1.5 导出图形 2 多主题图形生成 2. ...
- 计算机图形学绘制多边形代码_《GPU编程与CG语言之阳春白雪下里巴人》- 第二章(GPU 图形绘制管线)...
第二章 GPU 图形绘制管线 万事开头难,每门科学都是如此. ------ 马克思 图形绘制管线描述 GPU 渲染流程,即"给定视点.三维物体.光源.照明模式,和纹理等元素,如何绘制一幅二维 ...
- webgl图形平移、缩放、旋转
文章目录 前言 平移 图示 代码示例 缩放 图示 代码示例 旋转 公式推导 代码示例 总结 前言 在webgl中将图形进行平移.旋转.缩放的操作称为变换或仿射变换,图形的仿射变换涉及到顶点位置的修改, ...
- 基于P5JS创意图形绘制
基于P5JS创意图形绘制 使用p5,webgl等工具,尽量重现所给gif图库中的图像. 所选临摹图形为 主要过程 选用了P5JS在线编辑器进行实现,可以浏览P5JS网站并复制附件txt的代码查看效果. ...
最新文章
- mysql 事务 查询 范围加锁_MySQL死锁系列-常见加锁场景分析
- imwrite()函数
- 计算机无法安装手机数据线,连接电脑,详细教您手机数据线连接电脑没反应该怎么解决...
- Vue.js——vue-resource全攻略
- 高清监控如何选择交换机
- Android NDK 使用第三方静态库(转)
- 华为EMUI10带来开发者福音:一次开发多端部署
- 【渺小与伟大】这几张可视化图,颠覆你的认知!
- WebLogic的下载和安装
- 拯救者Y7000(2018)装黑苹果及90%驱动
- 吴恩达 - 机器学习课程笔记(持续更新)
- MOS管自举电路工作原理以及升压自举电路结构图分析
- threejs 管子_使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课...
- Python教你18个高效编程的方法
- MySQL索引(详细,1万字长文)
- jquery+css实现流星雨特效
- VUE项目学习(一):搭建VUE前端项目
- 线性回归方程b保留几位小数_实验室原始数据怎么保留最准确?(一)
- MySQL 8.0 执行 insert 插入数据非常缓慢的问题及解决方法
- 千锋Java第九周总结