webgl學習03-動態繪制點
動態繪制點
動態傳遞頂點坐標
繪制動態點需要進行 JavaScript 和 GLSL 之間的信息交互,即將JS代碼中指定的點位傳入GLSL中進行繪制。
常規頂點著色器代碼如下,我們需要通過JS代碼給 gl_Position 傳值來動態的繪制點位。
const VertexSource = ` void main () { // 頂點坐標 gl_Position = vec4(0.0, 0.0, 0.0, 1.0); // 頂點渲染像素大小 gl_PointSize = 25.0; } `
此時就需要引入GLSL中的變量 attribute 。
attribute變量
GLSL 中有三種類型的變量,而 attribute 就是其中之一。詳細介紹如下表:
這些變量我們都可以在 JavaScript 中獲取到他們引用地址,并對他們設置值。

代碼如下:
通常命名方式為 類型前綴+變量名。比如說我們的一個 attribute 變量,我們以 a_Xxx 的方式來命名,如下 a_Dnamic。
const VertexSource = ` // 定義了一個名為 a_dnamic,類型為 vec4 的 attribute 變量 attribute vec4 a_Dnamic; void main () { // 將變量賦值給頂點坐標 gl_Position = a_Dnamic; // 頂點渲染像素大小 gl_PointSize = 25.0; } `
接下來,我們只需在 JavaScript 中獲取這個變量 a_Dnamic再賦值就能實現動態傳遞頂點坐標了。
其中 gl.getAttribLocation表示根據變量名獲取 program 中的 attribute 變量。
gl.vertexAttrib[1234]f[v]表示根據獲取到的 attribute 變量進行賦值。其中1234為接受的浮點數數量,未接受為默認值0.0或1.0;v為允許接受數組。

繪制動態點完整代碼
const VertexSource = /* glsl */ ` attribute vec4 a_dnamic_posi; void main() { gl_Position = a_dnamic_posi; gl_PointSize = 25.0; } `; const FragSource = /* glsl */ ` void main() { gl_FragColor = vec4(0.0, 0.0, 0.9, 1.0); } `; const canvas = document.querySelector("#c"); const gl = canvas.getContext("webgl"); // 設置 canvas 背景色(若無需變化顏色,則只需要設置一次即可) gl.clearColor(0.0, 0.0, 0.0, 1.0); // 清空 canvas gl.clear(gl.COLOR_BUFFER_BIT); const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, VertexSource); gl.compileShader(vertexShader); const fragShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragShader, FragSource); gl.compileShader(fragShader); const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragShader); gl.linkProgram(program); gl.useProgram(program); let a_dnamicPosi = gl.getAttribLocation(program, "a_dnamic_posi"); let points = []; canvas.onmousedown = function (e) { let x = e.offsetX; let y = e.offsetY; let rect = e.target.getBoundingClientRect(); x = (x - rect.left - canvas.width / 2) / (canvas.width / 2); y = (canvas.height / 2 - (y - rect.top)) / (canvas.height / 2); points.push([x, y]); gl.clear(gl.COLOR_BUFFER_BIT); points.forEach((v)=>{ // 必須通過記錄的點位來渲染是因為webgl使用的是顏色緩沖區 // GPU是將畫面顏色記錄在緩沖區沖,一次性繪制在屏幕上的,每次都會清空屏幕 gl.vertexAttrib3f(a_dnamicPosi, ...v, 0.0); gl.drawArrays(gl.POINTS, 0, 1); }) };

浙公網安備 33010602011771號