Làm cách nào để thực hiện loại gợn này với trình đổ bóng mảnh GLSL?


11

Vì vậy, tôi đã thực hiện phần phản ánh:

uniform sampler2D texture;
uniform vec2 resolution;
uniform vec3 overlayColor;

void main()
{
vec2 uv = gl_FragCoord.xy / resolution.xy;

if (uv.y > 0.3)// is air - no reflection or effect
{
    gl_FragColor = texture2D(texture, vec2(uv.x, uv.y));
}
else
{
    // Compute the mirror effect.
    vec4 color = texture2D(texture, vec2(uv.x, 0.6 - uv.y));
    // 
    vec4 finalColor = vec4(mix(color.rgb, overlayColor, 0.25), 1.0);
    gl_FragColor = finalColor;
}
}

nguồn

Bây giờ câu hỏi là làm thế nào những gợn sóng được thực hiện?


3
Đây không phải là câu trả lời hoàn chỉnh, nhưng một loạt các gợi ý: bạn cần một bộ đồng phục để "làm động" hiệu ứng - tức là một biến giống như thời gian. Sử dụng timegiá trị đó , bạn có thể dịch chuyển uv.xyvới một (sin(time),cos(time))vectơ bù. Tất nhiên, bạn phải tìm ra biên độ của các độ lệch sin và cos. Tôi sẽ bắt đầu chỉ bằng cách bù đắp uv.yđầu tiên và xem làm thế nào tôi có thể điều chỉnh hiệu ứng hơn nữa.
teodron

Cảm ơn bạn rất nhiều vì những gợi ý này. Hóa ra đây là thứ tôi cần sau khi thử triển khai @ LeFauve.
cepro

Câu trả lời:


11

Tôi đã cố gắng thực hiện những gì teodron đề xuất:

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    float sepoffset = 0.005*cos(iGlobalTime*3.0);
    if (uv.y > 0.3 + sepoffset)// is air - no reflection or effect
    {
        gl_FragColor = texture2D(texture, vec2(uv.x, -uv.y));
    }
    else
    {
        // Compute the mirror effect.
        float xoffset = 0.005*cos(iGlobalTime*3.0+200.0*uv.y);
        //float yoffset = 0.05*(1.0+cos(iGlobalTime*3.0+50.0*uv.y));
        float yoffset = ((0.3 - uv.y)/0.3) * 0.05*(1.0+cos(iGlobalTime*3.0+50.0*uv.y));
        vec4 color = texture2D(texture, vec2(uv.x+xoffset , -1.0*(0.6 - uv.y+ yoffset)));
        // 
        //vec4 finalColor = vec4(mix(color.rgb, overlayColor, 0.25), 1.0);
        gl_FragColor = color;
    }
}

Nó trông khá gần (thật khó để nói nếu không có hình ảnh cơ sở) nhưng bạn có thể điều chỉnh các tham số.

Bạn có thể thấy nó hoạt động ở đó: https://www.shadertoy.com/view/Xll3R7

Một số nhận xét:

  • Tôi đã phải đảo ngược tọa độ y vì tôi đã làm cho hình ảnh bị lộn ngược, nhưng nó có thể phụ thuộc vào những gì bạn chuyển vào độ phân giải.xy; nếu kết quả được đảo ngược cho bạn, chỉ cần đảo ngược uv.y
  • Tôi đã thay đổi khai báo đồng phục của bạn để nó hoạt động với shadertoy. Bạn có thể bỏ qua những thay đổi đó.
  • Tuy nhiên, bạn sẽ cần thêm đồng phục cung cấp thời gian và sử dụng nó thay cho iGlobalTime (đó là thời gian tính bằng giây)
  • Tôi đã thêm một hiệu ứng thủy triều vì có vẻ như có một ví dụ trong ví dụ của bạn nhưng thật khó để nói (xem biến sepoffset). Bạn có thể xóa nó nếu bạn không thích nó
  • Tôi đã xóa màu lớp phủ vì nó không đẹp và ví dụ của bạn không có màu
  • Để điều chỉnh hiệu ứng theo sở thích của bạn:
    • thay đổi hệ số của iGlobalTime thành tăng tốc / làm chậm hiệu ứng (bạn có thể thay đổi từng yếu tố một cách riêng biệt nếu muốn, giả sử tăng tốc độ chuyển động x và làm chậm chuyển động y)
    • thay đổi hệ số cos () để khuếch đại / làm giảm hiệu ứng

EDIT: Tôi đã thay đổi yoffset để bao gồm sửa đổi từ @cepro


1
Nỗ lực lớn lao! +1
teodron

3
Cảm ơn sự giúp đỡ của bạn :). Điều này thực sự cho một kết quả khá gần. Nhưng tôi nghĩ rằng nó bỏ lỡ một thành phần cuối cùng. Lưu ý, trong hình, những gợn sóng đó càng gần máy ảnh (phía dưới màn hình) thì chúng càng lớn (kéo dài theo chiều dọc). Vì vậy, có lẽ chúng ta cần phải chia tỷ lệ bù y bằng uv.y? phao nổi = Tôi đã thử điều này và tôi giống như kết quả.
cepro

Bắt tốt cho các gợn sóng gần hơn @cepro. Tôi đã bỏ lỡ nó
LeFauve

IMO có gì đó không đúng với pettern sóng sửa đổi. Trong khi sóng tăng đối với tôi, họ đã có mẫu "nhân đôi" kỳ lạ đó (GTX 680 trong Chrome mới nhất).
Mario
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.