WebGL初學:構建一個多彩三角形與矩形
最近老學了一門新的課程:WebGL。實驗一就是利用WebGL繪製一個頂點顏色不同的三角形和矩形,就像下面這樣:
直接上程式碼吧:
HTML頁面:使用canvas元素生成畫布。
<canvas id="webgl-1" width="640" height="480">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
<br>
<canvas id="webgl-2" width="640" height="480">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
這裡我是直接用了兩個canvas元素以提供兩個不同形狀的繪製。
然後是javascript程式碼。
利用WebGL需要使用著色器,這裡不多介紹。
1.從HTML頁面獲取canvas元素的上下文,這裡主要要獲取到gl物件:
function initWebGL(canvas) {
var gl;
try {
gl = canvas.getContext("webgl");
gl.viewport(0, 0, canvas.width, canvas.height);
} catch (e) {
var msg = "無法從canvas中獲取webgl!" + e.toString();
alert(msg);
throw Error(msg);
}
return gl;
}
2.著色器原始碼:
// =======================================
// 頂點著色器和片元著色器
// =======================================
var vsSource = `
attribute vec3 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
gl_Position = vec4(a_Position, 1.0);
v_Color = a_Color;
}
`;
var fsSource = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}
`;
3.需要對著色器進行編譯及使用:
function loadShader(gl, type, source) {
// 1.建立著色器物件
var shader;
if(type === "vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else if(type === "fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
}
// 2.向著色器物件中填充著色器程式的原始碼
gl.shaderSource(shader, source);
// 3.編譯著色器
gl.compileShader(shader);
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
var error = gl.getShaderInfoLog(shader);
console.log('Failed to compile shader: ' + error);
gl.deleteShader(shader);
return -1;
}
// 4.返回著色器物件
return shader;
}
function initShader(gl, vertSource, fragSource) {
// 載入頂點著色器和片元著色器
var vertShader = loadShader(gl, "vertex", vertSource);
var fragShader = loadShader(gl, "fragment", fragSource);
if(!vertShader || !fragShader) {
return null;
}
// 1.建立著色器程式
var shaderProgram = gl.createProgram();
// 2.為程式物件分配著色器
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
// 3.連線程式物件
gl.linkProgram(shaderProgram);
// 建立失敗, alert
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('無法初始化著色器程式: ' + gl.getProgramInfoLog(shaderProgram));
console.log(gl.getProgramInfoLog(shaderProgram));
return null;
}
// 4.使用程式物件
gl.useProgram(shaderProgram);
gl.program = shaderProgram;
return true;
}
4.建立三角形物件:
function createTriangle(gl) {
var verts = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5,
]);
var colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
]);
var vSIZE = verts.BYTES_PER_ELEMENT;
var vertexBuffer = gl.createBuffer();
var cSIZE = colors.BYTES_PER_ELEMENT;
var colorBuffer = gl.createBuffer();
var triangle = {
vertsArray: verts,
colorsArray: colors,
vertBuffer: vertexBuffer,
colorBuffer: colorBuffer,
vSIZE: vSIZE,
cSIZE: cSIZE,
nVert: 3,
primType: gl.TRIANGLES
};
return triangle;
}
5.類似地,建立矩形物件:
function createSquare(gl) {
var verts = new Float32Array([
0.5, 0.5,
0.5, -0.5,
-0.5, 0.5,
-0.5, -0.5
]);
var colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 0.0
]);
var vSIZE = verts.BYTES_PER_ELEMENT;
var vertexBuffer = gl.createBuffer();
var cSIZE = colors.BYTES_PER_ELEMENT;
var colorBuffer = gl.createBuffer();
var square = {
vertsArray: verts,
colorsArray: colors,
vertBuffer: vertexBuffer,
colorBuffer: colorBuffer,
vSIZE: vSIZE,
cSIZE: cSIZE,
nVert: 4,
primType: gl.TRIANGLE_STRIP
};
return square;
}
6.初始化快取:
function initBuffer(gl, obj) {
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, obj.vertsArray, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, obj.vSIZE * 2 , 0);
gl.enableVertexAttribArray(a_Position);
gl.bindBuffer(gl.ARRAY_BUFFER, obj.colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, obj.colorsArray, gl.STATIC_DRAW);
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, obj.cSIZE * 3 , 0);
gl.enableVertexAttribArray(a_Color);
}
7.主程式入口:
window.onload = function main() {
var canvas1 = document.getElementById('webgl-1');
var gl1 = initWebGL(canvas1);
initShader(gl1, vsSource, fsSource);
var obj1 = createSquare(gl1);
initBuffer(gl1, obj1);
drawScene(canvas1, gl1, obj1);
var canvas2 = document.getElementById('webgl-2');
var gl2 = initWebGL(canvas2);
initShader(gl2, vsSource, fsSource);
var obj2 = createTriangle(gl2);
initBuffer(gl2, obj2);
drawScene(canvas2, gl2, obj2);
};
8.完成!
相關文章
- webgl 系列 —— 初識 WebGLWeb
- 鴻蒙初學001-構建第一個ArkTS應用(Stage模型)鴻蒙模型
- 一個牛人給Java初學者的建議Java
- 構建知識圖譜-初學
- webgl 系列 —— 三角形Web
- 02決策樹-初識與構建
- webgl值得重視的基礎構建Web
- CSS 三角形箭頭的矩形CSS
- 構建一個 @synchronizedsynchronized
- webgl 系列 —— 漸變三角形Web
- webgl入門(2)-初識webgl和著色器Web
- 初識建構函式函式
- 使用canvas畫出一個矩形Canvas
- WebGL學習之HDR與BloomWebOOM
- CSS帶有三角形箭頭的矩形CSS
- Spring Boot——初體驗開啟第一個Gradle構建的Web專案Spring BootGradleWeb
- OpenGL 學習 02 第一個三角形
- 想學習區塊鏈?那就用 Python 構建一個區塊鏈Python
- JavaScript WebGL 繪製一個面JavaScriptWeb
- 給初學者一些學習Python的建議Python
- 如何構建一個WEB同構應用Web
- LeetCode 492[構造矩形]LeetCode
- WebGL基礎(一): 從一個滑鼠畫點開始瞭解原生webGLWeb
- 構建一個閱讀網站網站
- 樹的另一個構建方式
- 使用開源工具構建 DevOps 流水線的初學者指南開源工具dev
- Mybatis初學建立一個MyBatis-HelloworldMyBatis
- [譯] 使用 React 和 ImmutableJS 構建一個拖放佈局構建器ReactJS
- FLASK藍本使用初體驗,個人對整個構建過程的理解Flask
- 使用Dockerfile構建一個django專案DockerDjango
- 用 GIN 構建一個 WEB 服務Web
- 構建一個Flowable命令列應用命令列
- 給Java開發初學者的10個學習建議,助你學習事半功倍!Java
- 給Java開發初學者的10個學習建議,助你學習事半功倍Java
- 從零開始學機器學習——構建一個推薦web應用機器學習Web
- 輸出一個三角形
- Flutter入門與實戰(三):構建一個常用的頁面框架Flutter框架
- 動手學Avalonia:基於矽基流動構建一個文生圖應用(一)