Saya perlu men-debug program GLSL tetapi saya tidak tahu cara menampilkan hasil antara. Apakah mungkin membuat beberapa jejak debug (seperti dengan printf) dengan GLSL?
Anda tidak dapat dengan mudah berkomunikasi kembali ke CPU dari dalam GLSL. Menggunakan glslDevil atau alat lain adalah taruhan terbaik Anda.
Sebuah printf akan membutuhkan upaya untuk kembali ke CPU dari GPU yang menjalankan kode GLSL. Sebagai gantinya, Anda dapat mencoba mendorong ke depan ke layar. Alih-alih mencoba menampilkan teks, tampilkan sesuatu yang secara visual berbeda dengan layar. Misalnya Anda dapat melukis sesuatu dengan warna tertentu hanya jika Anda mencapai titik kode Anda di mana Anda ingin menambahkan printf. Jika Anda perlu mencetak nilai, Anda dapat mengatur warna sesuai dengan nilai itu.
Ini adalah perangkat debugging. Jika Anda ingin tahu di mana posisi lampu berada di tempat kejadian, misalnya, buka: if (lpos.x> 100) bug = 1.0. Jika posisi cahaya lebih besar dari 100, adegan akan berubah menjadi merah.
ste3e
13
Saya telah menemukan Transform Feedback untuk menjadi alat yang berguna untuk debugging vertex shaders. Anda dapat menggunakan ini untuk menangkap nilai-nilai output VS, dan membacanya kembali di sisi CPU, tanpa harus melalui rasterizer.
Berikut ini tautan lain ke tutorial tentang Transform Umpan Balik.
Jika Anda ingin memvisualisasikan variasi nilai di layar, Anda dapat menggunakan fungsi peta panas yang mirip dengan ini (saya menulisnya di hlsl, tetapi mudah untuk beradaptasi dengan glsl):
Anda dapat mencoba ini: https://github.com/msqrt/shader-printf yang merupakan implementasi yang disebut dengan tepat "Fungsionalitas printf sederhana untuk GLSL."
Anda mungkin juga ingin mencoba ShaderToy, dan mungkin menonton video seperti ini ( https://youtu.be/EBrAdahFtuo ) dari saluran YouTube "The Art of Code" di mana Anda dapat melihat beberapa teknik yang bekerja dengan baik untuk debugging dan memvisualisasikan. Saya bisa sangat merekomendasikan salurannya saat dia menulis beberapa hal yang sangat bagus dan dia juga memiliki bakat untuk menyajikan ide-ide kompleks dalam novel, sangat menarik dan mudah dicerna formatnya (video Mandelbrot-nya adalah contoh yang luar biasa persis seperti itu: https: // youtu.be/6IWXkV82oyY )
Saya harap tidak ada yang keberatan dengan jawaban selarut ini, tetapi pertanyaannya berperingkat tinggi di pencarian Google untuk debugging GLSL dan tentu saja banyak yang berubah dalam 9 tahun :-)
PS: Alternatif lain juga bisa NVIDIA nSight dan AMD ShaderAnalyzer yang menawarkan debugger loncatan penuh untuk shader.
#version 410 core
uniform sampler2D samp;
in VS_OUT
{
vec4 color;
vec2 texcoord;} fs_in;
out vec4 color;void main(void){
vec4 sampColor;if( texture2D(samp, fs_in.texcoord).x >0.8f)//Check if Color contains red
sampColor = vec4(1.0f,1.0f,1.0f,1.0f);//If yes, set it to whiteelse
sampColor = texture2D(samp, fs_in.texcoord);//else sample from original
color = sampColor;}
Di bagian bawah jawaban ini adalah contoh kode GLSL yang memungkinkan untuk menampilkan nilai penuh floatsebagai warna, pengkodean IEEE 754 binary32. Saya menggunakannya seperti berikut (cuplikan ini memberikan yykomponen matriks modelview):
vec4 xAsColor=toColor(gl_ModelViewMatrix[1][1]);if(bool(1))// put 0 here to get lowest byte instead of three highest
gl_FrontColor=vec4(xAsColor.rgb,1);else
gl_FrontColor=vec4(xAsColor.a,0,0,1);
Setelah Anda mendapatkan ini di layar, Anda bisa mengambil pemilih warna apa saja, memformat warna sebagai HTML (menambahkan 00ke rgbnilai jika Anda tidak membutuhkan presisi yang lebih tinggi, dan melakukan pass kedua untuk mendapatkan byte yang lebih rendah jika Anda melakukannya), dan Anda mendapatkan representasi heksadesimal floatsebagai IEEE 754 binary32.
Inilah implementasi aktual dari toColor():
constint emax=127;// Input: x>=0// Output: base 2 exponent of x if (x!=0 && !isnan(x) && !isinf(x))// -emax if x==0// emax+1 otherwiseint floorLog2(float x){if(x==0.)return-emax;// NOTE: there exist values of x, for which floor(log2(x)) will give wrong// (off by one) result as compared to the one calculated with infinite precision.// Thus we do it in a brute-force way.for(int e=emax;e>=1-emax;--e)if(x>=exp2(float(e)))return e;// If we are here, x must be infinity or NaNreturn emax+1;}// Input: any x// Output: IEEE 754 biased exponent with bias=emaxint biasedExp(float x){return emax+floorLog2(abs(x));}// Input: any x such that (!isnan(x) && !isinf(x))// Output: significand AKA mantissa of x if !isnan(x) && !isinf(x)// undefined otherwisefloat significand(float x){// converting int to float so that exp2(genType) gets correctly-typed valuefloat expo=float(floorLog2(abs(x)));return abs(x)/exp2(expo);}// Input: x\in[0,1)// N>=0// Output: Nth byte as counted from the highest byte in the fractionint part(float x,int N){// All comments about exactness here assume that underflow and overflow don't occurconstfloat byteShift=256.;// Multiplication is exact since it's just an increase of exponent by 8for(int n=0;n<N;++n)
x*=byteShift;// Cut higher bits away.// $q \in [0,1) \cap \mathbb Q'.$float q=fract(x);// Shift and cut lower bits away. Cutting lower bits prevents potentially unexpected// results of rounding by the GPU later in the pipeline when transforming to TrueColor// the resulting subpixel value.// $c \in [0,255] \cap \mathbb Z.$// Multiplication is exact since it's just and increase of exponent by 8float c=floor(byteShift*q);returnint(c);}// Input: any x acceptable to significand()// Output: significand of x split to (8,8,8)-bit data vector
ivec3 significandAsIVec3(float x){
ivec3 result;float sig=significand(x)/2.;// shift all bits to fractional part
result.x=part(sig,0);
result.y=part(sig,1);
result.z=part(sig,2);return result;}// Input: any x such that !isnan(x)// Output: IEEE 754 defined binary32 number, packed as ivec4(byte3,byte2,byte1,byte0)
ivec4 packIEEE754binary32(float x){int e = biasedExp(x);// sign to bit 7int s = x<0.?128:0;
ivec4 binary32;
binary32.yzw=significandAsIVec3(x);// clear the implicit integer bit of significandif(binary32.y>=128) binary32.y-=128;// put lowest bit of exponent into its position, replacing just cleared integer bit
binary32.y+=128*int(mod(float(e),2.));// prepare high bits of exponent for fitting into their positions
e/=2;// pack highest byte
binary32.x=e+s;return binary32;}
vec4 toColor(float x){
ivec4 binary32=packIEEE754binary32(x);// Transform color components to [0,1] range.// Division is inexact, but works reliably for all integers from 0 to 255 if// the transformation to TrueColor by GPU uses rounding to nearest or upwards.// The result will be multiplied by 255 back when transformed// to TrueColor subpixel value by OpenGL.return vec4(binary32)/255.;}
Lakukan render offline ke suatu tekstur dan evaluasi data tekstur itu. Anda dapat menemukan kode terkait dengan googling untuk "render to tekstur" opengl Kemudian gunakan glReadPixels untuk membaca output ke dalam array dan melakukan pernyataan di atasnya (karena melihat melalui array yang begitu besar di debugger biasanya tidak terlalu berguna).
Anda juga mungkin ingin menonaktifkan penjepitan ke nilai output yang tidak antara 0 dan 1, yang hanya didukung untuk tekstur titik mengambang .
Saya pribadi terganggu oleh masalah debugging shader dengan benar untuk sementara waktu. Tampaknya tidak ada cara yang baik - Jika ada yang menemukan debugger yang baik (dan tidak ketinggalan zaman / usang), beri tahu saya.
Setiap jawaban atau komentar yang mengatakan "google xyz" harus diblokir atau dipilih dari Stackoverflow.
gregoiregentil
1
Jawaban yang ada semuanya bagus, tapi saya ingin membagikan satu permata kecil lagi yang berharga dalam men-debug masalah presisi rumit dalam shader GLSL. Dengan bilangan int yang sangat besar direpresentasikan sebagai titik apung, orang perlu berhati-hati untuk menggunakan lantai (n) dan lantai (n + 0,5) dengan benar untuk menerapkan putaran () ke int yang tepat. Maka dimungkinkan untuk membuat nilai float yang merupakan int yang tepat oleh logika berikut untuk mengemas komponen byte menjadi nilai output R, G, dan B.
Jawaban:
Anda tidak dapat dengan mudah berkomunikasi kembali ke CPU dari dalam GLSL. Menggunakan glslDevil atau alat lain adalah taruhan terbaik Anda.
Sebuah printf akan membutuhkan upaya untuk kembali ke CPU dari GPU yang menjalankan kode GLSL. Sebagai gantinya, Anda dapat mencoba mendorong ke depan ke layar. Alih-alih mencoba menampilkan teks, tampilkan sesuatu yang secara visual berbeda dengan layar. Misalnya Anda dapat melukis sesuatu dengan warna tertentu hanya jika Anda mencapai titik kode Anda di mana Anda ingin menambahkan printf. Jika Anda perlu mencetak nilai, Anda dapat mengatur warna sesuai dengan nilai itu.
sumber
sumber
Saya telah menemukan Transform Feedback untuk menjadi alat yang berguna untuk debugging vertex shaders. Anda dapat menggunakan ini untuk menangkap nilai-nilai output VS, dan membacanya kembali di sisi CPU, tanpa harus melalui rasterizer.
Berikut ini tautan lain ke tutorial tentang Transform Umpan Balik.
sumber
Jika Anda ingin memvisualisasikan variasi nilai di layar, Anda dapat menggunakan fungsi peta panas yang mirip dengan ini (saya menulisnya di hlsl, tetapi mudah untuk beradaptasi dengan glsl):
Kemudian dalam pixel shader Anda, Anda hanya menampilkan sesuatu seperti:
Dan bisa mendapatkan gambaran tentang perbedaannya di seluruh piksel Anda:
Tentu saja Anda dapat menggunakan set warna yang Anda suka.
sumber
GLSL Sandbox sangat berguna bagi saya untuk shader.
Bukan debugging per se (yang telah dijawab tidak mampu) tetapi berguna untuk melihat perubahan dalam output dengan cepat.
sumber
Anda dapat mencoba ini: https://github.com/msqrt/shader-printf yang merupakan implementasi yang disebut dengan tepat "Fungsionalitas printf sederhana untuk GLSL."
Anda mungkin juga ingin mencoba ShaderToy, dan mungkin menonton video seperti ini ( https://youtu.be/EBrAdahFtuo ) dari saluran YouTube "The Art of Code" di mana Anda dapat melihat beberapa teknik yang bekerja dengan baik untuk debugging dan memvisualisasikan. Saya bisa sangat merekomendasikan salurannya saat dia menulis beberapa hal yang sangat bagus dan dia juga memiliki bakat untuk menyajikan ide-ide kompleks dalam novel, sangat menarik dan mudah dicerna formatnya (video Mandelbrot-nya adalah contoh yang luar biasa persis seperti itu: https: // youtu.be/6IWXkV82oyY )
Saya harap tidak ada yang keberatan dengan jawaban selarut ini, tetapi pertanyaannya berperingkat tinggi di pencarian Google untuk debugging GLSL dan tentu saja banyak yang berubah dalam 9 tahun :-)
PS: Alternatif lain juga bisa NVIDIA nSight dan AMD ShaderAnalyzer yang menawarkan debugger loncatan penuh untuk shader.
sumber
Saya membagikan contoh fragmen shader, bagaimana saya benar-benar men-debug.
sumber
Di bagian bawah jawaban ini adalah contoh kode GLSL yang memungkinkan untuk menampilkan nilai penuh
float
sebagai warna, pengkodean IEEE 754binary32
. Saya menggunakannya seperti berikut (cuplikan ini memberikanyy
komponen matriks modelview):Setelah Anda mendapatkan ini di layar, Anda bisa mengambil pemilih warna apa saja, memformat warna sebagai HTML (menambahkan
00
kergb
nilai jika Anda tidak membutuhkan presisi yang lebih tinggi, dan melakukan pass kedua untuk mendapatkan byte yang lebih rendah jika Anda melakukannya), dan Anda mendapatkan representasi heksadesimalfloat
sebagai IEEE 754binary32
.Inilah implementasi aktual dari
toColor()
:sumber
Lakukan render offline ke suatu tekstur dan evaluasi data tekstur itu. Anda dapat menemukan kode terkait dengan googling untuk "render to tekstur" opengl Kemudian gunakan glReadPixels untuk membaca output ke dalam array dan melakukan pernyataan di atasnya (karena melihat melalui array yang begitu besar di debugger biasanya tidak terlalu berguna).
Anda juga mungkin ingin menonaktifkan penjepitan ke nilai output yang tidak antara 0 dan 1, yang hanya didukung untuk tekstur titik mengambang .
Saya pribadi terganggu oleh masalah debugging shader dengan benar untuk sementara waktu. Tampaknya tidak ada cara yang baik - Jika ada yang menemukan debugger yang baik (dan tidak ketinggalan zaman / usang), beri tahu saya.
sumber
Jawaban yang ada semuanya bagus, tapi saya ingin membagikan satu permata kecil lagi yang berharga dalam men-debug masalah presisi rumit dalam shader GLSL. Dengan bilangan int yang sangat besar direpresentasikan sebagai titik apung, orang perlu berhati-hati untuk menggunakan lantai (n) dan lantai (n + 0,5) dengan benar untuk menerapkan putaran () ke int yang tepat. Maka dimungkinkan untuk membuat nilai float yang merupakan int yang tepat oleh logika berikut untuk mengemas komponen byte menjadi nilai output R, G, dan B.
sumber