搜尋
首頁web前端js教程分解 WebGL 三角形設置

WebGL 一直是 Javascript 中更複雜的 API 之一。作為一名對所有互動式內容感興趣的 Web 開發人員,我決定深入研究 WebGL 的 MDN 文件。我曾經使用過 Three.js,它抽象化了 WebGL 的許多困難,但我還是忍不住打開了它!

這次深入研究的目的是看看我是否能夠充分理解文件並用更簡單的術語進行解釋。 免責聲明 — 我曾使用過 Three.js,並且對 3D 圖形術語和模式有一定的了解。如果這些概念以任何方式適用,我一定會解釋它們。

首先,我們將重點放在三角形的創建。這樣做的原因是為了了解設定 webGL 所需的部分。

為了了解將要涵蓋的內容,以下是我們將要執行的步驟。

  • 設定 HTML 畫布

  • 取得 WebGL 上下文

  • 清除畫布顏色並設定新顏色

  • 建立三角形 (x,y ) 座標數組

  • 新增頂點和片段著色器程式碼

  • 處理並編譯著色器程式碼

  • 建立 webGL 程式

  • 建立緩衝區並將其綁定到 webGL 程式

  • 使用該程式

  • 將GPU訊息連結到CPU

  • 畫出三角形

設定 HTML 畫布

  1. 建立一個名為「RenderTriangle」的資料夾
  2. 在該資料夾中建立一個index.html和main.js檔案

在index.html檔案中加入以下程式碼:

index.js



<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>


<canvas id="canvas"></canvas>

<script src="main.js"></script>

  1. 是渲染 WebGL 上下文的入口點

  2. 我們設定了基本的 HTML 程式碼並連結 main.js 檔案。

  3. main.js 檔案中,我們將存取畫布 id 來渲染 webGL 內容。

準備 HTML 畫布

在 main.js 檔案中加入以下程式碼來準備 HTML 畫布:

main.js

// get canvas
const canvas = document.getElementById("canvas");

// set width and height of canvas
canvas.width = window.innerWidth;

canvas.height = window.innerHeight;

// get the webgl context
const gl = canvas.getContext("webgl2");
  1. 透過id取得HTML畫布並將其儲存在名為「canvas」的變數中(您可以使用任何名稱)。

  2. 透過存取window.innerWidthwindow.innerHeight 設定畫布的canvas.widthcanvas.height

  3. 使用
  4. canvas.getContext(“webgl2”)

    取得 WebGL 上下文並將其儲存在名為「gl」的變數中。

  5. 色彩清晰

main.js

在編寫任何 webGL 程式之前,您需要設定畫布的背景顏色。 WebGL 有兩種方法可以實現這一點。
gl.clearColor(0.1, 0.2, 0.3, 1.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);

clearColor()

— 是一種設定特定背景顏色的方法。之所以稱為“clearColor”,是因為當您將 WebGL 渲染到 HTML 畫布中時,CSS 會將背景設為黑色。當您呼叫 clearColor() 時,它會清除預設顏色並設定您想要的任何顏色。我們可以在下面看到這一點。

注意:
clearColor()

有 4 個參數 (r, g, b, a)

clear()

— 在呼叫 clearColor() 並設定顯式背景顏色後, **clear()** 必須呼叫來「清除」或將緩衝區重設為預設值(緩衝區是顏色和深度資訊的暫存)。

clear()

方法是繪圖方法之一,這表示它是實際渲染顏色的方法。如果不呼叫 clear() 方法,畫布將不會顯示 clearColorclear() 參數選項是, 是 gl.COLOR_BUFFER_BIT、gl.DEPTH_BUFFER_BIT 或 gl.STENCIL_BUFFER_BIT。
在下面的程式碼中您可以新增多個參數以在不同場景下重置。

    gl.DEPTH_BUFFER_BIT — 表示像素深度資訊的緩衝區
  1. gl.COLOR_BUFFER_BIT — 表示像素顏色資訊的緩衝區
  2. 設定三角形座標

main.js

設定背景後,我們可以設定建立三角形所需的座標。座標以 (x, y) 座標的形式儲存在數組中。
// set position coordinates for shape
const triangleCoords = [0.0, -1.0, 0.0, 1.0, 1.0, 1.0];

下面的陣列保存 3 點座標。這些點連接起來形成三角形。

0.0, -1.0

0.0 , 1.0

1.0, 1.0

新增頂點和片段著色器

main.js

為三角形座標建立變數後,我們可以設定著色器。
const vertexShader = `#version 300 es
precision mediump float;

in vec2 position;

void main() {
 gl_Position = vec4(position.x, position.y, 0.0, 1.0); //x,y,z,w
}
`;


const fragmentShader = `#version 300 es
precision mediump float;

out vec4 color;

void main () {
 color = vec4(0.0,0.0,1.0,1.0); //r,g,b,a
}
`;

