Bagaimana cara menghidupkan tekstur air 2d top down abstrak?

24

Saat ini saya menerapkan permainan dengan pemandangan samudra. Saya menggunakan yang berikut, sedikit tekstur abstrak:masukkan deskripsi gambar di sini

Tekstur sebenarnya transparan, saya menambahkan warna seperti hijau untuk kejelasan.

Masalah saya sekarang adalah, bahwa saya tidak tahu bagaimana menghidupkan tekstur ini sehingga airnya terlihat bagus. Saya mencoba untuk memindahkan tekstur dengan gelombang dosa: texture.y += sin(angle). Tentu saja sekarang seluruh tekstur bergerak yang terlihat agak tidak realistis. Hal berikutnya yang saya coba adalah menambahkan layer lain dan menerapkan efek paralaks. Sehingga pantulan di bawah permukaan air juga akan bergerak, tetapi jauh lebih lambat. Terlihat sedikit lebih baik tetapi masih belum ... cukup bagus.

Saya pikir animasi yang paling baik adalah, jika sel-sel individu akan membesar dan berkontraksi, seperti jaring atau sepotong kain. Bayangkan jika seseorang akan sedikit menarik pada satu titik sel-sel ini dan sel tetangga akan mengembang dan sel yang saya tarik ke arah (atau mendorong ke) akan berkontraksi. Jenis seperti web pegas (?). Tapi saya tidak tahu bagaimana menerapkan sesuatu seperti ini:

  • Apa model matematika untuk ini? Sesuatu dengan pegas, di mana pasukan mendorong / menarik?
  • Dan jika demikian, bagaimana cara memetakan model ini ke tekstur yang diberikan? Menjaga semua kurva dan apa yang tidak ...

(Saya juga terbuka untuk berbagai ide / jawaban tentang cara menghidupkan tekstur yang diberikan. Realisme bukan intinya di sini, hanya beberapa air yang tampak seperti gerakan ...)

Solusi dari DMGregory

Saya memposting contoh libgdx di posting ini: animasi air 2d bergerigi dan tidak mulus (lihat jawaban tentang penyaringan tekstur)

morpheus05
sumber

Jawaban:

41

Cara umum ini dilakukan adalah menggunakan pencarian tekstur tidak langsung dalam shader untuk mengubah tekstur tampilan:

Animasi gif menampilkan animasi air

Di sini saya menggunakan tekstur dengan beberapa noise warna frekuensi rendah (memasang gumpalan halus warna acak), dan menggulirnya melintasi geometri tampilan seiring waktu.

masukkan deskripsi gambar di sini

Alih-alih menggambar warna dari tekstur ini, saya malah mengambil saluran merah & hijau dan mengurangi 0.5funtuk mengubahnya menjadi vektor 2D pseudorandom yang berubah dengan lancar seiring waktu & ruang.

Saya kemudian dapat menambahkan beberapa kecil dari vektor ini ke koordinat UV saya, sebelum pengambilan sampel dari tekstur air utama. Ini menggeser bagian dari tekstur yang kita baca & tampilkan, membengkokkannya.

Dengan rata-rata dua sampel dari kebisingan ini, menggulir ke arah yang berlawanan, kita dapat menyembunyikan arah gerakan sehingga hanya terlihat seperti tumpah tanpa tujuan.

Di Unity, shader akan terlihat seperti ini - seharusnya cukup sederhana untuk menerjemahkan ke bahasa shader pilihan Anda:

fixed4 frag (v2f i) : SV_Target
{               
    float2 waveUV = i.uv * _NoiseScale;
    float2 travel = _NoiseScrollVelocity * _Time.x;

    float2 uv = i.uv;
    uv += _Distortion * (tex2D(_Noise, waveUV + travel).rg - 0.5f);
    waveUV += 0.2f; // Force an offset between the two samples.
    uv += _Distortion * (tex2D(_Noise, waveUV - travel).rg - 0.5f);

    // Sample the main texture from the distorted UV coordinates.
    fixed4 col = tex2D(_MainTex, uv);

    return col;
}
DMGregory
sumber
1
Ini terlihat sangat bagus. Saya tidak yakin saya mengerti semua atribut: _NoseScale = skalar untuk penskalaan "peta kebisingan". _NoiseScrollVelocity = Vector2 di mana kecepatan kita bergerak melintasi peta kebisingan. _Noise =? _Distortion = Skalar yang saya pilih sebagai faktor distorsi? v2f = Vertex kami menentukan warnanya. i =?
morpheus05
_Noiseadalah [sampler tekstur yang bertuliskan] tekstur acak kecil yang blobby di atas. v2f iadalah data yang diinterpolasi dari vertex shader - kami terutama menggunakannya untuk mendapatkan koordinat tekstur untuk piksel yang kami gambar i.uv,. Dan Anda benar tentang sisanya.
DMGregory
Saya telah mengimplementasikan shader dan entah bagaimana itu tidak berhasil (tidak bergerak atau distorsi terlalu besar), saya berasumsi saya tidak menetapkan nilai dengan benar. time = perbedaan dari frame terakhir dalam ms. noise_scale = 1 (Saya menggunakan tekstur Anda, ulangi mode bungkus) noise_scroll_velocity = [0,01, 0,01] distorsi = 0,02
morpheus05
Perhatikan bahwa variabel disebut Waktu, bukan DeltaTime. Jika Anda menggunakan perbedaan waktu, dan framerate Anda konsisten, maka Anda akan selalu mendapatkan angka yang sama dan Anda akan menjalankan ulang shader dengan input yang sama, mendapatkan output yang sama (tidak ada yang bergerak). Lebih buruk lagi, jika framerate Anda tidak konsisten maka Anda akan mendapatkan getaran maju dan mundur. Anda ingin total waktu berlalu, bukan waktu delta.
DMGregory
Segera saya tekan kirim saya menyadari itu dan sekarang hampir berhasil. Animasi ini tampaknya menghasilkan gelombang dari sudut kanan bawah dan setelah itu, 10 detik atau lebih hanya menghilang, seperti gelombang yang berhenti. Apa yang bisa menjadi alasan untuk ini?
morpheus05
6

