Lưu ý: Bài viết này dựa vào sách OpenGL ES 2.0 programming guide kết hợp với các ví dụ mới được code lại, các thuật ngữ cũng được lược giản lại để dễ đọc và hiểu hơn

GLES được xử lý bằng cách kết hợp GLES API với ngôn ngữ hiệu ứng (shading language) được gọi là GLES Shading Language (ESSL)

Trình tự xử lý GLES 2.0 (nguồn: OpenGL ES 2.0 programming guide)

Hiệu ứng Vertex - Vertex Shader

Vertex shader dùng để xử lý các điểm (có nhiều cách gọi: điểm - đỉnh - nút).

Một vertex shader gồm có các thành phần:

  • Attributes (thuộc tính) - Với mỗi dữ liệu vertex được lưu trữ bằng mảng vertex
  • Uniforms (cách thức) - Dữ liệu hằng (constant data) được dùng bởi vertex shader
  • Samplers (mẫu thử) - định dạng của cách thức (type of uniforms) mà nó thể hiện textures được dùng bởi vertex shader. Đây là một tùy chọn không bắt buộc
  • Shader program - Chương trình chính của vertex shader mô tả cách hoạt động và thực hiện xử lý vertex

Kết quả xuất ra là varying variables (các biến biến đổi). Vào giai đoạn primitive - rasterization (chia thành dạng ma trận pixel nguyên thủy), các giá trị varying sẽ được tính toán và tạo ra các fragment (mảnh) sau đó chuyển nó đến fragment shader. Phương thức được dùng để tạo ra các giá trị được gọi là interpolation (nội suy).

Vertex Shader GLES 2.0 (nguồn: OpenGL ES 2.0 programming guide)

Vertex shader dùng các phép tính vertex chẳng hạn như phép dịch chuyển vị trí bằng ma trận, phương trình tính toán ánh sáng màu cho mỗi vertex, hoặc tạo và di chuyển các texture (hoa văn) trên các vertex.

Ta phân tích một vertex shader mẫu:

uniform mat4 u_mvpMatrix;

attribute vec4 a_position;
attribute vec4 a_color;

varying vec4 v_color;

void main()
{
    v_color = a_color;
    gl_Position = u_mvpMatrix * a_position;
}

Giải thích:

  • u_mvpMatrix lưu trữ ma trận model-view-projection
  • a_position là giá trị đầu vào vị trí của vertex
  • a_color là giá trị đầu vào màu của vertex
  • v_color là giá trị đầu ra màu của từng vertex
  • gl_Position là biến được tạo sẵn một cách tự động, các phép tính sau khi tính toán xong sẽ được lưu lại vào biến này.
  • Các shader đều có một hàm main là entry point
  • Giá trị v_color được gán bằng a_color
  • Giá trị gl_Position được tính bằng phép di chuyển vị trí của vertex

Primitive Assembly

Primitive (nguyên thủy) là geometric object (vật thể hình học) có thể được vẽ bằng các lệnh GLES. Các lệnh này bao gồm các mô tả về loại và hình cần vẽ.

Chẳng hạn, các vật thể sẽ được các nhỏ thành các hình ảnh đơn giản hơn có thể vẽ như hình tam giác, đường thẳng hoặc một chấm nhỏ. Với mỗi primitive, chúng được xác định bởi một view frustum (khung nhìn chóp cụt). Nếu vật thể nằm giữa view sẽ được cắt lại, nếu nằm ngoài sẽ bị bỏ ra khỏi view. Sau đó vật thể sẽ được xác định ở vị trí nào trên màn hình. Phép toán culling (phân loại) sẽ thực hiện primitives nào nằm trước hoặc nằm sau.

Mô tả về view frustum (nguồn: Unreal Engine document 4.27)

Rasterization

Đây là giai đoạn mà các primitive được vẽ. Rasterization (phép chia thành ma trận pixel) sẽ chuyển đổi primitive thành các mảnh hai chiều (two-dimensional fragments) mà các mảnh này dễ dàng được vẽ trên màn hình.

 

Mô tả về Rasterization (nguồn: OpenGL ES 2.0 programming guide)

Hiệu ứng Fragment - Fragment Shader

Fragment shader dùng để xử lý các mảnh.

Một fragment shader gồm có các thành phần:

  • Varying variables (các biến biến đổi): Kết quả xuất ra của vertex shader được tạo ra bởi giai đoạn rasterization của các mãnh bằng phương pháp interpolation (nội suy).
  • Uniforms (cách thức) - Dữ liệu hằng (constant data) được dùng bởi fragment shader
  • Samplers (mẫu thử) - định dạng của cách thức (type of uniforms) mà nó thể hiện textures được dùng bởi fragment shader.
  • Shader program - Chương trình chính của fragment shader mô tả cách hoạt động và thực hiện xử lý fragment

Fragement shader có thể tạo ra hoặc loại bỏ giá trị màu sắc được dùng chẳng hạn gl_FragColor. Màu sắc, độ sâu, stencil (khuôn tô) và tọa độ trên hệ trục (x, y) được tạo từ giai đoạn rasterization trở thành tham số đầu vào cho từng fragment.

Fragment Shader GLES 2.0 (nguồn: OpenGL ES 2.0 programming guide)

Ta phân tích một fragment shader mẫu:

precision mediump float;

varying vec4 v_color;

void main()
{
    gl_FragColor = v_color;
}

Giải thích:

  • precision mediump thể hiện độ chính xác của kết quả xuất ra.
  • v_color mô tả đầu vào cho fragment shader. Biến varying của fragment shader phải cùng tập (same set) với vertex shader.
  • Không có kết quả xuất ra cho fragment shader
  • Biến gl_FragColor là kết quả duy nhất, được gán giá trị từ v_color.

Xử lý trên từng fragment

Giai đoạn tiếp theo là xử lý từng fragment. Fragment được tạo ra từ giai đoạn rasterization bao gồm tọa độ (x, y) trên hệ trục nằm trên màn hình chỉ có thể được điều chỉnh trên pixel trong framebuffer (bộ nhớ đệm cho khung hình tiếp theo).

Các xử lý trên từng fragment (nguồn: OpenGL ES 2.0 programming guide)

Các xử lý bao gồm:

  • Pixel ownership test (kiểm tra quyền sở hữu điểm ảnh): kiểm tra nếu điểm ảnh nằm tại vị trí (x, y) trong khung hình hiện tại. Nó cho phép window system (cửa sổ của hệ thống) quản lý pixel trong framebuffer thuộc về ngữ cảnh hiện tại của GLES.
  • Scissor test (kiểm tra nằm trong khung hình): kiểm tra bằng cách cắt thành một khung hình chữ nhật và xác định xem fragment có nằm trong khung đó hay không. Nếu không thì sẽ loại bỏ fragment đó.
  • Stencil testdepth test (kiểm tra khuôn tô và độ sâu): kiểm tra khuôn tô và độ sâu giá trị của từng fragment nếu không thì sẽ bị loại bỏ
  • Dithering (phối màu) được dùng để giảm thiểu các artifact (sai lệch) có thể xảy ra khi dùng với độ chính xác thấp để lưu trữ các giá trị màu trong framebuffer

Sau khi kết thúc giai đoạn này, các fragment được xử lý hay loại bỏ đều được đưa vào framebuffer tại tọa độ (x, y). Các fragment được viết có thể tương thích với các lớp mask (mặt nạ) có hoặc không. Các lớp mặt nạ cho phép điều chỉnh tốt hơn với các giá trị đến buffer tương thích.

Lưu ý: GLES 2.0 và 3.0 đều không có Alpha test và LogicOp.

Comments


Comments are closed