2014-06-11 2 views
2

난 그림자 매핑으로 뒤죽박죽을 시작했다. 나는 사용 된 알고리즘을 이해한다. 문제는 내가 HLSL 코드에서 어수선한 곳인지 알아낼 수 없다는 것입니다. 여기에 있습니다 :그림자 매핑 아티팩트

//These change 
float4x4 worldViewProj; 
float4x4 world; 
texture  tex; 

//These remain constant 
float4x4 lightSpace; 
float4x4 lightViewProj; 
float4x4 textureBias; 
texture  shadowMap; 



sampler TexS = sampler_state 
{ 
    Texture = <tex>; 
    MinFilter = LINEAR; 
    MagFilter = LINEAR; 
    MipFilter = LINEAR; 
    AddressU = WRAP; 
    AddressV = WRAP; 
}; 

sampler TexShadow = sampler_state 
{ 
    Texture = <shadowMap>; 
    MinFilter = LINEAR; 
    MagFilter = LINEAR; 
    MipFilter = LINEAR; 
}; 

struct A2V 
{ 
    float3 posL : POSITION0; 
    float2 texCo : TEXCOORD0; 
}; 

struct OutputVS 
{ 
    float4 posH : POSITION0; 
    float2 texCo : TEXCOORD0; 
    float4 posW : TEXCOORD2; 
}; 

//Vertex Shader Depth Pass 
OutputVS DepthVS(A2V IN) 
{ 
    OutputVS OUT = (OutputVS)0; 

    //Get screen coordinates in light space for texture map 
    OUT.posH = mul(float4(IN.posL, 1.f), lightViewProj); 
    //Get the depth by performing a perspective divide on the projected coordinates 
    OUT.posW.x = OUT.posH.z/OUT.posH.w; 
    return OUT; 
} 


//Pixel shader depth Pass 
float4 DepthPS(OutputVS IN) : COLOR 
{ 
    //Texture only uses red channel, just store it there 
    return float4(IN.posW.x, 0, 0, 1); 
} 


//VertexShader Draw Pass 
OutputVS DrawVS(A2V IN) 
{ 
    OutputVS OUT = (OutputVS)0; 

    //Get the screen coordinates for this pixel 
    OUT.posH = mul(float4(IN.posL, 1.f), worldViewProj); 
    //Send texture coordinates through 
    OUT.texCo = IN.texCo; 
    //Pass its world coordinates through 
    OUT.posW = mul(float4(IN.posL, 1.f), world); 
    return OUT; 
} 

//PixelShader Draw Pass 
float4 DrawPS(OutputVS IN) : COLOR 
{ 
    //Get the pixels screen position in light space 
    float4 texCoord = mul(IN.posW, lightViewProj); 
    //Perform perspective divide to normalize coordinates [-1,1] 
    //texCoord.x = texCoord.x/texCoord.w; 
    //texCoord.y = texCoord.y/texCoord.w; 
    //Multiply by texture bias to bring in range 0-1 
    texCoord = mul(texCoord, textureBias); 
    //Get corresponding depth value 
    float prevDepth = tex2D(TexShadow, texCoord.xy); 
    //Check if it is in shadow 
    float4 posLight = mul(IN.posW, lightViewProj); 
    float currDepth = posLight.z/posLight.w; 
    if (currDepth >= prevDepth) 
     return float4(0.f, 0.f, 0.f, 1.f); 
    else 
     return tex2D(TexS, IN.texCo); 
} 


//Effect info 
technique ShadowMap 
{ 
    pass p0 
    { 
     vertexShader = compile vs_2_0 DepthVS(); 
     pixelShader = compile ps_2_0 DepthPS(); 
    } 

    pass p1 
    { 
     vertexShader = compile vs_2_0 DrawVS(); 
     pixelShader = compile ps_2_0 DrawPS(); 
    } 
} 

