2016-08-02 7 views
1

(내 나쁜 영어 죄송합니다.)그림자 매핑 (HLSL, 쉐이더 모델 3.0)

내가 스택 오버플로에 새로 온 사람

와 MS 비주얼 C++ 2015 컴파일러와 3D 게임 응용 프로그램을 작성, Direct3D를 9 HLSL (Shader 모델 3.0).

4 개의 렌더링 타겟 텍스처로 지연 렌더링 로직을 구현했습니다. 렌더 타겟 텍스처에 픽셀의 깊이 값을 저장하고 그림자 맵을 만들었습니다. 결과는 다음과 같습니다. (메쉬 카메라에 가까운 작은 크기를 갖기 때문에 모든 메쉬 블랙 컬러를 갖는다. 멀리 평면 거리 값 1000.0f이다.) I 섀도 매핑 쉐이더 출력 그림자 전체 화면 쿼드 렌더링

The depth texture and the shadow map.

붉은 색으로 쉐이더가 올바르게 작동하는지 확인하십시오. 그러나 셰이더가 잘못된 결과를 출력하는 것으로 보입니다. 그림자 맵 텍스처 출력은 메쉬 서페이스에서 반복됩니다. 여기

https://www.youtube.com/watch?v=1URGgoCR6Zc

는 쿼드을 그리는 그림자 매핑 정점 셰이더입니다.

struct VsInput { 
    float4 position : POSITION0; 
}; 

struct VsOutput { 
    float4 position : POSITION0; 
    float4 cameraViewRay : TEXCOORD0; 
}; 

float4x4 matInverseCameraViewProjection; 
float4 cameraWorldPosition; 
float farDistance; 

VsOutput vs_main(VsInput input) { 
    VsOutput output = (VsOutput)0; 

    output.position = input.position; 

    output.cameraViewRay = mul(float4(input.position.xy, 1.0f, 1.0f) * farDistance, matInverseCameraViewProjection); 
    output.cameraViewRay /= output.cameraViewRay.w; 
    output.cameraViewRay.xyz -= cameraWorldPosition.xyz; 

    return output; 
} 

여기에 쿼드를 그릴 섀도우 매핑 픽셀 셰이더가 있습니다.

struct PsInput { 
    float2 screenPosition : VPOS; 
    float4 viewRay : TEXCOORD0; 
}; 

struct PsOutput { 
    float4 color : COLOR0; 
}; 

texture depthMap; 
texture shadowMap; 

sampler depthMapSampler = sampler_state { 
    Texture = (depthMap); 
    AddressU = CLAMP; 
    AddressV = CLAMP; 
    MagFilter = POINT; 
    MinFilter = POINT; 
    MipFilter = POINT; 
}; 

sampler shadowMapSampler = sampler_state { 
    Texture = (shadowMap); 
    AddressU = CLAMP; 
    AddressV = CLAMP; 
    MagFilter = POINT; 
    MinFilter = POINT; 
    MipFilter = POINT; 
}; 

//float4x4 matCameraView; 
float4x4 matLightView; 
float4x4 matLightProjection; 
float4 cameraWorldPosition; 
float4 lightWorldPosition; 
float2 halfPixel; 
float epsilon; 
float farDistance; 

