Struct HLSL着色器:调用函数更改返回值

Struct HLSL着色器:调用函数更改返回值,struct,directx,shader,hlsl,Struct,Directx,Shader,Hlsl,我一直在做一个着色器程序,最奇怪的事情之一正在发生。 我有一个名为PositionLightPS的方法,它基本上执行位置灯光(泛光灯和聚光灯)的计算,并返回一个包含灯光强度和漫反射颜色的结构 它曾在以前版本的程序中工作,但由于某种原因停止工作 让我解释一下原因。但首先,这里是PositionPS方法的代码。我毫不怀疑这种方法的计算是正确的,但稍后会有更多的讨论 struct LightFragment { float4 diffuse; float intensity; };

我一直在做一个着色器程序,最奇怪的事情之一正在发生。 我有一个名为PositionLightPS的方法,它基本上执行位置灯光(泛光灯和聚光灯)的计算,并返回一个包含灯光强度和漫反射颜色的结构

它曾在以前版本的程序中工作,但由于某种原因停止工作

让我解释一下原因。但首先,这里是PositionPS方法的代码。我毫不怀疑这种方法的计算是正确的,但稍后会有更多的讨论

struct LightFragment {
    float4 diffuse;
    float intensity;
};

LightFragment PositionLightPS(PositionLightVOut pin, float3 lightToPixelVec)
{
    LightFragment result;

    pin.normal = normalize(pin.normal);

    float4 diffuse = shaderTexture.Sample( textureSampler, pin.tex0 );
    float3 finalDiffuse = float3(0.0f, 0.0f, 0.0f);

    float d = length(lightToPixelVec);
    if( d > plRange )
    {
        result.diffuse = float4(finalDiffuse, 0);
        result.intensity = 0; 
        return result;
    }

    lightToPixelVec /= d; 

    result.intensity = dot(lightToPixelVec, pin.normal);

    if( result.intensity > 0.0f )
    {   
        finalDiffuse = result.intensity * diffuse.xyz;
        finalDiffuse.xyz *= clColour.xyz;
        finalDiffuse.xyz *= clColour.w;

        finalDiffuse /= plAttenuation[0] + (plAttenuation[1] * d) + (plAttenuation[2] * (d*d));
    }   

    result.diffuse = float4(finalDiffuse, diffuse.a) * diffuseColour;
    return result;
}
这是泛光像素着色器

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    return = PositionLightPS(pin, lightToPixelVec).diffuse;
}
出于某种原因,这不起作用,尽管这已经有很长一段时间了。但这不是我问题的重点。当然奇怪的是,这两种方法产生不同的结果

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    //return float4(1,1,1,1);
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec);
    return float4(1,1,1,1);
}
这将返回一个黑色像素

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    return float4(1,1,1,1);
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec);
    //return float4(1,1,1,1);
}
这将返回一个白色像素

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    return float4(1,1,1,1);
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec);
    //return float4(1,1,1,1);
}
这意味着调用PositionLightPS方法会影响返回的值。。。但是为什么呢为什么会这样?发生了什么事?是内存错误吗?


(注意:直接在OmniLightDiffuse方法中复制PositionLightPS方法代码可以解决此问题,并且灯光显示正常。这意味着在PositionLightPS中执行的计算是正确的。问题是,使用LightFragment struct是否会对着色器程序产生影响?

通常,这是由于被零除的错误造成的。ATI和NVIDIA在处理此NaN方面可能有所不同。检查输入向量的长度,或添加一些ε。

通常,这是由于被零除的错误造成的。ATI和NVIDIA在处理此NaN方面可能有所不同。检查输入向量的长度,或者添加一些ε。

我找到了问题的原因。我的电脑使用CUDA,并在我不知情的情况下锁定自己使用集成图形芯片。迫使英伟达卡解决了这个问题。 然而,我确实发现了这篇非常有用的博客文章,详细说明了我的问题所在当两个特定的编译器标志同时处于活动状态时,调用用户定义函数会导致编译器内联删除它处理的像素。 我不知道集成图形芯片是否再现了这个确切的错误,但症状似乎完全对应(即调用返回值没有关联的函数将改变返回的内容)


有关更多详细信息,请参阅Nico Shertler的博文链接:

我找到了问题的原因。我的电脑使用CUDA,并在我不知情的情况下锁定自己使用集成图形芯片。迫使英伟达卡解决了这个问题。 然而,我确实发现了这篇非常有用的博客文章,详细说明了我的问题所在当两个特定的编译器标志同时处于活动状态时,调用用户定义函数会导致编译器内联删除它处理的像素。 我不知道集成图形芯片是否再现了这个确切的错误,但症状似乎完全对应(即调用返回值没有关联的函数将改变返回的内容)


有关更多详细信息,请参阅Nico Shertler的博客链接:

Bjorkes post为我提供了解决问题的线索。 我的代码输入了一个自定义函数,该函数返回一个白色像素(错误),调试器不允许我单步执行代码。 罪魁祸首是下面这句话。 float4 p=纹理。样本(…) 返回(浮动4)(1/p.x,1/p.y,1/p.z,1)


正在为0添加已解决问题的检查。

Bjorkes post为我提供了解决问题的线索。 我的代码输入了一个自定义函数,该函数返回一个白色像素(错误),调试器不允许我单步执行代码。 罪魁祸首是下面这句话。 float4 p=纹理。样本(…) 返回(浮动4)(1/p.x,1/p.y,1/p.z,1)

添加0的检查已解决问题