투영 텍스처와 디퍼 드 라이팅


10

에서 내 앞의 질문 , 나는 연기 조명 투영 텍스처링을 할 수 있는지 물었다. 이제 (반년 이상) 같은 일을 구현하는 데 문제가 있습니다. 이 기술을 가벼운 패스에 적용하려고합니다. (내 프로젝터는 알베도에 영향을 미치지 않습니다). 이 프로젝터가 있습니다 투사 행렬을 봅니다.

Matrix projection = Matrix.CreateOrthographicOffCenter(-halfWidth * Scale, halfWidth * Scale, -halfHeight * Scale, halfHeight * Scale, 1, 100000);
Matrix view       = Matrix.CreateLookAt(Position, Target, Vector3.Up);

여기서 halfWidthhalfHeightIS 감촉의 폭과 높이의 절반이며, Position프로젝터의 위치이며, target프로젝터의 대상이다. 이것은 괜찮은 것 같습니다. 이 셰이더로 전체 화면 쿼드를 그립니다.

float4x4 InvViewProjection;

texture2D DepthTexture;
texture2D NormalTexture;
texture2D ProjectorTexture;

float4x4 ProjectorViewProjection;

sampler2D depthSampler = sampler_state {
    texture = <DepthTexture>;
    minfilter = point;
    magfilter = point;
    mipfilter = point;
};

sampler2D normalSampler = sampler_state {
    texture = <NormalTexture>;
    minfilter = point;
    magfilter = point;
    mipfilter = point;
};

sampler2D projectorSampler = sampler_state {
    texture = <ProjectorTexture>;
    AddressU  = Clamp;
    AddressV  = Clamp;
};

float viewportWidth;
float viewportHeight;

// Calculate the 2D screen position of a 3D position
float2 postProjToScreen(float4 position) {
    float2 screenPos = position.xy / position.w;
    return 0.5f * (float2(screenPos.x, -screenPos.y) + 1);
}

// Calculate the size of one half of a pixel, to convert
// between texels and pixels
float2 halfPixel() {
    return 0.5f / float2(viewportWidth, viewportHeight);
}

struct VertexShaderInput {
    float4 Position : POSITION0;
};

struct VertexShaderOutput {
    float4 Position :POSITION0;
    float4 PositionCopy : TEXCOORD1;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input) {
    VertexShaderOutput output;
    output.Position = input.Position;
    output.PositionCopy=output.Position;
    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 {
    float2 texCoord =postProjToScreen(input.PositionCopy) + halfPixel();

    // Extract the depth for this pixel from the depth map
    float4 depth = tex2D(depthSampler, texCoord);
    //return float4(depth.r,0,0,1);
    // Recreate the position with the UV coordinates and depth value
    float4 position;
    position.x = texCoord.x * 2 - 1;
    position.y = (1 - texCoord.y) * 2 - 1;
    position.z = depth.r;
    position.w = 1.0f;

    // Transform position from screen space to world space
    position = mul(position, InvViewProjection);
    position.xyz /= position.w;
    //compute projection
    float3 projection=tex2D(projectorSampler,postProjToScreen(mul(position,ProjectorViewProjection)) + halfPixel());
    return float4(projection,1);
}

픽셀 쉐이더의 첫 번째 부분은 G- 버퍼 (이 코드는 다른 셰이더에서 아무 문제없이 사용하고 있음)에서 위치를 복구 한 다음 프로젝터 뷰 프로젝션 공간으로 변환됩니다. 문제는 투영이 나타나지 않는다는 것입니다. 내 상황의 이미지는 다음과 같습니다.

문제의 이미지

녹색 선은 렌더링 된 프로젝터 절두체입니다. 내 실수는 어디에 숨겨져 있습니까? XNA 4를 사용하고 있습니다. 조언을 주셔서 감사하고 영어를 유감스럽게 생각합니다.

편집하다:

위의 셰이더가 작동하지만 투영이 너무 작습니다. Scale 속성을 큰 값 (예 : 100)으로 변경하면 투영이 나타납니다. 그러나 카메라가 투영쪽으로 이동하면 이 YouTube 비디오 에서 볼 수 있듯이 투영이 확장됩니다 .

답변:


5

셰이더에서는 position.xyz /= w;크기 조정 문제를 일으키는 원인이 되므로를 제거해야합니다 .

// Transform position from screen space to world space 
position = mul(position, InvViewProjection); 
position.xyz /= position.w;  <<-- Comment this out

그 트릭을해야합니다.


0

너무 작은 결과를 얻고 그 크기에 도달하면 절두체가 여전히 1 대 1 공간 또는 0 대 1 등에 있기 때문일 수 있습니다. 절두체가 기반으로하는 당신의 오리고입니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.