Bagaimana saya bisa menerapkan efek scanline?

8

Saya sedang mengerjakan platformer old-school di libgdx dan saya ingin itu memiliki efek "scanline", seperti ini:

efek maldita castilla scanline

Upaya pertama saya adalah membuat sedikit tekstur dan menggambarnya pada layar quad penuh. Saya menggunakan dua mode kamera ortografis yang berbeda (satu untuk tilemap utama permainan, dan yang kedua untuk membuat tekstur garis pemindaian). Kadang-kadang tekstur macet di tilemap dan kadang-kadang terlalu besar, dan menutupi seluruh layar dalam warna hitam.

Apakah pendekatan saya menggunakan dua kamera dan tekstur masuk akal? Apa solusi yang baik untuk mencapai efek ini?

Alexandre GUIDET
sumber

Jawaban:

4

Masalah dengan secara naif merender tekstur garis pemindaian kecil ke quad layar penuh yang besar adalah bahwa tekstur akan meningkat, membuat apa yang menjadi satu set garis pemindaian piksel tunggal dalam tekstur menjadi lebih tebal, blurrier (tergantung pada metode interpolasi Anda), dan umumnya lebih buruk.

Anda seharusnya memasang ubintekstur melintasi quad sedemikian rupa untuk mempertahankan rasio 1: 1 pixel-to-texel. Ini melibatkan menyesuaikan koordinat tekstur quad sehingga mereka lebih besar dari 1 pada tingkat terjauh, dan juga mengatur parameter pembungkus tekstur Anda untuk mengulang bukannya penjepit. Jika tekstur Anda 64x64 piksel, dan layar Anda 1024x768 piksel, Anda dapat mengetahui bahwa dalam sumbu X Anda harus memasang tekstur 16 kali (1024/64). Demikian pula, pada sumbu Y Anda harus memasang 12 kali (768/64). Anda dapat menyesuaikan matematika ini untuk batas tekstur dan layar Anda yang sebenarnya. Gunakan angka-angka itu (16 dan 12) sebagai luasan maksimum koordinat tekstur quad Anda, dan Anda akan mendapatkan hasil yang jauh lebih baik. Bergantung pada bagaimana proyeksi ortografis Anda saat ini diatur untuk ubin, Anda bahkan mungkin tidak perlu mengubahnya untuk membuat ini.

Sebagai alternatif, Anda dapat mengambil pendekatan shader: render adegan biasa menjadi tekstur, lalu render tekstur itu sebagai quad layar penuh, tetapi abaikan setiap garis piksel yang aneh. Jika Anda tahu batas-batas layar dalam shader, Anda dapat melakukan ini dengan cukup mudah (ini adalah pseudo-code , samar-samar HLSL-ish, tetapi harus menerjemahkan dengan mudah):

float2    screenSize;
sampler2D textureSampler;
float2    textureCoordinate;

float4 main () { 
   // Interpolation of texture coordinates means that we don't get nice
   // integer boundaries we could take the modulus of.
   float half_y = textureCoordinate.y * screenSize.y * 0.5;
   float delta = round(half_y) - half_y;
   float delta_squared = delta * delta;
   if (delta_squared < 0.1) {
      return texture2D(textureSampler, textureCoordinate);
   } 

   return float4(0,0,0,0);
}

sumber
0

Masalah dengan menggunakan kamera adalah bahwa itu akan skala gambar. Yang Anda inginkan pada dasarnya adalah selalu menggambar gambar yang sama pada ukuran yang sama (100%). Saya menganggap itu cukup besar untuk selalu menutupi seluruh layar.

Jika ini masalahnya, salah satu solusinya adalah menerapkan transformasi terbalik dari kamera pada gambar sehingga menarik pada ukuran "pixel perfect".

Pilihan yang lebih mudah adalah dengan mengukurnya sendiri. Misalnya. jika kamera Anda diperbesar hingga 75%, gambar Anda akan diskalakan menjadi 133% ( 1/0.75).

ashes999
sumber
Anda mengatakan bahwa gambar harus cukup besar untuk menutupi seluruh layar, apakah tidak mungkin untuk mengisi sedikit persegi dengan tekstur kecil?
Alexandre GUIDET
@AlexandreGUIDET Saya tidak yakin. Saya menggunakan tekstur untuk memudar masuk dan keluar, dan itu adalah piksel 1x1 yang diskalakan. Untuk scanlines, Anda ingin mengulanginya. Anda harus memeriksa apakah libGDX memiliki opsi untuk ini.
ashes999
@AlexandreGUIDET apakah Anda mencoba ini?
ashes999
Saya memilih pendekatan yang berbeda menggunakan kamera lain dan menggambar efek scanline di atas layar. Saya belum puas dengan hasilnya karena pemandangan itu sepertinya tergelincir di belakang scanlines. Apa yang Anda pikirkan tentang menggunakan shader?
Alexandre GUIDET