我正在使用 Nvidia CG
和 Direct3D9
并且对以下代码有疑问。
它会编译,但不会“加载”(使用 cgLoadProgram
包装器)并且所导致的失败被简单地描述为 发生 D3D 失败
。
它是像素着色器的一部分,使用着色器模型设置为 3.0
有趣的是,此着色器在以下情况下加载良好:
1) 手动展开 while 语句(对许多 if { }
语句)。
2) 删除循环中带有 tex2D
函数的行。
3) 切换到着色器模型 2_X
并手动展开循环。
着色器代码的问题部分:
float2 tex = float2(1, 1);
float2 dtex = float2(0.01, 0.01);
float h = 1.0 - tex2D(height_texture1, tex);
float height = 1.00;
while ( h < height )
{
height -= 0.1;
tex += dtex;
// Remove the next line and it works (not as expected,
// of course)
h = tex2D( height_texture1, tex );
}
如果有人知道为什么会发生这种情况,或者可以在非 CG 环境中测试类似的代码,或者可以以其他方式帮助我,我在等你;)
谢谢。
最佳答案
我认为您需要在纹理坐标上使用 ddx/ddy 来确定循环之前的梯度,然后使用 tex2D(sampler2D samp, float2 s, float2 dx, float2 dy)
GPU 总是渲染四边形而不是像素(即使在像素边界上——渲染后端会丢弃多余的像素)。这样做是因为它允许它始终计算屏幕空间纹理派生,即使您使用计算的纹理坐标也是如此。它只需要取像素中心值之间的差值。
但是,当像问题代码中那样使用动态分支时,这不起作用,因为各个像素的着色器处理器可能会在控制流中发生分歧。因此,您需要在程序流程发散之前通过 ddx/ddy 手动计算导数。
关于C++着色器问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4150918/