Đây là cách tôi sẽ làm điều này. Trước tiên, hãy chắc chắn rằng bạn có UVs hoặc coords thế giới của đối tượng (mà bạn có thể đi qua từ shader đỉnh của bạn) có sẵn cho bạn. Nếu nó chỉ là một nền tảng, bạn cũng có thể chỉ sử dụng các đoạn coord ( gl_FragCoord
).
Ví dụ, giả sử chúng ta đang sử dụng các tia UV. Một shader mảnh chỉ với:
gl_FragColor = vec4(vec3(uv.x),1.0);
sẽ trông giống như:
![X UV](https://i.stack.imgur.com/OYekr.png)
Và tương tự, gl_FragColor = vec4(vec3(uv.y),1.0);
sẽ giống như:
![Y UV](https://i.stack.imgur.com/nHZHH.png)
Nếu bạn đang sử dụng hợp đồng thế giới hoặc hợp đồng phân đoạn, bạn vẫn có thể chia tỷ lệ và dịch để bình thường hóa thành (0,0) -> (1, 1), nhưng dù sao chúng ta cũng cần phải mở rộng quy mô và dịch lại để bạn có thể bỏ qua bước đó Thay vào đó, các coords của bạn nằm trong khoảng từ (-1.0, -1.0) đến (1.0, 1.0) để làm cho các bước tiếp theo dễ dàng hơn, như vậy:uv = 2.0 * uv - 1.0;
Bây giờ trước khi chúng ta tiến xa hơn, hãy tạo một gradient xuyên tâm siêu đơn giản. Hãy nhớ rằng phương trình của một đường tròn là x² + y² = r². Vì vậy, sử dụng các UV biến đổi như một hệ tọa độ, một vòng tròn đơn vị (r = 1) có thể được tạo ra gl_FragColor = vec4(vec3(uv.x * uv.x + uv.y * uv.y),1.0);
và sẽ trông giống như:
![R UV](https://i.stack.imgur.com/ayZ4U.png)
Bước tiếp theo là hoạt hình. Để làm điều này, bạn chỉ cần chơi xung quanh với giá trị "r" và thay đổi bán kính. Bạn không cần phải lo lắng về việc kẹp các giá trị màu giữa 0,0 và 1,0 vì dù sao điều đó cũng tự động xảy ra.
Tất cả cùng nhau nó sẽ trông giống như thế này:
uniform vec2 screenSize;
uniform float time;
void main(void) {
// Scale to UV space coords
vec2 uv = gl_FragCoord.xy / screenSize;
// Transform to [(-1.0, -1.0), (1.0, 1.0)] range
uv = 2.0 * uv - 1.0;
// Have something to vary the radius (can also just be a linear counter (time))
float wave = sin(time);
// Calculate how near to the center (0.0) or edge (1.0) this fragment is
float circle = uv.x * uv.x + uv.y * uv.y;
// Put it all together
gl_FragColor = vec4(vec3(circle + wave),1.0);
}
Tất nhiên bạn có thể đơn giản hóa rất nhiều thứ và chơi xung quanh nhiều hơn với các biến và hằng. Đây là bản demo trực tiếp của tôi đang làm điều đó: https://www.shadertoy.com/view/4sjXWh
Biên tập:
Nếu bạn muốn làm điều này với các màu sắc khác nhau, may mắn thay, có một giải pháp dễ dàng! Chuyển màu của bạn dưới dạng đồng phục (hoặc mã hóa chúng trong shader mảnh thực tế) và thay đổi dòng cuối cùng thành này:
gl_FragColor = mix(color1, color2, circle + wave);
color1
và color2
đều là vec4
s. Đây là hành động: https://www.shadertoy.com/view/XsjSW1