WebGL - Shader
Shader là các chương trình chạy trên GPU. Shader được viết bằng OpenGL ES Shader Language (được gọi là ES SL). ES SL có các biến riêng, kiểu dữ liệu, định tính, đầu vào và đầu ra tích hợp sẵn.
Loại dữ liệu
Bảng sau liệt kê các kiểu dữ liệu cơ bản được cung cấp bởi OpenGL ES SL.
Sr.No. | Loại & Mô tả |
---|---|
1 | void Đại diện cho một giá trị trống. |
2 | bool Chấp nhận đúng hoặc sai. |
3 | int Đây là kiểu dữ liệu số nguyên có dấu. |
4 | float Đây là một kiểu dữ liệu vô hướng nổi. |
5 | vec2, vec3, vec4 vectơ dấu phẩy động n thành phần |
6 | bvec2, bvec3, bvec4 Vector Boolean |
7 | ivec2, ivec3, ivec4 vector số nguyên có dấu |
số 8 | mat2, mat3, mat4 Ma trận float 2x2, 3x3, 4x4 |
9 | sampler2D Truy cập kết cấu 2D |
10 | samplerCube Truy cập kết cấu được ánh xạ hình khối |
Vòng loại
Có ba vòng loại chính trong OpenGL ES SL -
Sr.No. | Vòng loại & Mô tả |
---|---|
1 | attribute Bộ định tính này hoạt động như một liên kết giữa bộ đổ bóng đỉnh và OpenGL ES cho dữ liệu mỗi đỉnh. Giá trị của thuộc tính này thay đổi cho mỗi lần thực thi bộ đổ bóng đỉnh. |
2 | uniform Bộ định lượng này liên kết các chương trình đổ bóng và ứng dụng WebGL. Không giống như định tính thuộc tính, giá trị của đồng phục không thay đổi. Đồng phục ở chế độ chỉ đọc; bạn có thể sử dụng chúng với bất kỳ kiểu dữ liệu cơ bản nào để khai báo một biến. Example - đồng phục vec4 ánh sáng; |
3 | varying Bộ định lượng này tạo thành một liên kết giữa bộ đổ bóng đỉnh và bộ đổ bóng phân đoạn cho dữ liệu nội suy. Nó có thể được sử dụng với các kiểu dữ liệu sau - float, vec2, vec3, vec4, mat2, mat3, mat4 hoặc mảng. Example - thay đổi vec3 bình thường; |
Vertex Shader
Vertex shader là một mã chương trình, được gọi trên mọi đỉnh. Nó biến đổi (di chuyển) hình học (ví dụ: tam giác) từ nơi này sang nơi khác. Nó xử lý dữ liệu của mỗi đỉnh (dữ liệu mỗi đỉnh) như tọa độ đỉnh, chuẩn, màu và tọa độ kết cấu.
Trong mã ES GL của vertex shader, người lập trình phải xác định các thuộc tính để xử lý dữ liệu. Các thuộc tính này trỏ đến một Đối tượng đệm Vertex được viết bằng JavaScript. Các tác vụ sau có thể được thực hiện bằng cách sử dụng bộ đổ bóng đỉnh cùng với phép biến đổi đỉnh:
- Chuyển đổi đỉnh
- Chuyển đổi bình thường và bình thường hóa
- Tạo tọa độ kết cấu
- Chuyển đổi tọa độ kết cấu
- Lighting
- Ứng dụng vật liệu màu
Các biến được xác định trước
OpenGL ES SL cung cấp các biến được xác định trước sau đây cho trình đổ bóng đỉnh:
Sr.No. | Biến & Mô tả |
---|---|
1 | highp vec4 gl_Position; Giữ vị trí của đỉnh. |
2 | mediump float gl_PointSize; Giữ kích thước điểm đã biến đổi. Các đơn vị cho biến này là pixel. |
Mã mẫu
Hãy xem đoạn mã mẫu sau của công cụ đổ bóng đỉnh. Nó xử lý các đỉnh của một tam giác.
attribute vec2 coordinates;
void main(void) {
gl_Position = vec4(coordinates, 0.0, 1.0);
};
Nếu bạn quan sát kỹ đoạn mã trên, chúng ta đã khai báo một biến thuộc tính với tên coordinates. (Biến này sẽ được liên kết với Đối tượng đệm Vertex bằng phương thứcgetAttribLocation(). Thuộc tínhcoordinates được truyền dưới dạng tham số cho phương thức này cùng với đối tượng chương trình đổ bóng.)
Trong bước thứ hai của chương trình đổ bóng đỉnh đã cho, gl_position biến được xác định.
gl_Position
gl_Position là biến được xác định trước chỉ có trong chương trình tô bóng đỉnh. Nó chứa vị trí đỉnh. Trong đoạn mã trên,coordinatesthuộc tính được chuyển dưới dạng một vector. Vì vertex shader là một hoạt động trên mỗi đỉnh, nên giá trị gl_position được tính cho mỗi đỉnh.
Sau đó, giá trị gl_position được sử dụng bởi hợp ngữ nguyên thủy, cắt, chọn và các hoạt động chức năng cố định khác hoạt động trên nguyên thủy sau khi quá trình xử lý đỉnh kết thúc.
Chúng ta có thể viết các chương trình đổ bóng đỉnh cho tất cả các hoạt động có thể có của trình đổ bóng đỉnh, mà chúng ta sẽ thảo luận riêng trong hướng dẫn này.
Fragment Shader
A mesh được tạo thành bởi nhiều hình tam giác và bề mặt của mỗi hình tam giác được gọi là fragment. Trình đổ bóng phân mảnh là mã chạy trên mỗi pixel trên mỗi phân mảnh. Điều này được viết để tính toán và tô màu trên các pixel riêng lẻ. Các tác vụ sau có thể được thực hiện bằng cách sử dụng trình tạo bóng phân mảnh:
- Các phép toán trên các giá trị nội suy
- Quyền truy cập kết cấu
- Ứng dụng kết cấu
- Fog
- Tổng màu
Các biến được xác định trước
OpenGL ES SL cung cấp các biến được xác định trước sau đây cho trình đổ bóng phân mảnh:
Sr.No. | Biến & Mô tả |
---|---|
1 | trung gian vec4 gl_FragCoord; Giữ vị trí phân mảnh trong bộ đệm khung. |
2 | bool gl_FrontFacing; Giữ phân mảnh thuộc về nguyên thủy mặt trước. |
3 | mediump vec2 gl_PointCoord; Giữ vị trí phân mảnh trong một điểm (chỉ rasterization điểm). |
4 | mediump vec4 gl_FragColor; Giữ giá trị màu của đoạn đầu ra của bộ đổ bóng |
5 | mediump vec4 gl_FragData[n] Giữ màu phân mảnh để đính kèm màu n. |
Mã mẫu
Đoạn mã mẫu sau đây của trình tạo bóng phân mảnh cho thấy cách áp dụng màu cho mọi pixel trong một hình tam giác.
void main(void) {
gl_FragColor = vec4(0, 0.8, 0, 1);
}
Trong đoạn mã trên, colorgiá trị được lưu trữ trong biến gl.FragColor
. Chương trình đổ bóng phân mảnh chuyển đầu ra đến đường ống bằng cách sử dụng các biến hàm cố định; FragColor là một trong số đó. Biến này giữ giá trị màu của các pixel của mô hình.
Lưu trữ và biên dịch các chương trình Shader
Vì shader là những chương trình độc lập, chúng ta có thể viết chúng dưới dạng một script riêng biệt và sử dụng trong ứng dụng. Hoặc, bạn có thể lưu trữ chúng trực tiếp trongstring định dạng, như được hiển thị bên dưới.
var vertCode =
'attribute vec2 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 0.0, 1.0);' +
'}';
Biên dịch Shader
Biên dịch bao gồm ba bước sau:
- Tạo đối tượng đổ bóng
- Đính kèm mã nguồn vào đối tượng đổ bóng đã tạo
- Biên soạn chương trình
Tạo Vertex Shader
Để tạo một bộ đổ bóng trống, WebGL cung cấp một phương thức được gọi là createShader(). Nó tạo và trả về đối tượng đổ bóng. Cú pháp của nó như sau:
Object createShader (enum type)
Như đã quan sát trong cú pháp, phương thức này chấp nhận một giá trị enum được xác định trước làm tham số. Chúng tôi có hai lựa chọn cho việc này -
gl.VERTEX_SHADER để tạo bóng đổ đỉnh
gl.FRAGMENT_SHADER để tạo bộ đổ bóng phân mảnh.
Gắn nguồn vào Shader
Bạn có thể đính kèm mã nguồn vào đối tượng đổ bóng đã tạo bằng phương pháp shaderSource(). Cú pháp của nó như sau:
void shaderSource(Object shader, string source)
Phương thức này chấp nhận hai tham số -
shader - Bạn phải truyền đối tượng đổ bóng đã tạo dưới dạng một tham số.
Source - Bạn phải truyền mã chương trình đổ bóng ở định dạng chuỗi.
Biên soạn chương trình
Để biên dịch chương trình, bạn phải sử dụng phương pháp compileShader(). Cú pháp của nó như sau:
compileShader(Object shader)
Phương thức này chấp nhận đối tượng chương trình đổ bóng như một tham số. Sau khi tạo một đối tượng chương trình đổ bóng, hãy đính kèm mã nguồn vào nó và chuyển đối tượng đó vào phương thức này.
Đoạn mã sau đây cho biết cách tạo và biên dịch bộ đổ bóng đỉnh cũng như bộ đổ bóng phân đoạn để tạo hình tam giác.
// Vertex Shader
var vertCode =
'attribute vec3 coordinates;' +
'void main(void) {' +
' gl_Position = vec4(coordinates, 1.0);' +
'}';
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
// Fragment Shader
var fragCode =
'void main(void) {' +
' gl_FragColor = vec4(0, 0.8, 0, 1);' +
'}';
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
Chương trình kết hợp
Sau khi tạo và biên dịch cả hai chương trình đổ bóng, bạn cần tạo một chương trình kết hợp có chứa cả hai trình đổ bóng (đỉnh & đoạn). Các bước sau cần được thực hiện:
- Tạo một đối tượng chương trình
- Đính kèm cả hai bộ đổ bóng
- Liên kết cả hai bộ đổ bóng
- Sử dụng chương trình
Tạo một đối tượng chương trình
Tạo một đối tượng chương trình bằng phương pháp createProgram(). Nó sẽ trả về một đối tượng chương trình trống. Đây là cú pháp của nó -
createProgram();
Đính kèm Shader
Đính kèm bộ đổ bóng vào đối tượng chương trình đã tạo bằng phương thức attachShader(). Cú pháp của nó như sau:
attachShader(Object program, Object shader);
Phương thức này chấp nhận hai tham số -
Program - Truyền đối tượng chương trình rỗng đã tạo dưới dạng một tham số.
Shader - Chuyển một trong các chương trình đổ bóng đã biên dịch (đổ bóng đỉnh, đổ bóng phân mảnh)
Note - Bạn cần phải gắn cả hai shader bằng cách sử dụng phương pháp này.
Liên kết các Shader
Liên kết các bộ đổ bóng bằng phương pháp linkProgram(), bằng cách chuyển đối tượng chương trình mà bạn đã đính kèm các bộ đổ bóng. Cú pháp của nó như sau:
linkProgram(shaderProgram);
Sử dụng chương trình
WebGL cung cấp một phương thức được gọi là useProgram(). Bạn cần chuyển chương trình được liên kết tới nó. Cú pháp của nó như sau:
useProgram(shaderProgram);
Đoạn mã sau cho biết cách tạo, liên kết và sử dụng chương trình đổ bóng kết hợp.
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);