PsOutput ps_main(PsInput input) { 
    PsOutput output = (PsOutput)0; 
    output.color.a = 1.0f; 

    //Reconstruct the world position using the view-space linear depth value. 
    float2 textureUv = input.screenPosition * halfPixel * 2.0f - halfPixel; 
    float viewDepth = tex2D(depthMapSampler, textureUv).r; 
    float3 eye = input.viewRay.xyz * viewDepth; 
    float4 worldPosition = float4((eye + cameraWorldPosition.xyz), 1.0f); 

    //Test if the reconstructed world position has right coordinate values. 
    //output.color = mul(worldPosition, matCameraView).z/farDistance; 

    float4 positionInLightView = mul(worldPosition, matLightView); 
    float lightDepth = positionInLightView.z/farDistance; 
    float4 positionInLightProjection = mul(positionInLightView, matLightProjection); 
    positionInLightProjection /= positionInLightProjection.w; 

    //If-statement doesn't work??? 
    float condition = positionInLightProjection.x >= -1.0f; 
    condition *= positionInLightProjection.x <= 1.0f; 
    condition *= positionInLightProjection.y >= -1.0f; 
    condition *= positionInLightProjection.y <= 1.0f; 
    condition *= positionInLightProjection.z >= 0.0f; 
    condition *= positionInLightProjection.z <= 1.0f; 
    condition *= positionInLightProjection.w > 0.0f; 

    float2 shadowMapUv = float2(
     positionInLightProjection.x * 0.5f + 0.5f, 
     -positionInLightProjection.y * 0.5f + 0.5f 
    ); 

    //If-statement doesn't work??? 
    float condition2 = shadowMapUv.x >= 0.0f; 
    condition2 *= shadowMapUv.x <= 1.0f; 
    condition2 *= shadowMapUv.y >= 0.0f; 
    condition2 *= shadowMapUv.y <= 1.0f; 

    float viewDepthInShadowMap = tex2D(
     shadowMapSampler, 
     shadowMapUv 
    ).r; 
    output.color.r = lightDepth > viewDepthInShadowMap + epsilon; 
    output.color.r *= condition; 
    output.color.r *= condition2; 

    return output; 
} 

그림자 맵의 자외선이 일부 잘못된 값이 보인다,하지만 난 진짜 문제는 무엇을 알아낼 수 없습니다.

도움을 주셔서 감사합니다.

편집 : 쉐이더 코드를 업데이트했습니다. 뷰 공간의 선형 깊이를 사용하기로 결정하고 세계 지위가 올바른 가치를 지니고 있음을 확인했습니다. 섀도우 맵 좌표 값에 잘못된 값이있는 이유를 정말로 이해하지 못합니다 ...

+0

나쁜 영어는 무엇입니까? –

답변

0

해결책을 찾았습니다.

첫 번째 문제는 렌더 타겟 텍스처가 잘못된 텍스처 포맷을 가졌습니다. 나는 D3DFMT_R32F를 사용해야했다. (나는 D3DFMT_A8R8G8B8을 사용했다.)

그리고이 그림자를 내 그림자 맵핑 쉐이더에 추가했다.

//Reconstruct the world position using the view-space linear depth value. 
float2 textureUv = input.screenPosition * halfPixel * 2.0f - halfPixel; 
float4 viewPosition = float4(input.viewRay.xyz * tex2D(depthMapSampler, textureUv).r, 1.0f); 
float4 worldPosition = mul(viewPosition, matInverseCameraView); 

... 

//If-statement doesn't work??? 
float condition = positionInLightProjection.x >= -1.0f; 
condition *= positionInLightProjection.x <= 1.0f; 
condition *= positionInLightProjection.y >= -1.0f; 
condition *= positionInLightProjection.y <= 1.0f; 
condition *= positionInLightProjection.z >= 0.0f; 
condition *= positionInLightProjection.z <= 1.0f; 
condition *= viewPosition.z < farDistance; 

마지막 줄이 중요하고 두 번째 문제점을 해결했습니다. 'farDistance'는 카메라 절두체의 평면 거리입니다. 나는 아직도 그것이 필요한 이유를 이해하려고 노력하고있다.

0

잘못된 바이어스를 사용하고있는 것 같습니다. 구글은 "그림자 여드름"을 피하고 문제에 대한 답을 찾아야합니다. 또한 그림자 맵의 해상도가 문제가 될 수 있습니다.

+0

아니, 그건 내 문제가 아니야. 섀도우 맵 텍스처는 카메라의 위치와 각도에 따라 메쉬 서페이스에서 반복됩니다. 실제 결과 비디오를 보여줘야 할 것 같습니다. – FooBarBazQux