모든 매트릭스가 정확하고 깊이 맵이 올바르게 그려져 있는지 확인했습니다. 이 코드를 처리하는 모든 C++을 다시 작성하고 더 깔끔하게 만들었으며 여전히 동일한 문제가 발생했습니다. 나는 현재 그 그림자를 블렌딩하지 않고, 정확히 그릴 수있을 때까지 평면을 검은 색으로 그립니다. 방향 표시등이므로 직각 투영을 사용합니다. 나는 URL을 이미지를 삽입 할 수있는 충분한 명성 포인트를 해달라고하지만 현재 위치 : 깊이지도 - http://i.imgur.com/T2nITid.png 프로그램 출력 - http://i.imgur.com/ae3U3N0.png

어떤 도움이나 통찰력이 크게 학교 프로젝트의로 감상 할 수있다. 감사합니다

+0

당신은 내가 실제 그림자를 가지고 있다는 것을 알 수 있습니다. 나는 또한 그 모든 다른 goop도 가지고 있으며 그것이 어디에서 오는 것인지 확실하지 않습니다. – user3355098

답변

2

당신이 깊이 버퍼에서 얻는 값은 0에서 1까지의 부동 소수점 값입니다. 이미 알고 있듯이 부동 소수점은 정확하지 않으며 소수점 이하 자릿수를 요구하면 덜 정확합니다. 당신은 유물로 끝납니다.

할 수있는 일이 있습니다. 가장 쉬운 방법은 투영 행렬의 원근 Z 값을 서로 가깝게하여 깊이 버퍼가 오브젝트의 얼마나 멀리 떨어져 있는지 나타내는 소수점 이하의 자리를 사용하지 않도록하는 것입니다. 나는 보통 1-200의 가치를 갖는 것이 나에게 꽤 좋은 결과를 준다는 것을 알게된다.

당신이 할 수있는 또 다른 쉬운 일은 더 많은 픽셀을 제공하므로 더 정확하게 장면을 나타 내기 때문에 그리는 텍스처의 크기를 늘리는 것입니다.

게임 엔진이 쉐도우 매핑 인공물을 개선하기 위해 할 수있는 많은 복잡한 것들이 있지만 그 것에 관한 책을 쓸 수 있으며, 실제로 들어갔 으면 좋겠다고 생각한다면 blog .

+0

그래서 당신은 이것이 정밀한 문제라고 생각하고 내가 놓치고있는 것이 아닌가? 나는이 문제에 대한 한 달 후에 알고리즘을 꽤 잘 이해하고 이해하기 쉽기 때문에 똑같은 생각을하는 경향이 있습니다 ... 직관적으로 말이죠. 나는 1.f와 100.f의 near와 far 클리핑 평면을 사용하고 있고, 또한 라인을 따라 간단한 바이어스를 추가하려고 시도했다. (그리고 나는 많은 편향을 시도했다.) if (abs (curDepth - prevDepth) <.001) 그러나 그들은 장면의 대다수를 검게하는 경향이 있었다. 텍스처 크기를 512에서 1024로 늘렸고 가장자리가 더 매끄러운 동일한 기본 결과를 얻었습니다. – user3355098

+0

@ user3355098 코드를 살펴 보는 데 많은 시간을 할애하지 않으면 보증 할 수있는 것이 하나도 없습니다.하지만이 문제는 매우 자주 발생하며 해결 방법을 제시하는 경향이 있습니다. DirectX는 섀도우 매핑 코드를 제공하므로이를 코드와 비교할 수 있습니다. – Caesar

+0

그래, 나는 포함 된 많은 다른 그림자 매핑 자습서를 보았다. youtube.com에서 1 시간 분량의 동영상을 끝까지 시청했습니다. 내가 아는 한 모든 것이 정확하다. 어떤 인공물은 투영 각도에 접함이라는 사실에서 기인한다고 생각합니다. 그것은 단지 구와 함께 일어날 것입니다. 아직도 전체 구석이 까맣다 까 왜 설명하지 않는다. – user3355098