A shader is a program written in OpenGL ES Shading Language. The program takes position and color information about each vertice point. This information is what’s needed to render geometry.

There are two types of shaders functions that are needed to draw webgl content, the vertex shader and fragment shader

*vertex shader *— The vertex shader function uses position information to render each pixel. Per every render, the vertex shader function runs on each vertex. The vertex shader then transforms each vertex from it’s original coordinates to WebGL coordinates. Each transformed vertex is then saved to the gl_Position variable in the vertex shader program.

*fragment shader *— The fragment shader function is called once for every pixel on a shape to be drawn. This occurs after the vertex shader runs. The fragment shader determines how the color of each pixel and “texel (pixel within a texture)” should be applied. The fragment shader color is saved in the gl_FragColor variable in the fragment shader program.

In the code above we are creating both a vertexShader and fragmentShader constant and storing the shader code in them. The Book of Shaders is a great resource for learning how to write GLSL code.

Processing the Vertex and Fragment Shaders

main.js

// process vertex shader
const shader = gl.createShader(gl.VERTEX_SHADER);

gl.shaderSource(shader, vertexShader);

gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog(vertexShader));
}


// process fragment shader
const shader = gl.createShader(gl.FRAGMENT_SHADER);

gl.shaderSource(shader, fragmentShader);

gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog(fragmentShader));
}

Now that we wrote the shader code (GLSL), we need to create the shader. The shader code still needs to compile. To do this we call the following functions:

createShader() — This creates the shader within the WebGL context

shaderSource() — This takes the GLSL source code that we wrote and sets it into the webGLShader object that was created with createShader.

compileShader() — This compiles the GLSL shader program into data for the WebGLProgram.

The code above processes the vertex and fragment shaders to eventually compile into the WebGLProgram.

Note: An if conditional is added to check if both shaders have compiled properly. If not, an info log will appear. Debugging can be tricky in WebGL so adding these checks is a must.

Creating a WebGL Program

main.js

const program = gl.createProgram();

// Attach pre-existing shaders
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);

gl.linkProgram(program);

if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  const info = gl.getProgramInfoLog(program);
  throw "Could not compile WebGL program. \n\n${info}";
}

Let’s review the code above:

After compiling the vertexShader and fragmentShader, we can now create a WebGLProgram. A WebGLProgram is an object that holds the compiled vertexShader and fragmentShader.

createProgram() — Creates and initializes the WebGLProgram

attachShader() — This method attaches the shader to the webGLProgram

linkProgram() — This method links the program object with the shader objects

Lastly, we need to make a conditional check to see if the program is running properly. We do this with the gl.getProgramParameter.

Create and Bind the Buffers

Now that the WebGL Program is created and the shader programs are linked to it, it’s time to create the buffers. What are buffers?

To simplify it as much as possible, buffers are objects that store vertices and colors. Buffers don’t have any methods or properties that are accessible. Instead, the WebGL context has it’s own methods for handling buffers.

Buffer — “a temporary storage location for data that’s being moved from one place to another”
-wikipedia

We need to create a buffer so that we can store our triangle colors and vertices.

To do this we add the following:

main.js

const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleCoords), gl.STATIC_DRAW);

gl.bindBuffer(gl.ARRAY_BUFFER, null);

In the code above we’re creating a buffer (or temporary storage object) using the createBuffer() method. Then we store it in a constant. Now that we have a buffer object we need to bind it to a target. There are several different target but since we’re storing coordinates in an array we will be using the gl.ARRAY_BUFFER.

To bind the buffer to a target, we use gl.bindBuffer() and pass in the gl.ARRAY_BUFFER (target) and the buffer itself as parameters.

The next step would be to use gl.bufferData() which creates the data store. gl.bufferData() takes the following parameters:

targetgl.ARRAY_BUFFER
datanew Float32Array(triangleCoords)
usage (draw type) — gl.STATIC_DRAW

Lastly, we unbind the buffer from the target to reduce side effects.

Use Program

main.js

gl.useProgram(program);

Once the buffer creation and binding is complete, we can now call the method that sets the WebGLProgram to the rendering state.

Link GPU and CPU

As we get closer to the final step, we need to talk about attributes.

In WebGL, vertex data is stored in a special variable called attributes. attributes are only available to the javascript program and the vertex shader. To access the attributes variable we need to first get the location of the attributes from the GPU. The GPU uses an index to reference the location of the attributes.

main.js

// get index that holds the triangle position information
const position = gl.getAttribLocation(obj.program, obj.gpuVariable);

gl.enableVertexAttribArray(position);

gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

gl.vertexAttribPointer(position, 2, gl.FLOAT, obj.normalize, obj.stride, obj.offset);

Let’s review the code above:

