根據上一篇學習筆記,理解WebGL的工做原理及基本調用代碼後,能夠開始研究3D頂點對象的縮放、旋轉、以及對對象進行可交互(鼠標或鍵盤控制)的旋轉或者縮放。html
要理解對象的旋轉/縮放須要首先學習矩陣的計算原理,關於矩陣變換參考這兩篇文章:
https://blog.csdn.net/jscese/article/details/52065628
https://blog.csdn.net/u012501459/article/details/12945149#transformweb
其中還涉及到了Math函數的cos正切(輸入弧度參數獲得三角形的對邊/鄰邊的比值)與sin正弦函數,具體的內容請自行百度百科。canvas
矩陣計算的學習筆記:瀏覽器
1個vec * 1個mat4獲得1個新的vec:函數
Vec*mat4計算示例:
Mat = [
M1,m2,m3,m4
M5,m6,m7,m8
M9,m10,m11,m12,
M13,m14,m15,m16
]
Vec = [x,y,z,1]學習
New_vec_x = x*m1+y*m5+z*m9+1*m13
New_vec_y = x*m2+y*m6+z*m10+1*m14
New_vec_z = x*m3+y*m7+z*m11+1*m15
New_vec_1 = x*m4+y*m8+z*m12+1*m16
New_vec = [new_vec_x, new_vec_y, new_vec_z, new_vec1]測試
經常使用的矩陣變換:webgl
Uniform Scaling 統一縮放矩陣:
s=1.5 頂點縮放1.5倍
[
s,0,0,0,
0,s,0,0,
0,0,s,0,
0,0,0,1
].net
平移矩陣:
[
1,0,0,tx
0,1,0,ty,
0,0,1,tz,
0,0,0,1
]orm
沿x軸旋轉矩陣
[
1,0,0,0
0,cosθ,sinθ, 0,
0,-sinθ,cosθ,0,
0,0,0,1
]
沿y軸旋轉矩陣
[
cosθ, 0, -sinθ, 0,
0, 1, 0, 0,
sinθ,0 , cosθ, 0,
0, 0, 0, 1
]
沿z軸旋轉矩陣
[
cosθ, sinθ, 0, 0
-sinθ, cosθ, 0, 0
0, 0,1, 0
0,0,0,1
]
理解上述內容後,就能夠用矩陣對webgl對象進行縮放/旋轉/平移了,測試代碼以下,拷貝到您的瀏覽器能夠查看一個立方體並能夠用鼠標進行旋轉控制:
<!doctype html>
<html>
<head>
</head>
<body>
<canvas id="my_Canvas" width="500" height="500"></canvas>
<script>
var canvas = document.getElementById('my_Canvas')
var gl = canvas.getContext('experimental-webgl')
var vertices = [
-1, -1, -1,
1, -1, -1,
-1, 1, -1,
1, 1, -1,
-1, -1, 1,
1, -1, 1,
-1, 1, 1,
1, 1, 1,
]
var vertex_buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)
gl.bindBuffer(gl.ARRAY_BUFFER, null)
var vertCode = `
attribute vec3 coordinates;
uniform mat4 myTranslateMatrix;
uniform mat4 myScaleMatrix;
uniform mat4 myRotateMatrix;
uniform mat4 myRotateXMatrix;
uniform mat4 myRotateZMatrix;
void main(void){
gl_Position = ( vec4(coordinates, 2.5) )*myTranslateMatrix*myScaleMatrix * myRotateMatrix * myRotateXMatrix * myRotateZMatrix;
gl_PointSize = 10.0;
}
`
var fragCode = `
void main(void){
gl_FragColor = vec4(0.1,0.1,0.1, 1.0);
}
`
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode)
gl.compileShader(vertShader)
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode)
gl.compileShader(fragShader)
var program = gl.createProgram()
gl.attachShader(program, vertShader)
gl.attachShader(program, fragShader)
gl.linkProgram(program)
gl.useProgram(program)
var coordinates = gl.getAttribLocation(program, 'coordinates')
gl.enableVertexAttribArray(coordinates)
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer)
gl.vertexAttribPointer(coordinates, 3, gl.FLOAT, false, 0,0)
var myTranslateMatrix = gl.getUniformLocation(program, 'myTranslateMatrix')
var myTranslate = function(gl, matrixUniform, x,y,z){
var matrix = new Float32Array([
1,0,0,x,
0,1,0,y,
0,0,1,z,
0,0,0,1
])
gl.uniformMatrix4fv(matrixUniform, false, matrix)
}
var myScaleMatrix = gl.getUniformLocation(program, 'myScaleMatrix')
myScale = function(gl, matrixUniform, scale){
gl.uniformMatrix4fv(matrixUniform, false, new Float32Array([
scale, 0, 0, 0,
0, scale, 0,0,
0,0,scale,0,
0,0,0,1
]))
}
myRotateX = function(gl, myRotateMatrix, jd){
var hd;
var coshd;
var sinhd;
hd=jd*Math.PI/180
coshd=Math.cos(hd)
sinhd=Math.sin(hd)
gl.uniformMatrix4fv(myRotateMatrix, false, new Float32Array([
1, 0,0,0,
0, coshd,sinhd,0,
0, -1*sinhd, coshd, 0,
0,0,0,1
]))
}
myRotateY = function(gl, myRotateMatrix, jd){
var hd;
var coshd;
var sinhd;
hd=jd*Math.PI/180
coshd=Math.cos(hd)
sinhd=Math.sin(hd)
gl.uniformMatrix4fv(myRotateMatrix, false, new Float32Array([
coshd, 0,-1*sinhd,0,
0, 1,0,0,
sinhd, 0 , coshd, 0,
0,0,0,1
]))
}
myRotateZ = function(gl, myRotateMatrix, jd){
var hd;
var coshd;
var sinhd;
hd=jd*Math.PI/180
coshd=Math.cos(hd)
sinhd=Math.sin(hd)
gl.uniformMatrix4fv(myRotateMatrix, false, new Float32Array([
coshd, sinhd,0,0,
-1*sinhd, coshd,0,0,
0, 0 , 1, 0,
0,0,0,1
]))
}
var xjd=0,yjd=0,zjd=0
var moving = false
var mov_x_length = 0
var mov_y_length = 0
var page_x=0;
var page_y=0;
canvas.onmousedown = function(e){
moving = true
console.log('mousedown', e)
page_x = e.x
page_y = e.y
}
canvas.onmouseup = function(e) {
moving = false
console.log('mouseup', e)
}
canvas.onmousemove = function(e) {
if(moving) {
//console.log('mousemove', e)
mov_x_length+=page_x-e.x
mov_y_length+=page_y-e.y
// e.x, e.y
console.log(mov_x_length, mov_y_length)
page_x = e.x
page_y = e.y
}
}
myRotateMatrix = gl.getUniformLocation(program, 'myRotateMatrix')
myRotateXMatrix = gl.getUniformLocation(program, 'myRotateXMatrix')
myRotateZMatrix = gl.getUniformLocation(program, 'myRotateZMatrix')
animate = function(){
myTranslate(gl, myTranslateMatrix, 0,0,0.0)
myScale(gl, myScaleMatrix, 1)
myRotateX(gl,myRotateXMatrix, mov_y_length)
myRotateY(gl,myRotateMatrix, mov_x_length)
myRotateZ(gl,myRotateZMatrix, zjd)
gl.clearColor(0.5,0.5,0.5, 1.0)
gl.enable(gl.DEPTH_TEST)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.viewport(0,0,canvas.width, canvas.height)
gl.drawArrays(gl.LINE_LOOP, 0, 8)
requestAnimationFrame(animate)
}
animate()
</script>
</body></html>