지형을 항상 만드는건 아님 (메쉬를 지형으로 사용하는 경우)
삼각형 메쉬를 바닥면에 일정한 간격으로 생성하여 사각형을 만듬
이 후 높이를 조절 후 높이 값만 저장해두고 사용 height map
terrain 쉐이더 파일
PatchTess ConstantHS(InputPatch<VS_OUT, 3> input, int patchID : SV_PrimitiveID)
{
...
edge0Pos = mul(float4(edge0Pos, 1.f), g_matWorld).xyz;
edge1Pos = mul(float4(edge1Pos, 1.f), g_matWorld).xyz;
edge2Pos = mul(float4(edge2Pos, 1.f), g_matWorld).xyz;
float edge0TessLevel = CalculateTessLevel(g_vec4_0.xyz, edge0Pos, minDistance, maxDistance, 4.f);
float edge1TessLevel = CalculateTessLevel(g_vec4_0.xyz, edge1Pos, minDistance, maxDistance, 4.f);
float edge2TessLevel = CalculateTessLevel(g_vec4_0.xyz, edge2Pos, minDistance, maxDistance, 4.f);
output.edgeTess[0] = edge0TessLevel;
output.edgeTess[1] = edge1TessLevel;
output.edgeTess[2] = edge2TessLevel;
output.insideTess = edge2TessLevel;
return output;
}
constant hull shader에서는
카메라와 삼각형의 빗변들 거리를 통하여 테셀레이션 레벨을 정함
struct DS_OUT
{
float4 pos : SV_Position;
float2 uv : TEXCOORD;
float3 viewPos : POSITION;
float3 viewNormal : NORMAL;
float3 viewTangent : TANGENT;
float3 viewBinormal : BINORMAL;
};
[domain("tri")]
DS_OUT DS_Main(const OutputPatch<HS_OUT, 3> input, float3 location : SV_DomainLocation, PatchTess patch)
{
...
float3 localPos = input[0].pos * location[0] + input[1].pos * location[1] + input[2].pos * location[2];
float2 uv = input[0].uv * location[0] + input[1].uv * location[1] + input[2].uv * location[2];
...
float2 fullUV = float2(uv.x / (float)tileCountX, uv.y / (float)tileCountZ);
localPos.y = g_tex_2.SampleLevel(g_sam_0, fullUV, 0).x;
float2 deltaUV = float2(1.f / mapWidth, 1.f / mapHeight);
float2 deltaPos = float2(tileCountX * deltaUV.x, tileCountZ * deltaUV.y);
...
output.pos = mul(float4(localPos, 1.f), g_matWVP);
output.viewPos = mul(float4(localPos, 1.f), g_matWV).xyz;
output.viewTangent = normalize(mul(float4(localTangent, 0.f), g_matWV)).xyz;
output.viewBinormal = normalize(mul(float4(localBinormal, 0.f), g_matWV)).xyz;
output.viewNormal = normalize(cross(output.viewBinormal, output.viewTangent));
output.uv = uv;
return output;
}
도메인 쉐이더에서 정점 위치가 바뀌기 때문에 버텍스 쉐이더에서 하던 역할을 해야함
높이 맵 텍스쳐에서 높이를 추출하여 해당 좌표의 y 값을 변경
변경된 좌표를 기준으로 deferred 렌더에 필요한 행렬들을 다시 계산해주게 됨
terrain 클래스 추가
class Terrain : public Component
{
public:
...
void Init(int32 sizeX, int32 sizeZ);
virtual void FinalUpdate() override;
private:
int32 _sizeX = 15;
int32 _sizeZ = 15;
float _maxTesselation = 4.f;
...
};
초기화 시 지형의 크기를 입력 받아 세팅하도록 정의
void Terrain::FinalUpdate()
{
...
Vec3 pos = mainCamera->GetTransform()->GetLocalPosition();
_material->SetVec4(0, Vec4(pos.x, pos.y, pos.z, 0));
}
final update 시에 메인 카메라의 위치를 받아와 쉐이더에서 계산 시 사용할 수 있도록 입력