Since we’re rendering a triangle we need the index of the position variable that we set in the vertex shader. We do this using the gl.getAttribLocation() method. By passing in the WebGL program and the position variable name (from the vertex shader) we can get the position attribute’s index.

Next, we need to use the gl.enableVertexAttribArray() method and pass in the position index that we just obtained. This will enable the attributes` storage so we can access it.

We will then rebind our buffer using gl.bindBuffer() and pass in the gl.ARRAY_BUFFER and buffer parameters (the same as when we created the buffers before). Remember in the “Create and Bind the Buffers” section we set the buffer to null to avoid side effects.

When we binded the buffer to the gl.ARRAY_BUFFER we are now able to store our attributes in a specific order. gl.vertexAttribPointer() allows us to do that.

By using gl.vertexAttribPointer() we can pass in the attributes we’d like to store in a specific order. The parameters are ordered first to last.

The gl.vertexAttribPointer is a more complex concept that may take some additional research. You can think of it as a method that allows you to store your attributes in the vertex buffer object in a specific order of your choosing.

Sometimes 3D geometry already has a certain format in which the geometry information is set. vertexAttribPointer comes in handy if you need to make modifications to how that geometry information is organized.

Draw Triangle

main.js

gl.drawArrays(gl.TRIANGLES, 0, 3);

Lastly, we can use the gl.drawArrays method to render the triangle. There are other draw methods, but since our vertices are in an array, this method should be used.

gl.drawArrays() takes three parameters:

mode — which specifies the type of primitive to render. (in this case were rendering a triangle)

first — specifies the starting index in the array of vector points (our triangle coordinates). In this case it’s 0.

count — specifies the number of indices to be rendered. ( since it's a triangle we’re rendering 3 indices)

Note: For more complex geometry with a lot of vertices you can use **triangleCoords.length / 2 **to ****get how many indices your geometry has.

Finally, your triangle should be rendered to the screen! Let’s review the steps.

Breaking Down the WebGL Triangle Setup

  • Set up the HTML canvas

  • Get the WebGL context

  • Clear the canvas color and set a new one

  • Create an array of triangle (x,y )coordinates

  • Add vertex and fragment shader code

  • Process and compile the shader code

  • Create a webGL program

  • Create and bind buffers to the webGL program

  • Use the program

  • Link the GPU information to the CPU

  • Draw out the triangle

The API is a complex one so there’s still a lot to learn but understanding this setup has given me a better foundation.

// Set up the HTML canvas
const canvas = document.getElementById("canvas");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// get the webgl context
const gl = canvas.getContext("webgl2");

// Clear the canvas color and set a new one
gl.clearColor(0.1, 0.2, 0.3, 1.0);
gl.clear(gl.DEPTH_BUFFER_BIT | gl.COLOR_BUFFER_BIT);


// Create an array of triangle (x,y )coordinates
const triangleCoords = [0.0, -1.0, 0.0, 1.0, 1.0, 1.0];

// Add vertex and fragment shader code
const vertexShader = `#version 300 es
precision mediump float;
in vec2 position;

void main() {
gl_Position = vec4(position.x, position.y, 0.0, 1.0); //x,y,z,w
}
`;

const fragmentShader = `#version 300 es
precision mediump float;
out vec4 color;

void main () {
color = vec4(0.0,0.0,1.0,1.0); //r,g,b,a
}
`;


// Process and compile the shader code
const vShader = gl.createShader(gl.VERTEX_SHADER);

gl.shaderSource(vShader, vertexShader);
gl.compileShader(vShader);

if (!gl.getShaderParameter(vShader, gl.COMPILE_STATUS)) {
 console.log(gl.getShaderInfoLog(vertexShader));
}


const fShader = gl.createShader(gl.FRAGMENT_SHADER);

gl.shaderSource(fShader, fragmentShader);
gl.compileShader(fShader);

if (!gl.getShaderParameter(fShader, gl.COMPILE_STATUS)) {
console.log(gl.getShaderInfoLog(fragmentShader));
}

// Create a webGL program
const program = gl.createProgram();


// Link the GPU information to the CPU
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);

gl.linkProgram(program);


if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
const info = gl.getProgramInfoLog(program);
throw "Could not compile WebGL program. \n\n${info}";
}


// Create and bind buffers to the webGL program
const buffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleCoords), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);


// Use the program
gl.useProgram(program);



// Link the GPU information to the CPU
const position = gl.getAttribLocation(program, "position");

gl.enableVertexAttribArray(position);
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.vertexAttribPointer(position, 2, gl.FLOAT, gl.FALSE, 0, 0);


// render triangle
gl.drawArrays(gl.TRIANGLES, 0, 3);

Here are some invaluable references to help understand this material better.

https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API
https://www.udemy.com/course/webgl-internals/
https://webglfundamentals.org/

以上是分解 WebGL 三角形設置的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能