认识 webgl
WebGL仅仅是一个光栅化引擎,它可以根据你的代码绘制出点,线和三角形。 WebGL在电脑的GPU中运行,每对方法中一个叫顶点着色器, 另一个叫片断着色器,并且使用一种和C或C 类似的强类型的语言 GLSL。 每一对组合起来称作一个 program(着色程序)
GLSL全称是 Graphics Library Shader Language (图形库着色器语言),是着色器使用的语言。 它有一些不同于JavaScript的特性,主要目的是为栅格化图形提供常用的计算功能。
webgl 发展
WebGL起源于Mozilla员工弗拉基米尔·弗基西维奇的一项称为Canvas 3D实验项目。2006年,弗基西维奇首次展示了Canvas 3D的原型。2007年底在Firefox和Opera被实现。
在2009年初,非营利技术联盟Khronos Group启动了WebGL的工作组,最初的工作成员包括Apple、Google、Mozilla、Opera等。2011年3月发布WebGL 1.0规范。截至2012年3月,工作组的主席由肯·罗素(Ken Russell,全名“Kenneth Bradley Russell”)担任。
WebGL的早期应用包括Zygote Body。
WebGL 2规范的发展始于2013年,并于2017年1月完成。该规范基于OpenGL ES 3.0。首度实现在Firefox 51、Chrome 56和Opera 43中。
webgl的支持(兼容性)
WebGL(Web 图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API 可以在 HTML5"canvas"元素中使用。 这种一致性使 API 可以利用用户设备提供的硬件图形加速。
目前支持 WebGL 的浏览器有:Firefox 4 , Google Chrome 9 , Opera 12 , Safari 5.1 , Internet Explorer 11 和Microsoft Edge build 10240 ;
然而,WebGL 一些特性也需要用户的硬件设备支持。
WebGL 2 API 引入了对大部分的 OpenGL ES 3.0 功能集的支持; 它是通过WebGL2RenderingContext界面提供的。
canvas 元素也被 Canvas API 用于在网页上进行 2D 图形处理。
webgl的优缺点
优点:
- WebGL通过HTML脚本本身实现 Web 交互式三维动画的制作,无需任何浏览器插件支持。
- WebGL利用底层的图形硬件加速功能进行的图形渲染,是通过统一的、标准的、跨平台的OpenGL接口实现的。
缺点:
- 相对于桌面开发API: Unity、 OpenGl、UE这些软件,效果略差
- 开发成本高,需要对线性数学和webgl api熟悉
- 硬件GPU 显卡要求高
创建webgl
Canvas 是 HTML5 提供的一个特性,你可以把它当做一个载体,简单的说就是一张白纸。而 Canvas 2D 相当于获取了内置的二维图形接口,也就是二维画笔。Canvas 3D 是获取基于 WebGL的图形接口,相当于三维画笔。你可以选择不同的画笔在上面作画。
代码语言:php [2-4|6-8]复制 // 创建canvas,定宽高
const canvas = document.querySelector('#canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 基于canvas创建gl, 设置颜色
const gl = canvas.getContext('webgl');
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
创建webgl 着色器
shaders:
OpenGL Shading Language
precision :
lowp :精确度低
mediump:精确度中
highp :精确度高
代码语言:php [1-9|11-23]复制 // 顶点着色器
const vertexShaderSource = `
// 设置浮点数据类型为中级精度
precision mediump float;
// 接收顶点坐标 (x,y)
attribute vec2 a_Position;
void main () {
gl_Position = vec4(a_Position, 0.0, 1.0);
}
`;
// 创建创建着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
//绑定数据源
gl.shaderSource(vertexShader, vertexShaderSource);
// 编译着色器
gl.compileShader(vertexShader);
// 创建着色器程序
const program = gl.createProgram()
gl.attachShader(program, vertexShader)
gl.attachShader(program, fragmentShader)
// 链接 并使用着色器
gl.linkProgram(program)
gl.useProgram(program)
调试着色器
代码语言:php [1-8|9-11]复制 const success = gl.getProgramParameter(program, gl.LINK_STATUS)
if (success) {
gl.useProgram(program)
return program
}
console.error(gl.getProgramInfoLog(program), 'test---')
gl.deleteProgram(program)
WebGL 工作原理
WebGL在GPU上的工作基本上分为两部分,第一部分是将顶点(或数据流)转换到裁剪空间坐标, 第二部分是基于第一部分的结果绘制像素点
代码语言:javascript复制var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 9;
gl.drawArrays(primitiveType, offset, count);
webgl 着色器和GLSL
WebGL每次绘制需要两个着色器, 一个顶点着色器和一个片断着色器,每一个着色器都是一个方法。 一个顶点着色器和一个片断着色器链接在一起放入一个着色程序中(或者只叫程序)。 一个典型的WebGL应用会有多个着色程序。
这两个方法通常是在你的GPU上运行
顶点着色器
顶点着色器的作用是计算顶点的位置。根据计算出的一系列顶点位置,WebGL可以对点, 线和三角形在内的一些图元进行光栅化处理。
当对这些图元进行光栅化处理时需要使用片断着色器方法。 片断着色器的作用是计算出当前绘制图元中每个像素的颜色值。
片断着色器
一个片断着色器的工作是为当前光栅化的像素提供颜色值
代码语言:javascript复制precision mediump float;
void main() {
gl_FragColor = doMathToMakeAColor;
}
-------
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
var level = 0;
var width = 2;
var height = 1;
var data = new Uint8Array([
255, 0, 0, 255, // 一个红色的像素
0, 255, 0, 255, // 一个绿色的像素
]);
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
着色器获取数据的4种方法
这些方法对所需的任何数据都需要发送到GPU
- 1.属性(Attributes)和缓冲
- 2.全局变量(Uniforms)
- 3.纹理(Textures)
- 4.可变量(Varyings)
着色器方式 属性(Attributes)和缓冲
代码语言:php [1-8|9-23]复制// 属性可以用 float, vec2, vec3, vec4, mat2, mat3 和 mat4 数据类型
var string = `
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
`
// 创建缓冲
var buf = gl.createBuffer();
// 数据存入缓冲
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, someData, gl.STATIC_DRAW);
// 开启从缓冲中获取数据
gl.enableVertexAttribArray(positionLoc);
var numComponents = 3; // (x, y, z)
var type = gl.FLOAT; // 32位浮点数据
var normalize = false; // 不标准化
var offset = 0; // 从缓冲起始位置开始获取
var stride = 0; // 到下一个数据跳多少位内存
// 0 = 使用当前的单位个数和单位长度 ( 3 * Float32Array.BYTES_PER_ELEMENT )
gl.vertexAttribPointer(positionLoc, numComponents, type, false, stride, offset);
gl.disableVertexAttribArray(positionLoc); // 关闭从缓冲中获取数据
着色器方式 全局变量(Uniforms)
全局变量在一次绘制过程中传递给着色器的值都一样,在下面的一个简单的例子中, 用全局变量给顶点着色器添加了一个偏移量
代码语言:php复制// 着色器里
uniform vec2 u_someVec2[3];
// JavaScript 初始化时
var someVec2Loc = gl.getUniformLocation(someProgram, "u_someVec2");
// 渲染的时候
gl.uniform2fv(someVec2Loc, [1, 2, 3, 4, 5, 6]); // 设置数组 u_someVec2
着色器方式 纹理(Textures)
代码语言:php [1-9|10-14]复制var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
var level = 0;
var width = 2;
var height = 1;
var data = new Uint8Array([
255, 0, 0, 255, // 一个红色的像素
0, 255, 0, 255, // 一个绿色的像素
]);
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
着色器方式 可变量(Varyings)
为了使用可变量,要在两个着色器中定义同名的可变量。 给顶点着色器中可变量设置的值,会作为参考值进行内插,在绘制像素时传给片断着色器的可变量
代码语言:php [1-6|7-13]复制attribute vec4 a_position;
uniform vec4 u_offset;
varying vec4 v_positionWithOffset;
void main() {
gl_Position = a_position u_offset;
v_positionWithOffset = a_position u_offset;
}
GLSL
GLSL全称是 Graphics Library Shader Language (图形库着色器语言)
栅格化图形提供常用的计算功能,内建的数据类型例如vec2, vec3和 vec4分别代表两个值,三个值和四个值, 类似的还有mat2, mat3 和 mat4 分别代表 2x2, 3x3 和 4x4 矩阵
代码语言:javascript复制vec4 a = vec4(1, 2, 3, 4);
vec4 b = a * 2.0;
// b 现在是 vec4(2, 4, 6, 8);
GLSL是一个强类型的语言
代码语言:javascript复制float f = 1.0; // 使用float
float f = float(1) // 转换integer为float
vec4(v.rgb, 1) 不会因为 1 报错,因为 vec4 内部进行了转换类似 float(1)
查看规范
webgl 使用案例
案列:
沙发模型
洗衣机模
衣服模型
webgl使用
试用webgl
详细webgl
WebGL 需要掌握的知识点
- 1.图像处理
- 2.二维平移,旋转,缩放和矩阵运算
- 3.三维(正射投影,透视投影, 相机)
- 4.光照(方向光源,点光源,聚光灯)
- 5.组织和重构
- 6.几何
- 7.纹理
- 8.渲染到纹理
- 9.阴影
- 10.文字
- 11.Optimization