Fragment Shader là một giai đoạn có thể lập trình của pipeline đồ họa, xác định màu sắc cuối cùng của mỗi mảnh (pixel) của hình ảnh. Theo Khronos Group, 2025, trình đổ bóng mảnh nhận dữ liệu nội suy từ Vertex Shader và thực hiện các tính toán chiếu sáng, tạo họa tiết và hiệu ứng màu sắc. Fragment Shader được gọi cho mỗi pixel, khiến nó trở thành giai đoạn tốn nhiều tài nguyên nhất trong pipeline đồ họa.
Những điểm chính
Fragment Shader (trình đổ bóng mảnh hay pixel) là một giai đoạn có thể lập trình của pipeline đồ họa tính toán màu sắc cuối cùng của mỗi mảnh hình ảnh. Một mảnh là một pixel tiềm năng trở thành pixel hiển thị trên màn hình sau khi vượt qua các kiểm tra độ sâu và stencil.
Fragment Shader thực thi sau quá trình raster hóa, khi các nguyên thủy 3D (tam giác) đã được chuyển đổi thành tập hợp các mảnh. Trình đổ bóng nhận các thuộc tính nội suy — tọa độ họa tiết, pháp tuyến, màu sắc đã được tính toán trong Vertex Shader cho các đỉnh tam giác và nội suy tuyến tính cho mỗi pixel bên trong tam giác.
Trước khi xuất hiện các trình đổ bóng có thể lập trình (trước DirectX 8 / OpenGL 2.0), việc tính toán màu pixel được thực hiện bởi một pipeline cố định với một tập hợp hạn chế các thao tác. Fragment Shader có thể lập trình xuất hiện vào năm 2001 và mở rộng triệt để khả năng đồ họa: các nhà phát triển có được toàn quyền kiểm soát màu sắc của mỗi pixel, cho phép triển khai chiếu sáng chân thực, vật liệu phức tạp và các hiệu ứng hậu kỳ.
Fragment Shader được GPU khởi chạy cho mỗi mảnh do bộ raster hóa tạo ra. Mỗi lần gọi trình đổ bóng xử lý một mảnh, đọc dữ liệu đầu vào, thực thi mã người dùng và ghi giá trị đầu ra — màu sắc của mảnh ở định dạng RGBA.
Dữ liệu đầu vào của Fragment Shader bao gồm các thuộc tính nội suy từ Vertex Shader (tọa độ họa tiết, pháp tuyến, màu sắc), biến uniform (nguồn sáng, ma trận) và bộ lấy mẫu họa tiết. Dữ liệu đầu ra là vector màu (gl_FragColor trong OpenGL ES 2.0 hoặc biến do người dùng định nghĩa trong ES 3.0), được ghi vào bộ đệm màu.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uTexture;
out vec4 fragColor;
void main() {
fragColor = texture(uTexture, vTexCoord);
}
Fragment Shader chịu trách nhiệm về chất lượng hình ảnh. Tất cả các hiệu ứng mà người dùng thấy trên màn hình — màu sắc, bóng đổ, phản chiếu, độ trong suốt — đều được tính toán ở giai đoạn này của pipeline đồ họa.
Thao tác phổ biến nhất là lấy mẫu màu từ họa tiết bằng tọa độ UV nội suy. Sampler2D và hàm texture() cho phép lấy màu pixel từ atlas họa tiết. Lọc (bilinear, trilinear, anisotropic) được kiểm soát thông qua tham số bộ lấy mẫu và ảnh hưởng đến độ sắc nét của hình ảnh ở các góc nhìn khác nhau.
Mô hình chiếu sáng Phong được tính toán trong Fragment Shader cho mỗi pixel, tạo ra các điểm sáng mượt hơn so với chiếu sáng đỉnh (tô bóng Gouraud). Chiếu sáng Phong bao gồm ba thành phần: môi trường (ambient), khuếch tán (diffuse) và phản chiếu (specular).
// Fragment shader with Phong lighting
in vec3 vNormal;
in vec3 vPosition;
uniform vec3 uLightDir;
uniform vec3 uLightColor;
void main() {
vec3 norm = normalize(vNormal);
float diff = max(dot(norm, uLightDir), 0.0);
fragColor = vec4(uLightColor * diff, 1.0);
}
Fragment Shader cho phép áp dụng xử lý hậu kỳ: hiệu chỉnh màu qua bảng tra cứu (LUT), làm mờ (blur), hiệu ứng phát sáng (bloom) và tonemapping cho kết xuất HDR. Tất cả các hiệu ứng này hoạt động ở cấp độ pixel và thực thi trong thời gian thực.
Hiệu suất của Fragment Shader là yếu tố chính giới hạn FPS trong các game di động hiện đại. Vì trình đổ bóng được gọi cho mỗi pixel, ngay cả sự gia tăng nhỏ về độ phức tạp mã cũng có thể dẫn đến giảm tốc độ khung hình đáng kể.
Đối với GPU di động (Qualcomm Adreno, ARM Mali), khuyến nghị: sử dụng mediump precision cho biến float, kết hợp các lần lấy mẫu họa tiết, áp dụng kiểm tra early-z để loại bỏ các mảnh không nhìn thấy trước khi thực thi trình đổ bóng.
| Phương pháp | Mô tả | Lợi ích |
|---|---|---|
| Mediump precision | Độ chính xác 16 bit thay vì 32 bit | Lên đến 2x tốc độ |
| Early-Z | Kiểm tra độ sâu trước trình đổ bóng | Giảm số lần gọi |
| Texture atlasing | Một họa tiết thay vì nhiều | Ít chuyển đổi hơn |
Cả hai loại trình đổ bóng đều có thể được lập trình bởi nhà phát triển, nhưng chúng hoạt động ở các giai đoạn khác nhau của pipeline và giải quyết các tác vụ khác nhau. Fragment Shader tốn nhiều tài nguyên hơn đáng kể do số lần gọi.
| Tham số | Fragment Shader | Vertex Shader |
|---|---|---|
| Số lần gọi | Hàng triệu (độ phân giải màn hình) | Hàng nghìn (số đỉnh) |
| Dữ liệu đầu vào | Thuộc tính nội suy | Thuộc tính đỉnh |
| Chức năng chính | Tính toán màu mảnh | Biến đổi hình học |
| Truy cập họa tiết | Đầy đủ (nhiều bộ lấy mẫu) | Hạn chế |
| Tác động đến hiệu suất | Cao (phụ thuộc độ phân giải) | Trung bình (phụ thuộc hình học) |
Fragment Shader có thể đơn giản (lấy mẫu họa tiết) hoặc phức tạp (chiếu sáng nhiều lớp). Hãy xem xét hai ví dụ thực tế: tạo họa tiết cơ bản và hiệu ứng chuyển màu sử dụng thời gian.
#version 300 es
precision mediump float;
in vec2 vTexCoord;
in vec3 vColor;
uniform sampler2D uDiffuseMap;
out vec4 fragColor;
void main() {
vec4 texColor = texture(uDiffuseMap, vTexCoord);
fragColor = texColor * vec4(vColor, 1.0);
}
#include <metal_stdlib>
using namespace metal;
struct FragmentIn {
float2 texCoord;
float3 normal;
};
fragment float4
fragmentMain(FragmentIn in [[stage_in]],
texture2d<float> tex [[texture(0)]]) {
constexpr sampler s(filter = linear);
float4 color = tex.sample(s, in.texCoord);
return color;
}
Câu hỏi thường gặp
Fragment Shader là một chương trình nhỏ trên GPU xác định màu sắc của mỗi pixel trên màn hình. Nếu Vertex Shader xác định hình dạng của đối tượng, thì Fragment Shader xác định đối tượng đó trông như thế nào — họa tiết, chiếu sáng, màu sắc.
Fragment Shader được gọi cho mỗi pixel trên màn hình. Trên thiết bị có độ phân giải 2532x1170 (iPhone) con số này gần như 3 triệu lần gọi mỗi khung hình. Ở 60 FPS, trình đổ bóng thực thi 180 triệu lần mỗi giây, đòi hỏi sức mạnh tính toán rất lớn.
Trong Fragment Shader triển khai: tạo họa tiết, chiếu sáng (Phong, PBR), bóng đổ, phản chiếu, khúc xạ, bloom, độ sâu trường ảnh, hiệu chỉnh màu, bộ lọc LUT và tạo họa tiết thủ tục.
Sử dụng mediump precision cho float, giảm số lần lấy mẫu họa tiết, áp dụng early-z culling, kết hợp các thao tác trình đổ bóng và tránh rẽ nhánh có điều kiện bên trong trình đổ bóng.
Chúng giống nhau. Thuật ngữ Fragment Shader được sử dụng trong OpenGL / Vulkan, còn Pixel Shader được sử dụng trong thuật ngữ Direct3D (Microsoft). Về chức năng, chúng giống hệt nhau: cả hai đều tính toán màu sắc của mỗi mảnh/pixel.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm