webgl的 drawArrays函数及其强大而且灵活,第一个参数不同的值,我们就能以7种不同的方式绘制图形.webgl可以绘制的基本图形如下所示
image.png
注意
- 三角带点击规律是:第偶数个三角形:以上一个三角形的第二条边+下一个点为基础,以和第二条边相反的方向绘制三角形
第奇数个三角形:以上一个三角形的第三条边+下一个点为基础,以和第二条边相反的方向绘制三角形 - 三角扇的绘制规律是:已三角形的第三条边的反方向为起点
图形的移动 旋转
图形尝试移动,旋转,缩放三角,然后在屏幕上面显示出来叫做变换或者也叫仿射变换
平移
为了平移一个三角形需要对顶点的每个分量,加上三角形在对应x,y 上平移的距离.在 webgl 中我们只需要对着色器中的顶点上的每个分量加上一个常量就可以实现平移操作.图形的平移是逐顶点操作,而不是逐片元操作.
示例代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400"></canvas>
</body>
<script id="vertextShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
uniform vec4 u_Trabslation;
void main () {
gl_Position =u_Trabslation+a_Position;
// gl_PointSize = 20.0;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
// 全局设置浮点数的精确度,其他类型都有默认的精度类型,浮点数需要单独的设置
// precision mediump float;
// uniform vec4 u_FragColor;
void main () {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
</script>
<script src="./jsm/util.js"></script>
<script>
let tx=0.0,ty=0.0,tz=0.0
function main () {
const canvas = document.getElementById('webgl')
const gl = canvas.getContext('webgl')
const vertextShader = document.getElementById('vertextShader').innerText
const fragmentShader = document.getElementById('fragmentShader').innerText
if (!initShaders(gl,vertextShader,fragmentShader)) return
if (!gl) return
const a_Position = gl.getAttribLocation(gl.program,'a_Position')
const u_Trabslation = gl.getUniformLocation(gl.program,'u_Trabslation')
if (a_Position < 0 && u_Trabslation<0) return
gl.uniform4f(u_Trabslation,tx,ty,tz,0.0)
const vertexs = [0.0,0.0,0.2,0.0,0.0,0.2]
// 创建缓冲区域
const buffer = gl.createBuffer()
// 绑定缓冲区域
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
// 向缓冲区域写入数据
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertexs),gl.STATIC_DRAW)
// 将缓冲对象分配给 attribute 对象
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0)
// 开启链接 attribute 变量
gl.enableVertexAttribArray(a_Position)
gl.clearColor(0.0,0.0,0.0,1.0)
render(gl)
canvas.onmousedown = function (e) {
click(gl,u_Trabslation)
}
}
function render (gl) {
// 颜色深度清空
gl.clear(gl.COLOR_BUFFER_BIT)
// 开始绘制
gl.drawArrays(gl.TRIANGLES,0,3)
}
function click(gl,u_Trabslation) {
tx+=0.1
ty+=0.1
tz+=0.1
gl.uniform4f(u_Trabslation,tx,ty,tz,0.0)
render(gl)
}
</script>
</html>
旋转
旋转比平移稍微复杂一点,对于旋转来说必须指明:
- 旋转轴(图形将围绕旋转轴旋转)
- 旋转方向(方向:顺时间或者逆时针)
- 旋转角度(图形旋转经过的角度)
例如从 p 点(x,y)旋转到 z点(x1,y1),旋转的角度ø,
X1 = xcosø-ysinø
Y1 = xsinø+ycosø
可以把 cos和 sin 值传递给顶端着色器,然后在顶点着色器根据等式计算出 x1,y1.
示例代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400"></canvas>
</body>
<script id="vertextShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
uniform float u_Cosb;
uniform float u_Sinb;
void main () {
// gl_Position = a_Position;
gl_Position.x = a_Position.x*u_Cosb-a_Position.y*u_Sinb;
gl_Position.y = a_Position.x*u_Sinb+a_Position.y*u_Cosb;
gl_Position.z = a_Position.z;
gl_Position.w =1.0;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
// 全局设置浮点数的精确度,其他类型都有默认的精度类型,浮点数需要单独的设置
// precision mediump float;
// uniform vec4 u_FragColor;
void main () {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
</script>
<script src="./jsm/util.js"></script>
<script>
let tx=0.0,ty=0.0,tz=0.0
let angle = 0.0;
function main () {
const canvas = document.getElementById('webgl')
const gl = canvas.getContext('webgl')
const vertextShader = document.getElementById('vertextShader').innerText
const fragmentShader = document.getElementById('fragmentShader').innerText
if (!initShaders(gl,vertextShader,fragmentShader)) return
if (!gl) return
const a_Position = gl.getAttribLocation(gl.program,'a_Position')
const u_Cosb = gl.getUniformLocation(gl.program,'u_Cosb')
const u_Sinb = gl.getUniformLocation(gl.program,'u_Sinb')
if (a_Position < 0 ) return
angleChange(gl,u_Cosb,u_Sinb)
const vertexs = [0.0,0.0,0.2,0.0,0.0,0.2]
// 创建缓冲区域
const buffer = gl.createBuffer()
// 绑定缓冲区域
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
// 向缓冲区域写入数据
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertexs),gl.STATIC_DRAW)
// 将缓冲对象分配给 attribute 对象
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0)
// 开启链接 attribute 变量
gl.enableVertexAttribArray(a_Position)
gl.clearColor(0.0,0.0,0.0,1.0)
render(gl)
canvas.onmousedown = function (e) {
click(gl,u_Cosb,u_Sinb)
}
}
function render (gl) {
// 颜色深度清空
gl.clear(gl.COLOR_BUFFER_BIT)
// 开始绘制
gl.drawArrays(gl.TRIANGLES,0,3)
}
function angleChange(gl,u_Cosb,u_Sinb) {
const radian = Math.PI*angle/180.0
const cosB = Math.cos(radian)
const sinB = Math.sin(radian)
// 产地给顶点着色器
gl.uniform1f(u_Cosb,cosB)
gl.uniform1f(u_Sinb,sinB)
}
function click(gl,u_Cosb,u_Sinb) {
angle+=10
angleChange(gl,u_Cosb,u_Sinb)
render(gl)
}
</script>
</html>
变换矩阵
对于简单的变换,可以使用数学的表达式计算,但是当情形比较复杂的时候,数学表达式就比较繁琐了.这时候我们使用数学工具-变换矩阵来完成这项工作.在 webgl 中矩阵属于列主序的.使用 uniformMatrix4fv 函数想生成的类型数组穿度个 uniform 变量
gl.unoformMatrix4fv(location,transpose,array)
- location:uniform 变量的地址
- transpose:webgl必须为 false
- array:类型化数组
网友评论