我需要调试一个GLSL程序,但我不知道如何输出中间结果。 是否有可能使用GLSL进行一些调试跟踪(如printf) ?
当前回答
我正在分享一个片段着色器的例子,我实际上是如何调试的。
#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 white
else
sampColor = texture2D(samp, fs_in.texcoord); //else sample from original
color = sampColor;
}
其他回答
我正在分享一个片段着色器的例子,我实际上是如何调试的。
#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 white
else
sampColor = texture2D(samp, fs_in.texcoord); //else sample from original
color = sampColor;
}
我发现变换反馈是调试顶点着色器的有用工具。您可以使用它来捕获VS输出的值,并在CPU端读取它们,而不必通过光栅化器。
这里是另一个转换反馈教程的链接。
void main(){
float bug=0.0;
vec3 tile=texture2D(colMap, coords.st).xyz;
vec4 col=vec4(tile, 1.0);
if(something) bug=1.0;
col.x+=bug;
gl_FragColor=col;
}
GLSL Shader源代码由图形驱动程序编译和链接,并在GPU上执行。 如果你想调试着色器,那么你必须使用图形调试器,如RenderDoc或NVIDIA Nsight。
在这个答案的底部是一个GLSL代码的例子,它允许输出完整的浮点值作为颜色,编码IEEE 754 binary32。我像这样使用它(这段代码给出了modelview矩阵的yy组件):
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);
在屏幕上显示后,您可以选择任何颜色选择器,将颜色格式化为HTML(如果您不需要更高的精度,则将00附加到rgb值,如果需要,则执行第二遍以获得较低的字节),然后您将得到浮点数的十六进制表示为IEEE 754 binary32。
下面是toColor()的实际实现:
const int emax=127;
// Input: x>=0
// Output: base 2 exponent of x if (x!=0 && !isnan(x) && !isinf(x))
// -emax if x==0
// emax+1 otherwise
int 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 NaN
return emax+1;
}
// Input: any x
// Output: IEEE 754 biased exponent with bias=emax
int 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 otherwise
float significand(float x)
{
// converting int to float so that exp2(genType) gets correctly-typed value
float 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 fraction
int part(float x,int N)
{
// All comments about exactness here assume that underflow and overflow don't occur
const float byteShift=256.;
// Multiplication is exact since it's just an increase of exponent by 8
for(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 8
float c=floor(byteShift*q);
return int(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 7
int s = x<0. ? 128 : 0;
ivec4 binary32;
binary32.yzw=significandAsIVec3(x);
// clear the implicit integer bit of significand
if(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.;
}
推荐文章
- 我如何调试git/git-shell相关的问题?
- Visual Studio拒绝忘记断点?
- 如何在Python自己的调试器(PDB)中执行多行语句
- GLSL的随机/噪声函数
- 我如何在Visual Studio中预处理后看到C/ c++源文件?
- Linux有c++ gdb图形用户界面吗?
- 是什么让Visual Studio调试器停止评估ToString重写?
- 打印一个可变内存地址在swift
- 访问控制台和扩展的后台开发工具
- Python内存泄漏
- 使用Visual Studio调试器在值更改时中断
- 如何调试一个GLSL着色器?
- 漂亮地打印Java集合(toString不返回漂亮输出)
- 确定导致分段错误的代码行?
- 如何在GDB中打印c++向量的元素?