Saya telah menyiapkan beberapa kode pengukur FPS di WebGL (berdasarkan jawaban SO ini ) dan telah menemukan beberapa keanehan dengan kinerja shader fragmen saya. Kode hanya membuat quad tunggal (atau lebih tepatnya dua segitiga) di atas kanvas 1024x1024, sehingga semua keajaiban terjadi dalam fragmen shader.
Pertimbangkan shader sederhana ini (GLSL; vertex shader hanyalah pass-through):
// some definitions
void main() {
float seed = uSeed;
float x = vPos.x;
float y = vPos.y;
float value = 1.0;
// Nothing to see here...
gl_FragColor = vec4(value, value, value, 1.0);
}
Jadi ini hanya membuat kanvas putih. Rata-rata sekitar 30 fps pada mesin saya.
Sekarang mari kita tingkatkan angka yang berderak dan hitung setiap fragmen berdasarkan pada beberapa oktaf suara yang bergantung pada posisi:
void main() {
float seed = uSeed;
float x = vPos.x;
float y = vPos.y;
float value = 1.0;
float noise;
for ( int j=0; j<10; ++j)
{
noise = 0.0;
for ( int i=4; i>0; i-- )
{
float oct = pow(2.0,float(i));
noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
}
}
value = noise/2.0+0.5;
gl_FragColor = vec4(value, value, value, 1.0);
}
Jika Anda ingin menjalankan kode di atas, saya telah menggunakan implementasi inisnoise
.
Ini membawa fps ke sesuatu seperti 7. Itu masuk akal.
Sekarang bagian yang aneh ... mari kita hitung hanya satu dari setiap 16 fragmen sebagai noise dan biarkan yang lain putih, dengan membungkus perhitungan noise dalam kondisi berikut:
if (int(mod(x*512.0,4.0)) == 0 && int(mod(y*512.0,4.0)) == 0)) {
// same noise computation
}
Anda akan mengharapkan ini menjadi lebih cepat, tetapi masih hanya 7 fps.
Untuk satu pengujian lagi, mari filter saja piksel dengan persyaratan berikut:
if (x > 0.5 && y > 0.5) {
// same noise computation
}
Ini memberikan jumlah piksel noise yang sama persis seperti sebelumnya, tetapi sekarang kita kembali ke hampir 30 fps.
Apa yang terjadi disini? Tidakkah kedua cara untuk menyaring piksel ke-16 ini menghasilkan jumlah siklus yang sama persis? Dan mengapa yang lebih lambat memperlambat semua piksel sebagai noise?
Pertanyaan bonus: Apa yang bisa saya lakukan tentang ini? Apakah ada cara untuk mengatasi kinerja yang mengerikan jika saya benar - benar ingin berbintik kanvas saya dengan hanya beberapa fragmen mahal?
(Hanya untuk memastikan, saya telah mengkonfirmasi bahwa perhitungan modulo yang sebenarnya tidak mempengaruhi laju bingkai sama sekali, dengan merender setiap piksel 16 hitam bukan putih.)