Saya mencoba membuat shader ini berjalan di iDevice yang sangat tua, dan juga Android.
Bahkan ketika saya mengurangi kode ke 2 fungsi sinus per fragmen shader berjalan sekitar 20fps.
Saya telah mempertimbangkan mengambil daun dari buku teknik naungan lama dan menciptakan sebuah array yang menampung sekelompok nilai trigonometri yang telah ditentukan dan entah bagaimana menggunakannya untuk memperkirakan shader.
Dalam shader yang saya tautkan di atas, saya sudah mensimulasikan bahwa dengan membulatkan nilai-nilai yang dikirim ke fungsi trigon, semakin jauh meninggalkan mouse (saat turun) semakin sedikit kualitas shader. Ini sebenarnya cukup keren karena sangat dekat dengan sisi kiri sepertinya shader yang benar-benar berbeda dan sangat keren.
Pokoknya saya punya dua dilema:
- Saya tidak tahu apa cara paling efisien untuk memiliki array nilai 360 seperti di dalamnya dalam shader GLSL, konstan atau seragam?
Saya tidak tahu bagaimana cara menempatkan angka dalam kisaran seperti biasanya jika saya ingin sudut antara 0 dan 360 (ya saya tahu GPU menggunakan radian) Saya akan melakukannya seperti itu.
func range(float angle) { float temp = angle while (temp > 360) {temp -= 360;} while (temp < 0) {temp += 360;} return temp; }
Namun GLSL tidak memungkinkan saat loop atau fungsi rekursif.
sumber
mod
fungsi bawaan adalah yang Anda inginkan. Anda akan menulismod(angle, 360.0)
.Jawaban:
Sudah disarankan dalam komentar berulang kali, tetapi tidak ada yang merasa perlu untuk memberikan jawaban yang tepat, jadi demi kelengkapan, solusi langsung dan umum untuk masalah ini mungkin menggunakan tekstur sebagai tabel pencarian, khususnya tekstur 1D yang berisi semua nilai fungsi Anda untuk rentang input yang dimungkinkan (yaitu / ). Ini memiliki berbagai keunggulan:[ 0 , 2 π )[ 0 , 360 ) [ 0 , 2 π)
GL_REPEAT
sebagai mode pembungkus untuk tekstur dan itu akan secara otomatis mulai dari awal lagi ketika mengakses dengan argumen> 1 (dan juga untuk argumen negatif).GL_LINEAR
sebagai filter tekstur, cara ini mendapatkan nilai yang Anda bahkan tidak menyimpan. Tentu saja interpolasi linier tidak 100% akurat untuk fungsi trigonometri, tetapi tentu saja lebih baik daripada tidak ada interpolasi.float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;
Tentu saja masih harus dievaluasi jika ini adalah solusi yang lebih baik, karena akses tekstur juga tidak sepenuhnya gratis, serta kombinasi terbaik dari ukuran dan format tekstur.
Untuk mengisi tekstur dengan data dan memberikan komentar pada salah satu komentar Anda, Anda harus mempertimbangkan bahwa pemfilteran tekstur mengembalikan nilai tepat di pusat texel , yaitu tekstur terkoordinasi dengan setengah ukuran texel. Jadi ya, Anda harus menghasilkan nilai pada
.5
texels , yaitu sesuatu seperti ini dalam kode aplikasi:Namun, Anda mungkin masih ingin membandingkan kinerja pendekatan ini dengan pendekatan yang menggunakan array seragam kecil (yaitu[0,360)
uniform float sinTable[361]
, atau mungkin kurang dalam praktiknya, perhatikan batas implementasi Anda pada ukuran array seragam) yang baru saja Anda muat dengan nilai masing-masing menggunakanglUniform1fv
dan akses dengan menyesuaikan sudut Anda ke menggunakan fungsi dan membulatkannya ke nilai terdekat:mod
sumber