Bagaimana menerapkan riak jenis ini dengan shader fragmen GLSL?

11

Jadi saya sudah menerapkan bagian refleksi:

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;
}
}

sumber

Sekarang pertanyaannya adalah bagaimana riak ini diimplementasikan?

cepro
sumber
3
Ini bukan jawaban yang lengkap, tetapi serangkaian petunjuk: Anda perlu seragam untuk "menghidupkan" efeknya - yaitu variabel seperti waktu. Dengan menggunakan timenilai itu, Anda dapat menggeser uv.xydengan (sin(time),cos(time))vektor offset. Tentu saja, Anda harus mengetahui amplitudo dari offset sinus dan cosinus. Saya akan mulai dengan hanya mengimbangi yang uv.ypertama dan melihat bagaimana saya dapat menyesuaikan efek lebih lanjut.
teodron
Terima kasih banyak atas petunjuk ini. Ternyata inilah yang saya butuhkan setelah mencoba implementasi @ LeFauve.
cepro

Jawaban:

11

Saya mencoba menerapkan apa yang disarankan teodron:

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;
    }
}

Itu terlihat cukup dekat (sulit untuk mengatakan tanpa gambar dasar) tetapi Anda dapat mengubah parameter.

Anda dapat melihatnya beraksi di sana: https://www.shadertoy.com/view/Xll3R7

Beberapa komentar:

  • Saya harus membalik koordinat y karena saya mendapatkan gambar terbalik, tetapi mungkin tergantung dari apa yang Anda berikan ke resolution.xy; jika hasilnya terbalik untuk Anda, cukup batalkan uv.y
  • Saya mengubah deklarasi seragam Anda sehingga berfungsi dengan shadertoy. Anda dapat mengabaikan perubahan itu.
  • Namun Anda perlu menambahkan seragam yang menyediakan waktu dan menggunakannya sebagai ganti iGlobalTime (yang merupakan waktu dalam detik)
  • Saya menambahkan efek pasang karena sepertinya ada satu pada contoh Anda tetapi sulit untuk mengatakannya (lihat variabel sepoffset). Anda dapat menghapusnya jika Anda tidak menyukainya
  • Saya menghapus warna overlay karena tidak terlihat bagus, dan contoh Anda tidak memilikinya
  • Untuk mengubah efek sesuai selera Anda:
    • ubah faktor iGlobalTime untuk mempercepat / memperlambat efek (Anda dapat mengubah masing-masing secara terpisah jika Anda mau, misalkan mempercepat gerakan x dan memperlambat gerakan y)
    • ubah faktor cos () untuk memperbesar / memperkecil efek

EDIT: Saya mengubah yoffset untuk memasukkan modifikasi dari @cepro

LeFauve
sumber
1
Usaha yang bagus! +1
teodron
3
Terima kasih untuk bantuannya :). Ini benar-benar memberikan hasil yang cukup dekat. Tapi saya pikir itu salah satu bahan terakhir. Perhatikan, dalam gambar, bahwa semakin dekat riak-riak itu dengan kamera (bagian bawah layar) semakin besar riasannya (diregangkan secara vertikal). Jadi mungkin kita perlu skala y diimbangi oleh uv.y? float yoffset = ((0.3 - uv.y) /0.3) * 0.05 * (1.0 + cos (iGlobalTime * 3.0 + 50.0 * uv.y)) ;. Saya sudah mencoba ini dan saya agak suka hasilnya.
cepro
Tangkapan yang bagus untuk riak yang lebih dekat @cepro. Saya melewatkannya
LeFauve
IMO ada yang salah dengan gelombang pettern yang dimodifikasi. Sementara ombak meningkat untuk saya, mereka memiliki pola "cermin" aneh di dalamnya (GTX 680 di Chrome terbaru).
Mario