URenderer 에서 관리된다.void URenderer::RenderWorldGrid()
{
PrepareWorldGrid();
AActor* CameraActor = FEditorManager::Get().GetCamera();
if (CameraActor == nullptr)
{
return;
}
float GridGap = UEngine::Get().GetWorldGridGap();
FTransform CameraTransform = CameraActor->GetActorTransform();
FVector CameraLocation = CameraTransform.GetPosition();
int32 StepX = static_cast<int32>(CameraLocation.X / GridGap);
int32 StepY = static_cast<int32>(CameraLocation.Y / GridGap);
FVector GridOffset(StepX * GridGap, StepY * GridGap, 0.f);
FVector GridScale(GridGap, GridGap, 1.f);
FTransform GridTransform(GridOffset, FVector::ZeroVector, GridScale);
ConstantUpdateInfo UpdateInfo
{
GridTransform.GetMatrix(),
FVector4(0.2f, 0.2f, 0.2f, 1.0f),
false,
};
UpdateObjectConstantBuffer(UpdateInfo);
DeviceContext->Draw(GridVertexNum, 0);
// restore
DeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// 나머지는 PrepareMainShader에서 작업중이므로, 생략
}
GridGap 값에 따라 스냅하며 따라다니기 때문에 카메라에 고정된 것이 아닌 월드에 고정된 듯 보인다.
////////
/// Input, Output
////////
struct VS_INPUT
{
float3 Position : POSITION; // Input position from vertex buffer
};
struct PS_INPUT
{
float4 Position : SV_POSITION; // Transformed position to pass to the pixel shader
float4 Color : COLOR; // Color to pass to the pixel shader
float4 WorldPosition : POSITION;
};
////////
/// Function
////////
PS_INPUT mainVS(VS_INPUT input)
{
PS_INPUT output;
output.Position = float4(input.Position.xyz, 1.0f);
output.Position = mul(output.Position, WorldMatrix);
output.WorldPosition = output.Position;
output.Position = mul(output.Position, ViewMatrix);
output.Position = mul(output.Position, ProjectionMatrix);
output.Color = CustomColor;
return output;
}
float4 mainPS(PS_INPUT input) : SV_TARGET
{
float Dist = length(input.WorldPosition.xyz - ViewPosition);
float MaxDist = FarClip * 1.2f;
float MinDist = MaxDist * 0.5f;
// Fade out grid
float Fade = saturate(1.f - (Dist - MinDist) / (MaxDist - MinDist));
input.Color.a *= Fade * Fade * Fade;
return input.Color;
}
WorldPosition 은 그리드 정점의 월드 포지션으로, 부드럽게 Fade out 되는 효과를 위해 버텍스 쉐이더에서 계산한다.
버텍스 쉐이더에서 계산된 정점 정보는 레스터라이저를 거치면서 선형 보간되어, 두 정점 사이의 Fade out 효과가 부드럽게 이어지게 된다.
Fade out은 색상의 알파 값을 조정하여 투명해지도록 설정해야하므로, 별도의 블렌드 스테이트를 추가했다.
D3D11_BLEND_DESC BlendState;
ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC));
BlendState.RenderTarget[0].BlendEnable = TRUE;
BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; // 소스 색상: 알파값 사용
BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; // 대상 색상: (1 - 알파)
BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; // 알파값 유지
BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
Device->CreateBlendState(&BlendState, &GridBlendState);