Kami mengalami beberapa masalah dengan penelusuran ray kami di DirectX, terutama dengan beberapa masalah pita serius dengan specular. Dengan daya spekulan tinggi (di atas 8) dimulai. Saya ingin tahu apakah ini masalah HDR / LDR atau dapat dikaitkan dengan hal lain, seperti normals atau vektor lainnya?
MEMPERBARUI
Lihat di bawah untuk pembaruan.
Inilah kode shader yang relevan untuk Blinn-Phong dalam sebuah lingkup:
float3 hitPoint = thisRay.origin + thisRay.direction * bestHit.hitT;
float3 normal = normalize(hitPoint - spheres[bestHit.hitID].center);
float3 toLight = pointLights[0].position.xyz - hitPoint;
float d = length(toLight);
toLight = normalize(toLight);
float diffuse = max(dot(normal, toLight), 0.0f);
float3 v = normalize(thisRay.origin - hitPoint);
float3 h = normalize(v + toLight);
float spec = 0;
if (diffuse > 0)
spec = pow(max(dot(normal, h), 0.0f), specPower) * diffuse;
output[threadID.xy] = spheres[bestHit.hitID].colour * diffuse + spheres[bestHit.hitID].specColour * spec;
specPower sama dengan 8 di gambar ini
specPower sama dengan 9 di gambar ini
Apakah ini sesederhana masalah HDR / LDR atau apakah itu terkait dengan presisi normal? Saya percaya saya pernah mengalami masalah ini sebelumnya di penyaji ditangguhkan di mana normals dari presisi rendah dan tidak benar dikemas / dibongkar tetapi dalam hal ini normals dihasilkan dengan cepat dan semuanya diserahkan langsung ke backbuffer.
Perbarui 1
Saya ingin menambahkan di atas bahwa segitiga menderita artefak yang sama dan mereka memiliki normal saat ini dihasilkan dengan cara berikut:
float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));
Saya akan mengatakan ini membuatnya semakin tidak mungkin bahwa masalah normal adalah permukaannya. Gambar berikut ini menunjukkan apa yang terjadi ketika specPower mencapai 2048.
sumber
float3 h = normalize( reflect(toLight,normal) );
, danspec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;
spec
secara langsung, dan jugamax(dot(normal, h), 0.0f)
. Cari pengembalian ini ke nilai 1 dalam perhitungan mana pun.Jawaban:
Sepertinya ada masalah dengan implementasi fungsi pow pada GPU khusus ini.
Ketika mencurigai bug dalam fungsi matematika ganti fungsi matematika dengan yang setara, misalnya ganti:
Dengan bug yang muncul di specPower = 9.0, buat hard-code-nya
Atau
Jika masalah hilang, ini berarti kemungkinan ada bug underflow dalam fungsi pow terkait eksponen pada GPU atau driver ini.
Apa yang dapat Anda lakukan sebagai solusi, dengan anggapan perhitungan shader fragmen dilakukan secara internal dengan float 16bit. Jika saya menghitung ini dengan benar, Anda harus melakukannya
Bisa jadi 32768 atau 8192: Saya mungkin mati sedikit atau GPU mungkin menggunakan presisi lebih atau kurang. untuk pow (x, 9.0) penjepitan akan menjadi pow (maks (temp, 0.3401975), 9.0) Nilai-nilai X di bawah ini akan melemahkan kisaran eksponen (+15 hingga -14) dari floating point IEEE 16bit (sekali lagi, saya dengan asumsi inilah yang digunakan GPU.)
dari kode rosetta ( http://rosettacode.org/wiki/Nth_root#C.2B.2B )
Anda harus menghitung ini pada CPU dan memberi nilai pada seragam: GPU mungkin akan memiliki masalah presisi yang sama jika Anda menghitungnya di shader.
Jika Anda dapat mengonfirmasi ini, coba hubungi tim driver GPU dengan contoh kode sumber shader yang mereplikasi masalah memberi mereka versi driver yang tepat, revisi OS, dan model GPU, yang dapat dieksekusi mungkin membantu tetapi tidak mengirimkannya karena email Anda akan terjebak dalam pemeriksa virus / spam. Hanya membangun satu dan menyimpan salinan kalau-kalau mereka meminta sampel pra-dibangun dieksekusi. Sebagai rasa hormat, beri mereka kesempatan untuk memperbaikinya sebelum menyebutnya secara publik. Itu bisa saja berupa bug pengoptimalan dalam kompiler shader mereka yang hanya terjadi pada shader khusus Anda. Mungkin perlu waktu (bulan) untuk menghubungi mereka, orang-orang ini sering kekurangan staf.
sumber