webgl的 drawArrays函數(shù)及其強(qiáng)大而且靈活,第一個(gè)參數(shù)不同的值,我們就能以7種不同的方式繪制圖形.webgl可以繪制的基本圖形如下所示
注意
- 三角帶點(diǎn)擊規(guī)律是:第偶數(shù)個(gè)三角形:以上一個(gè)三角形的第二條邊+下一個(gè)點(diǎn)為基礎(chǔ)亏掀,以和第二條邊相反的方向繪制三角形
第奇數(shù)個(gè)三角形:以上一個(gè)三角形的第三條邊+下一個(gè)點(diǎn)為基礎(chǔ)派昧,以和第二條邊相反的方向繪制三角形 - 三角扇的繪制規(guī)律是:已三角形的第三條邊的反方向?yàn)槠瘘c(diǎn)
圖形的移動(dòng) 旋轉(zhuǎn)
圖形嘗試移動(dòng),旋轉(zhuǎn),縮放三角,然后在屏幕上面顯示出來叫做變換或者也叫仿射變換
平移
為了平移一個(gè)三角形需要對(duì)頂點(diǎn)的每個(gè)分量,加上三角形在對(duì)應(yīng)x,y 上平移的距離.在 webgl 中我們只需要對(duì)著色器中的頂點(diǎn)上的每個(gè)分量加上一個(gè)常量就可以實(shí)現(xiàn)平移操作.圖形的平移是逐頂點(diǎn)操作,而不是逐片元操作.
示例代碼如下:
<!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">
// 全局設(shè)置浮點(diǎn)數(shù)的精確度,其他類型都有默認(rèn)的精度類型,浮點(diǎn)數(shù)需要單獨(dú)的設(shè)置
// 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]
// 創(chuàng)建緩沖區(qū)域
const buffer = gl.createBuffer()
// 綁定緩沖區(qū)域
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
// 向緩沖區(qū)域?qū)懭霐?shù)據(jù)
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertexs),gl.STATIC_DRAW)
// 將緩沖對(duì)象分配給 attribute 對(duì)象
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>
旋轉(zhuǎn)
旋轉(zhuǎn)比平移稍微復(fù)雜一點(diǎn),對(duì)于旋轉(zhuǎn)來說必須指明:
- 旋轉(zhuǎn)軸(圖形將圍繞旋轉(zhuǎn)軸旋轉(zhuǎn))
- 旋轉(zhuǎn)方向(方向:順時(shí)間或者逆時(shí)針)
- 旋轉(zhuǎn)角度(圖形旋轉(zhuǎn)經(jīng)過的角度)
例如從 p 點(diǎn)(x,y)旋轉(zhuǎn)到 z點(diǎn)(x1,y1),旋轉(zhuǎn)的角度?,
X1 = xcos?-ysin?
Y1 = xsin?+ycos?
可以把 cos和 sin 值傳遞給頂端著色器,然后在頂點(diǎn)著色器根據(jù)等式計(jì)算出 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">
// 全局設(shè)置浮點(diǎn)數(shù)的精確度,其他類型都有默認(rèn)的精度類型,浮點(diǎn)數(shù)需要單獨(dú)的設(shè)置
// 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]
// 創(chuàng)建緩沖區(qū)域
const buffer = gl.createBuffer()
// 綁定緩沖區(qū)域
gl.bindBuffer(gl.ARRAY_BUFFER,buffer)
// 向緩沖區(qū)域?qū)懭霐?shù)據(jù)
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertexs),gl.STATIC_DRAW)
// 將緩沖對(duì)象分配給 attribute 對(duì)象
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)
// 產(chǎn)地給頂點(diǎn)著色器
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>
變換矩陣
對(duì)于簡(jiǎn)單的變換,可以使用數(shù)學(xué)的表達(dá)式計(jì)算,但是當(dāng)情形比較復(fù)雜的時(shí)候,數(shù)學(xué)表達(dá)式就比較繁瑣了.這時(shí)候我們使用數(shù)學(xué)工具-變換矩陣來完成這項(xiàng)工作.在 webgl 中矩陣屬于列主序的.使用 uniformMatrix4fv 函數(shù)想生成的類型數(shù)組穿度個(gè) uniform 變量
gl.unoformMatrix4fv(location,transpose,array)
- location:uniform 變量的地址
- transpose:webgl必須為 false
- array:類型化數(shù)組