Làm thế nào bạn sẽ thực hiện hiệu ứng quang sai màu với shader?
Liệu kết xuất của thế giới với các khoảng cách lấy nét khác nhau cho mỗi màu sẽ giải quyết vấn đề (có thể với việc chỉ sử dụng một lần hiển thị độ sâu)?
Làm thế nào bạn sẽ thực hiện hiệu ứng quang sai màu với shader?
Liệu kết xuất của thế giới với các khoảng cách lấy nét khác nhau cho mỗi màu sẽ giải quyết vấn đề (có thể với việc chỉ sử dụng một lần hiển thị độ sâu)?
Câu trả lời:
Hiện tượng quang sai được tạo ra khi một ống kính không thể tập trung mọi màu vào cùng một tiêu điểm. Một cách đơn giản để giả mạo hiệu ứng này và hiển thị nó dưới dạng hậu xử lý toàn màn hình nhanh, là áp dụng bù cho mỗi kênh màu trong một shader mảnh.
Bằng cách sử dụng một độ lệch khác nhau cho mỗi kênh, bạn có thể đạt được một bản fax hợp lý về hiệu ứng mong muốn. Một ví dụ về kỹ thuật này có thể được tìm thấy ở đây ; shader mảnh sẽ trông giống như thế này:
void main () {
// Previously, you'd have rendered your complete scene into a texture
// bound to "fullScreenTexture."
vec4 rValue = texture2D(fullscreenTexture, gl_TexCoords[0] - rOffset);
vec4 gValue = texture2D(fullscreenTexture, gl_TexCoords[0] - gOffset);
vec4 bValue = texture2D(fullscreenTexture, gl_TexCoords[0] - bOffset);
// Combine the offset colors.
gl_FragColor = vec4(rValue.r, gValue.g, bValue.b, 1.0);
}
Cách hack đơn giản này không thực sự tính đến thực tế là quang sai màu là hiệu ứng thấu kính, mặc dù: để có được một mô phỏng tốt hơn, bạn thực sự muốn kết xuất một cái gì đó để hoạt động như ống kính. Điều này tương tự như cách bạn kết xuất các vật thể phản chiếu hoặc khúc xạ. Do đó, một shader phản xạ / khúc xạ điển hình có thể là cơ sở để thực hiện quang sai màu.
Thông thường, bạn sẽ tính toán một vectơ khúc xạ duy nhất dựa trên vectơ xem và một số chỉ số khúc xạ được xác định , sử dụng hàm khúc xạ của GLSL trong một shader đỉnh:
void main () {
// ...
// RefractionVector is a varying vec3.
// 'ratio' is the ratio of the two indices of refraction.
RefractionVector = refract(incidentVector, normalVector, ratio);
// ...
}
Sau đó, bạn sử dụng vectơ đó trong một shader mảnh để thực hiện tra cứu kết cấu khối (vào bản đồ môi trường). Thông thường, điều này cũng được thực hiện cùng với hiệu ứng phản chiếu và kết hợp sử dụng thuật ngữ Fresnel được tính toán .
Để mô phỏng quang sai màu, sau đó, bạn có thể thực hiện ba phép tính vectơ khúc xạ khác nhau , mỗi phép tính hơi lệch qua các chỉ số khúc xạ khác nhau, trong shader đỉnh:
void main () {
// ...
// RefractionVector is a varying vec3, as above.
// 'ratioR,' et cetera, is the ratio of indices of refraction for
// the red, green and blue components respectively.
RedRefractionVector = refract(incidentVector, normalVector, ratioR);
GreenRefractionVector = refract(incidentVector, normalVector, ratioG);
BlueRefractionVector = refract(incidentVector, normalVector, ratioB);
// ...
}
Ba vectơ khác nhau đó có thể được sử dụng để thực hiện ba tra cứu bản đồ khối khác nhau, có thể được trộn lẫn với nhau tương tự như cách các màu được trộn trong ví dụ đơn giản:
void main () {
vec3 color;
color.r = vec3(textureCube(EnvironmentMap, RedRefractionVector)).r;
color.g = vec3(textureCube(EnvironmentMap, GreenRefractionVector)).g;
color.b = vec3(textureCube(EnvironmentMap, BlueRefractionVector)).b;
gl_FragColor = vec4(color, 1.0);
}
Để biết thêm chi tiết, Sách Cam OpenGL có sẵn và chứa một ví dụ về các hiệu ứng phản xạ và khúc xạ cơ bản, cũng như một ví dụ về hiệu ứng quang sai màu.