2012-12-06 4 views
0

저는 셰이더 프로그램에서 작업 중이며 가장 이상한 일 중 하나가 발생했습니다. 필자는 PositionLightPS라는 메서드를 가지고 있습니다.이 메서드는 기본적으로 위치 조명 (옴니 및 스포트라이트)에 대한 계산을 수행하고 조명의 강도와 확산 색을 모두 포함하는 구조체를 반환합니다. HLSL Shader : 호출 함수가 반환 값을 변경합니다.

그것은 그러나 그것은

날 이유를 설명하자 ... 어떤 이유로 작동이 중지, 프로그램의 이전 버전에서 작동하는 데 사용됩니다. 그러나 먼저 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); } 

백 화소를

를 반환 이것은 그래서 이것은 PositionLightPS 메소드를 호출하는 값에 영향을 미치는 것을 의미

를 반환 돌아왔다 ...하지만 왜? 왜 그럴까요? 무슨 일 이니? 메모리 오류입니까?

(주 :.. OmniLightDiffuse 방법에서 직접 PositionLightPS 방법 코드를 복사하는 것은 상기 문제를 해결하고, 보통 광 디스플레이는이 PositionLightPS에서 수행되는 계산이 올바른지 수단 문제는 다음이다 사용 않는 LightFragment 구조체가 쉐이더 프로그램에 어떤 영향을 미치는지?)

답변

2

문제의 원인을 찾았습니다. 내 컴퓨터는 CUDA를 사용하며 내 지식없이 통합 그래픽 칩을 사용하도록 잠겨 있습니다. NVidia 카드를 강제로 문제가 해결되었습니다.

그러나 본질적으로 내 문제였던이 유용한 블로그 게시물을 찾았습니다. 사용자 정의 함수를 호출하면 두 개의 특정 컴파일러 플래그가 동시에 활성화 될 때 컴파일러가 인라인하여 픽셀을 삭제합니다.. 통합 그래픽 칩이이 정확한 오류를 재생했는지는 모르겠지만 증상이 완벽하게 일치하는 것으로 보입니다 (즉, 반환 값에 아무런 영향을주지 않는 함수를 호출하면 반환되는 값이 변경됩니다).

자세한 내용은 Nico Shertler의 블로그 게시물 링크 : http://nicoschertler.wordpress.com/2012/01/02/hlsl-4-calls-to-user-defined-functions-will-crash/

1

일반적으로 이것은 0으로 나누기 오류 때문입니다. ATI와 NVIDIA는이 NaN 처리 방식이 다를 수 있습니다. 입력 벡터의 길이를 확인하거나 엡실론을 추가하십시오.

관련 문제