[D3D] 카메라 버그 (TroubleShooting)

vector·2025년 11월 23일

1. 버그 현상

  • Emissive를 사용할 때 카메라 방향인 정면에서 봤을 때는 제대로 동작하지만, 카메라를 돌려서 측면이나 뒷면을 보게 될 경우에는 제대로 작동하지 않는 현상 발생

2. 원인 찾기

1. 쉐이더

00.Light.fx

  • Emissive를 만들어주는 코드에서는 현재 큰 문제가 없다는걸 볼 수 있음
  • 원인x
 // Emissive
{
    float3 E = normalize(cameraPosition - worldPosition);
    float value = saturate(dot(E, normal));
    float emissive = 1.0f - value;
    emissive = smoothstep(0.0f, 1.0f, emissive);
    emissive = pow(emissive, 1.f); // 감마 보정
    
    emissiveColor = GlobalLight.emissive * Material.emissive * emissive;
}

14.NormalMapping.fx

  • output.positioninput.positionW의 곱으로 월드좌표를 변환했지만, output.worldPosition에서 input.position.xyz를 가져왔던 부분을 수정
  • 원인x
MeshOutput VS(VertexTetrueNormalTangent input)
{
    MeshOutput output;
    output.position = mul(input.position, W); // 로컬->월드좌표
    // coutput.worldPosition = input.position.xyz; 원래 코드
    output.worldPosition = output.position.xyz; // 수정 코드
    output.position = mul(output.position, VP);
    output.uv = input.uv;
    output.normal = mul(input.normal, (float3x3) W);
    output.tangent = mul(input.tangent, (float3x3) W);
    
    return output;
}

00.Global.fx

  • CameraPosition()함수 float3(-V._41_42_43)에서 V값이 잘못됬다?
  • 하지만, 14.NormalMapping.fx에서 output.position = mul(output.position, VP)를 함으로써 잘 들어갔음을 볼 수 있음
  • 원인x

RenderManager, Camera

  • RenderManger에서 PushGlobalData()에서 V가 잘 안들어갔다면, 정상적으로 실행x
  • Camera에서 UpdateMatrix()부분의 View계산도 제대로 들어가있음
  • 원인x

CameraPosition()

  • CPU부분이랑 다른 부분에서 문제가 없다는 것은 `00.Global.fx에서 만들어준 CameraPosition()함수에서의 좌표값이 제대로 전달이 안됬을 확률이 가장 높다.
  • 14.NormalMapping.fxPS에서 CameraPosition()을 pos 변수로 받아서 출력해보자
float4 PS(MeshOutput input) : SV_TARGET
{
    ComputeNormalMapping(input.normal, input.tangent, input.uv);
    
    float4 color = ComputeLight(input.normal, input.uv, input.worldPosition);
    
    float3 pos = CameraPosition();
    
    return float4(pos.xyz, 1);
}

  • 카메라의 Rotation을 이동하게되면 색상이 변경되는 것을 알 수 있음
  • View를 구할때 Rotation값을 간과했던 부분이 문제

문제 해결

00.Global.fx

  • CameraPosition()에서 -V._41_42_43이 아닌 Rotation도 포함이 되어 있는 View의 역행렬VInv._41_42_43으로 구해주자

RenderManger

  • View의 역행렬을 쉐이더에서 수정해줄수 있지만, CPU에서 값을 계산해서 GPU로 넘겨주는 방식으로 진행
  • RenderManagerGlobalDesc에서 Matrix VInv추가
  • RenderManagerPushGlobalData()에서 VInvVeiw.Invert()를 대입
// 00.Global.fx
float3 CameraPosition()
{
	// return -V._41_42_43; // 기존 코드
    return VInv._41_42_43;	// 수정 코드
}

// RenderManager.h
struct GlobalDesc
{
	Matrix V = Matrix::Identity;
	Matrix P = Matrix::Identity;
	Matrix VP = Matrix::Identity;
	Matrix VInv = Matrix::Identity;		// 추가 코드
};

// RenderManager.cpp
void RenderManager::PushGlobalData(const Matrix& view, const Matrix& projection)
{
	_globalDesc.V = view;
	_globalDesc.P = projection;
	_globalDesc.VP = view * projection;
	_globalDesc.VInv = view.Invert();		// 추가 코드
	_globalBuffer->CopyData(_globalDesc);

	_globalEffectBuffer->SetConstantBuffer(_globalBuffer->GetComPtr().Get());
}

참고 강의

https://www.inflearn.com/courses/lecture?courseId=329791&type=LECTURE&unitId=161137&tab=script&subtitleLanguage=ko

profile
게임 클라이언트 프로그래머 준비중 (공부 및 기록용)

0개의 댓글