Ini disebut efek kaustik, dan menghasilkan efek ini pada saat runtime cukup memakan waktu, jadi ini secara tradisional dilakukan dengan animasi frame-by-frame pre-rendered. Ada alat yang akan menghasilkan bingkai animasi kaustik untuk Anda, seperti Caustics Generator , yang memiliki versi gratis untuk penggunaan non-komersial. Ada juga beberapa yang dibuat sebelumnya yang dapat Anda beli secara signifikan lebih murah daripada versi pro dari alat yang saya sebutkan.

Perhatikan bahwa efek kaustik juga biasanya merupakan efek yang diterapkan sebagai cookie ringan pada medan bawah air, atau pada permukaan bawah air. Artinya, meletakkannya di permukaan air sambil melihat ke bawah ke dalam air itu tidak seperti biasanya.

Ed Marty
sumber
Itu sangat menarik, saya juga akan melihat generator ini (walaupun, saya akan mencoba varian shader jika saya memahaminya ...)
morpheus05
4

Ini terlihat seperti tekstur yang dapat Anda hasilkan dari grafik voronoi, misalnya:

masukkan deskripsi gambar di sini

Anda dapat membuat penyesuaian kecil dan halus pada grafik dengan memindahkan titik-titiknya; menggambar ulang grafik setiap frame akan cukup mahal, jadi Anda mungkin ingin membuat animasi terlebih dahulu.

FacticiusVir
sumber
4
Saya benar-benar telah membuat kaustik seperti ini di shader di masa lalu. Ini belum tentu semahal yang Anda bayangkan ( inilah contoh rendering tepi Voronoi secara realtime dalam shader WebGL ), meskipun mendapatkan bentuk halus yang tepat di tepinya - daripada poligon runcing - bisa jadi menantang.
DMGregory
Ooo, itu sangat bagus; Saya punya beberapa generator medan yang sangat berguna.
FacticiusVir
0

Ada metode oldschool, yang melibatkan lapisan tekstur bawah, dan dua tekstur transparan setengah untuk refleksi di atas.

Jika Anda ingin pergi jauh-jauh dan ingin air agar tidak terlihat penuh dengan gelombang yang dikloning atau aliran sup biru samish adalah tujuan yang harus dicapai.

https://steamcdn-a.akamaihd.net/apps/valve/2010/siggraph2010_vlachos_waterflow.pdf

Huruf pika
sumber
3
Meskipun tautan dapat membantu, mereka tidak pernah membuat jawaban yang baik. Bisakah Anda mengembangkan kedua metode tesis ini? Bagaimana cara mengimplementasikannya?
Vaillancourt
Metode pertama, pada dasarnya adalah metode yang sangat tua yang digunakan untuk menghidupkan air - Anda mengambil tekstur air lapisan dasar yang Koordinat UVWnya digeser ke arah pilihan Anda. Sekarang Anda menerapkan di samping peta / benjolan-peta normal yang Anda geser ke arah lain - jika dilakukan dengan baik, ini terlihat meyakinkan untuk sungai kecil. Ini sangat terbatas meskipun untuk badan air besar - seperti apa pun gelombang ressembling akan mendapatkan efek moire. Tautan menjelaskan penggunaan flowmap jauh lebih baik dari yang saya bisa.
Pica
Silakan gunakan fitur edit untuk meningkatkan pertanyaan dengan apa yang Anda tambahkan di sini :) Orang-orang terbiasa mencari jawaban di pos, bukan di komentar.
Vaillancourt