一 繪製鼠標點擊過的位置
當鼠標點擊canvas時,記錄點擊位置,然後將所有點擊過的位置都繪製一個紅點。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WebGL</title>
</head>
<body onload="main()">
<canvas id="container" width="1280px" height="720px"></canvas>
</body>
</html>
<script type="text/javascript" src="main.js"></script>
/**
* 在鼠標點擊的位置繪製點
* [email protected]
* */
// 頂點着色器源碼
var vertexShaderSrc = `
attribute vec4 a_Position;// 接收傳入位置座標,必須聲明爲全局
attribute float a_PointSize;// 接收傳入位置座標,必須聲明爲全局,繪製單個點時才生效
void main(){
gl_Position = a_Position;// gl_Position 內置變量,表示點的位置,必須賦值
gl_PointSize = a_PointSize;// gl_PointSize 內置變量,表示點的大小(單位像素),可以不賦值,默認爲1.0
}`;
// 片段着色器源碼
var fragmentShaderSrc = `
void main(){
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);// gl_Position 內置變量,表示點的位置,必須賦值
}`;
// 初始化使用的shader
function initShader(gl) {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);// 創建頂點着色器
gl.shaderSource(vertexShader, vertexShaderSrc);// 綁定頂點着色器源碼
gl.compileShader(vertexShader);// 編譯定點着色器
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);// 創建片段着色器
gl.shaderSource(fragmentShader, fragmentShaderSrc);// 綁定片段着色器源碼
gl.compileShader(fragmentShader);// 編譯片段着色器
var shaderProgram = gl.createProgram();// 創建着色器程序
gl.attachShader(shaderProgram, vertexShader);// 指定頂點着色器
gl.attachShader(shaderProgram, fragmentShader);// 指定片段着色色器
gl.linkProgram(shaderProgram);// 鏈接程序
gl.useProgram(shaderProgram);//使用着色器
gl.program = shaderProgram;
}
function main() {
var canvas = document.getElementById("container");
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
initShader(gl);// 初始化着色器
var a_PointSize = gl.getAttribLocation(gl.program, "a_PointSize");// 獲取shader中的a_PointSize變量
gl.vertexAttrib1f(a_PointSize, 10.0);// 給a_PointSize賦值
var a_Position = gl.getAttribLocation(gl.program, "a_Position");// 獲取shader中的a_Position變量
canvas.onmousedown = function (event) {
onClick(event, gl, canvas, a_Position);
};
gl.clearColor(0.0, 0.0, 0.0, 1.0);// 指定清空canvas的顏色
gl.clear(gl.COLOR_BUFFER_BIT);// 清空canvas
}
g_points = [];
function onClick(event, gl, canvas, a_Position) {
// 記錄鼠標點擊過的位置
var rect = event.target.getBoundingClientRect();
var x = ((event.clientX - rect.left) - canvas.width * 0.5) / (canvas.width * 0.5);
var y = (canvas.height * 0.5 - (event.clientY - rect.top)) / (canvas.height * 0.5);
g_points.push([x, y]);
gl.clear(gl.COLOR_BUFFER_BIT);
for (var i = 0; i < g_points.length; i++) {
var pos = g_points[i];
gl.vertexAttrib4f(a_Position, pos[0], pos[1], 0.0, 1.0);
gl.drawArrays(gl.POINTS, 0, 1);
}
}
如圖:
用這個例子是想說明,每次繪製之後,緩衝區就會被清空,如果不記錄點擊過的位置重新繪製,之前的點就會消失。
只有頂點纔會對傳給attribute變量(插值的點不會傳遞給attribute,插值發生在光柵化階段,在vs之後)。attribute變量的個數又上限,值與設備相關。
二 uniform變量
uniform變量主要是向shader中傳遞一些與頂點無關的數據,在頂點着色器和片元着色器中都可以使用。 數量在vs和fs有各自的上限,具體多少也是與設備相關的。
示例:
/**
* 在鼠標點擊的位置繪製點
* [email protected]
* */
// 頂點着色器源碼
var vertexShaderSrc = `
attribute vec4 a_Position;// 接收傳入位置座標,必須聲明爲全局
attribute float a_PointSize;// 接收傳入位置座標,必須聲明爲全局,繪製單個點時才生效
void main(){
gl_Position = a_Position;// gl_Position 內置變量,表示點的位置,必須賦值
gl_PointSize = a_PointSize;// gl_PointSize 內置變量,表示點的大小(單位像素),可以不賦值,默認爲1.0
}`;
// 片段着色器源碼
var fragmentShaderSrc = `
precision mediump float;// 設置精度
uniform vec4 u_FragColor;// 接收傳入的顏色參數
void main(){
gl_FragColor = u_FragColor;// gl_FragColor 內置變量,表示片元顏色,必須賦值
}`;
// 初始化使用的shader
function initShader(gl) {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);// 創建頂點着色器
gl.shaderSource(vertexShader, vertexShaderSrc);// 綁定頂點着色器源碼
gl.compileShader(vertexShader);// 編譯定點着色器
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);// 創建片段着色器
gl.shaderSource(fragmentShader, fragmentShaderSrc);// 綁定片段着色器源碼
gl.compileShader(fragmentShader);// 編譯片段着色器
var shaderProgram = gl.createProgram();// 創建着色器程序
gl.attachShader(shaderProgram, vertexShader);// 指定頂點着色器
gl.attachShader(shaderProgram, fragmentShader);// 指定片段着色色器
gl.linkProgram(shaderProgram);// 鏈接程序
gl.useProgram(shaderProgram);//使用着色器
gl.program = shaderProgram;
}
function main() {
var canvas = document.getElementById("container");
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
initShader(gl);// 初始化着色器
var a_PointSize = gl.getAttribLocation(gl.program, "a_PointSize");// 獲取shader中的a_PointSize變量
gl.vertexAttrib1f(a_PointSize, 10.0);// 給a_PointSize賦值
var u_FragColor = gl.getUniformLocation(gl.program, "u_FragColor");// 獲取shader中的u_FragColor變量
var a_Position = gl.getAttribLocation(gl.program, "a_Position");// 獲取shader中的a_Position變量
canvas.onmousedown = function (event) {
onClick(event, gl, canvas, a_Position, u_FragColor);
};
gl.clearColor(0.0, 0.0, 0.0, 1.0);// 指定清空canvas的顏色
gl.clear(gl.COLOR_BUFFER_BIT);// 清空canvas
}
g_points = [];
g_colors = [];
function onClick(event, gl, canvas, a_Position, u_FragColor) {
// 記錄鼠標點擊過的位置
var rect = event.target.getBoundingClientRect();
var x = ((event.clientX - rect.left) - canvas.width * 0.5) / (canvas.width * 0.5);
var y = (canvas.height * 0.5 - (event.clientY - rect.top)) / (canvas.height * 0.5);
g_points.push([x, y]);
// 記錄顏色
if(x >= 0 && y >= 0) {
g_colors.push([1.0, 0.0, 0.0, 1.0]);// 第一象限
} else if (x < 0 && y > 0) {
g_colors.push([0.0, 1.0, 0.0, 1.0]);// 第二象限
} else if (x < 0 && y < 0) {
g_colors.push([0.0, 0.5, 1.0, 1.0]);// 第三象限
} else {
g_colors.push([1.0, 1.0, 0.0, 1.0]);// 第四象限
}
gl.clear(gl.COLOR_BUFFER_BIT);
for (var i = 0; i < g_points.length; i++) {
var pos = g_points[i];
var rgba = g_colors[i];
gl.vertexAttrib4f(a_Position, pos[0], pos[1], 0.0, 1.0);
gl.uniform4f(u_FragColor, rgba[0], rgba[1], rgba[2], rgba[3]);
gl.drawArrays(gl.POINTS, 0, 1);
}
}
如圖, 根據鼠標點擊位置的象限,分別給點設置不同的顏色: