寫在前面
建議先閱讀下前面我的兩篇文章。
平移
1、關鍵點說明
-
頂點着色器需要加上 uniform vec4 u_Translation, 存儲平移的坐標矢量。
-
頂點坐標位置 : gl_Position = a_Position + u_Translation
-
平移API : gl.uniform4f(u_Translation, Tx, Ty, Tz, 0.0);
2、demo
- html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<canvas id="canvas" width="200px" height="200px"></canvas>
</body>
</html>
- JavaScript
<script>
function main() {
//頂點着色器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'uniform vec4 u_Translation;\n' +
'void main() {\n' +
' gl_Position = a_Position + u_Translation;\n' +
'}\n';
//片元着色器
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
//獲取canvas元素
var canvas = document.getElementById('canvas');
//獲取繪制二維上下文
var gl = canvas.getContext('webgl');
if (!gl) {
console.log("Failed");
return;
}
//編譯着色器
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, VSHADER_SOURCE);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, FSHADER_SOURCE);
gl.compileShader(fragShader);
//合並程序
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
//獲取坐標點
var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
var n = initBuffers(gl, shaderProgram);
if (n < 0) {
console.log('Failed to set the positions');
return;
}
// 清除指定<畫布>的顏色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 清空 <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, n);
}
function opt(gl, shaderProgram) {
var Tx = 0.5, Ty = 0.5, Tz = 0.0;
var u_Translation = gl.getUniformLocation(shaderProgram, 'u_Translation');
if (!u_Translation) {
console.log('Failed to get the storage location of u_Translation');
return;
}
gl.uniform4f(u_Translation, Tx, Ty, Tz, 0.0);
}
function initBuffers(gl, shaderProgram) {
var vertices = new Float32Array([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
var n = 3;//點的個數
//創建緩沖區對象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log("Failed to create the butter object");
return -1;
}
//將緩沖區對象綁定到目標
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
//向緩沖區寫入數據
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
//獲取坐標點
var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
//將緩沖區對象分配給a_Position變量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
//連接a_Position變量與分配給它的緩沖區對象
gl.enableVertexAttribArray(a_Position);
return n;
}
main();
</script>
旋轉
1、關鍵點說明
- 坐標P(x,y,z) , 繞Z軸旋轉β角度變成 p1(x1, y1, z1)
則根據數據三角函數公式可得:
x1 = xcosβ - ysinβ
y1 = xsinβ + ycosβ
z1=z
-
頂點着色器需要加上 uniform float u_CosB, u_SinB 存儲旋轉角度。
-
頂點坐標位置 :
- 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
-
旋轉API :
- gl.uniform1f(u_CosB, cosB)
- gl.uniform1f(u_sinB, sinB);
2、demo
- JavaScript
<script>
function main() {
//頂點着色器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'uniform float u_CosB, u_SinB;\n' +
'void main() {\n' +
' gl_Position.x = a_Position.x * u_CosB - a_Position.y * u_SinB;\n' +
' gl_Position.y = a_Position.x * u_SinB + a_Position.y * u_CosB;\n' +
' gl_Position.z = a_Position.z;\n' +
' gl_Position.w = 1.0;\n' +
'}\n';
//片元着色器程序
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
var Tx = 0.5, Ty = 0.5, Tz = 0.0;
//獲取canvas元素
var canvas = document.getElementById('canvas');
//獲取繪制二維上下文
var gl = canvas.getContext('webgl');
if (!gl) {
console.log("Failed");
return;
}
//編譯着色器
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, VSHADER_SOURCE);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, FSHADER_SOURCE);
gl.compileShader(fragShader);
//合並程序
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
//獲取坐標點
var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
var n = initBuffers(gl, shaderProgram);
if (n < 0) {
console.log('Failed to set the positions');
return;
}
opt(gl, shaderProgram);
// 清除指定<畫布>的顏色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 清空 <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, n);
}
function opt(gl, program) {
// 旋轉角度
var ANGLE = 90.0;
var radian = Math.PI * ANGLE / 180.0;
var cosB = Math.cos(radian);
var sinB = Math.sin(radian);
var u_CosB = gl.getUniformLocation(program, 'u_CosB');
var u_sinB = gl.getUniformLocation(program, 'u_SinB');
gl.uniform1f(u_CosB, cosB);
gl.uniform1f(u_sinB, sinB);
}
function initBuffers(gl, shaderProgram) {
var vertices = new Float32Array([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
var n = 3;//點的個數
//創建緩沖區對象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log("Failed to create the butter object");
return -1;
}
//將緩沖區對象綁定到目標
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
//向緩沖區寫入數據
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
//獲取坐標點
var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
//將緩沖區對象分配給a_Position變量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
//連接a_Position變量與分配給它的緩沖區對象
gl.enableVertexAttribArray(a_Position);
return n;
}
main();
</script>
縮放
1、關鍵點說明
-
頂點着色器需要加上 uniform mat4 u_xformMatrix, 存儲縮放因子的坐標矢量。
-
頂點坐標位置 : gl_Position = u_xformMatrix * a_Position
-
縮放API : gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);
- u_xformMatrix : 縮放因子
- xformMatrix : 原始坐標
2、demo
- JavaScript
<script>
function main() {
//頂點着色器程序
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'uniform mat4 u_xformMatrix;\n' +
'void main() {\n' +
' gl_Position = u_xformMatrix * a_Position;\n' +
'}\n';
//片元着色器程序
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
var Tx = 0.5, Ty = 0.5, Tz = 0.0;
//獲取canvas元素
var canvas = document.getElementById('canvas');
//獲取繪制二維上下文
var gl = canvas.getContext('webgl');
if (!gl) {
console.log("Failed");
return;
}
//編譯着色器
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, VSHADER_SOURCE);
gl.compileShader(vertShader);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, FSHADER_SOURCE);
gl.compileShader(fragShader);
//合並程序
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
//獲取坐標點
var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
var n = initBuffers(gl, shaderProgram);
if (n < 0) {
console.log('Failed to set the positions');
return;
}
opt(gl, shaderProgram);
// 清除指定<畫布>的顏色
gl.clearColor(0, 0, 0, 1);
// 清空 <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the rectangle
gl.drawArrays(gl.TRIANGLES, 0, n);
}
// 縮放
function opt(gl, program) {
// 縮放因子
var Sx = 1.0, Sy = 1.5, Sz = 1.0;
var xformMatrix = new Float32Array([
Sx, 0.0, 0.0, 0.0,
0.0, Sy, 0.0, 0.0,
0.0, 0.0, Sz, 0.0,
0.0, 0.0, 0.0, 1.0
]);
var u_xformMatrix = gl.getUniformLocation(program, 'u_xformMatrix');
gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);
}
// 構建緩沖區
function initBuffers(gl, shaderProgram) {
var vertices = new Float32Array([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
var n = 3;//點的個數
//創建緩沖區對象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log("Failed to create the butter object");
return -1;
}
//將緩沖區對象綁定到目標
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
//向緩沖區寫入數據
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
//獲取坐標點
var a_Position = gl.getAttribLocation(shaderProgram, 'a_Position');
//將緩沖區對象分配給a_Position變量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
//連接a_Position變量與分配給它的緩沖區對象
gl.enableVertexAttribArray(a_Position);
return n;
}
// 主方法調用
main();
</script>
寫在最后