WEBGL原理
webgl:
WebGL(Web图形库)是一个JavaScript APl,可在任何兼容的Web浏览器中染高性能的交互式3D和2D图形,而无需使用插件。WebGL通过引入一个与OpenGL ES 2.0非常一致的API来做到这一点,该API可以在HTML5 <canvas></canvas>元素中使用。这种一致性使API可以利用用户设备提供的硬件图形加速。
渲染管线:
Webgl的渲染依赖底层GPU的渲染能力,所以WEBGL 染流程和 GPU 内部的染管线是相同的。渲染管线的作用是将3D模型转换为2维图像。
在早期,渲染管线是不可编程的,叫做固定渲染管线,工作的细节流程已经固定,修改的话需要调整一些参数。现代的 GPU 所包含的染管线为可编程渲染管线,可以通过编程 GLSL 着色器语言 来控制一些染阶段的细节简单来说: 就是使用shader,我们可以对画布中每个像素点做处理,然后就可以生成各种酷炫的效果了
渲染过程 :
顶点着色器 > 图片装配 光栅化 > 片元着色器 > 剪裁测试 > 多重采样操作 > 背面剔除 > 模板测试 > 深度测试 > 融合 > 缓存
webgl其实就是和Gpu打交道的工具(我们可做的就是操纵上图的 顶点着色器 和 片段着色器 <片元着色器>)
如何对应画布上的点(位置)由于我们眼睛看到的是平面, 所以更关注gl_Position(x,y,z,w)中的x,y
剪裁空间坐标值:无论画布空间多大,剪裁坐标的范围总是在(-1,1)
可以由四种方式得到顶点数据:
attributes:(从缓冲区获得数据)
uniforms:(全局变量)
texture:(纹理)
varyings:(变量)<将顶点着色器变量 传给 片元着色器>
图元:
描述各种图形元素的函数叫图元,描述集合元素的称为几何图元(点,线段或多边形)。点和线是最简单的几何图形经过顶点着色器计算后的坐标会被组装成组合图元
图元装配:
将顶点,颜色,纹理等内容组装(一个可渲染的多边形的过程)
光栅化:
将三维图形 剔除不可见部分,剪裁到不可视范围内部分 ,最终生成可视平面
片元:
光栅化后,每一个包含 颜色 深度 纹理数据 的像素点(片元)
逐片元挑选: 深度测试(z-index) -> 模板测试 (只绘制可视内容)
基本步骤:
一个示例:
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><style>body {padding: 0;margin: 0;}#canvas {width: 100%;height: 100%;}</style><title>webgl原理</title>
</head>
<body>
<canvas id="canvas"></canvas><script>//定义画布const canvas = document.querySelector('#canvas')canvas.width = window.innerWidthcanvas.height = window.innerHeightconst gl = canvas.getContext('webgl') //得到gl绘图上下文gl.viewport(0, 0, canvas.width, canvas.height) //设置gl绘图视口大小//创建顶点着色器const vertexShader = gl.createShader(gl.VERTEX_SHADER) //创建顶点着色器//写顶点着色器glsl源码gl.shaderSource(vertexShader, `attribute vec4 a_Position;void main(){gl_Position = a_Position;}`)//编译顶点着色器gl.compileShader(vertexShader)//创建片元着色器const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)gl.shaderSource(fragmentShader, `void main(){gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`)//编译片元着色器gl.compileShader(fragmentShader)//创建一个程序连接顶点色器和片元着色器const program = gl.createProgram();//链接顶点色器和片元着色器gl.attachShader(program, vertexShader)gl.attachShader(program, fragmentShader)//链接程序gl.linkProgram(program)//使用程序进行渲染gl.useProgram(program)//创建顶点缓冲区对象const vertexBuffer = gl.createBuffer()//绑定顶点缓冲区对象gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)//向顶点缓冲区对象写入数据const vertices = new Float32Array([0.0, 0.5,-0.5, -0.5,0.5, -0.5])//STATIC_DRAW表示数据不会改变,DYNAMIC_DRAW表示值会改变gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)//获取顶带你着色器的a_position的位置const a_Position = gl.getAttribLocation(program, 'a_Position')//将顶点缓冲区对象分配给a_Position变量//让openGL解析顶点数据(数据,n<几个数据为一组>, 数据类型 ,n<跳数几个字读取>,n<开始读取位置>)gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)//启用顶点着色器的a_Position变量gl.enableVertexAttribArray(a_Position)//绘制三角形gl.drawArrays(gl.TRIANGLES, 0, 3)
</script>
</body>
</html>