Terrain
- 지형을 표현할 때 사용
- 무수한 삼각형의 조합으로 이루어져 있다.
- x 와 z 축의 정점 간격이 일정하다.
- 덮어질 텍스처의 높이(y축) 정보를 추가하여 저장한다. (height map)
shared_ptr<Mesh> Resources::LoadTerrainMesh(int32 sizeX, int32 sizeZ)
{
vector<Vertex> vec;
for (int32 z = 0; z < sizeZ + 1; z++)
{
for (int32 x = 0; x < sizeX + 1; x++)
{
Vertex vtx;
vtx.pos = Vec3(static_cast<float>(x), 0, static_cast<float>(z));
vtx.uv = Vec2(static_cast<float>(x), static_cast<float>(sizeZ - z));
vtx.normal = Vec3(0.f, 1.f, 0.f);
vtx.tangent = Vec3(1.f, 0.f, 0.f);
vec.push_back(vtx);
}
}
vector<uint32> idx;
for (int32 z = 0; z < sizeZ; z++)
{
for (int32 x = 0; x < sizeX; x++)
{
idx.push_back((sizeX + 1) * (z + 1) + (x));
idx.push_back((sizeX + 1) * (z)+(x + 1));
idx.push_back((sizeX + 1) * (z)+(x));
idx.push_back((sizeX + 1) * (z)+(x + 1));
idx.push_back((sizeX + 1) * (z + 1) + (x));
idx.push_back((sizeX + 1) * (z + 1) + (x + 1));
}
}
shared_ptr<Mesh> findMesh = Get<Mesh>(L"Terrain");
if (findMesh)
{
findMesh->Init(vec, idx);
return findMesh;
}
shared_ptr<Mesh> mesh = make_shared<Mesh>();
mesh->Init(vec, idx);
Add(L"Terrain", mesh);
return mesh;
}
- X, Z Size 개수만큼 칸을 만들기 위해 정점들을 생성하고 인덱스 버퍼를 통해 연결
PatchTess ConstantHS(InputPatch<VS_OUT, 3> input, int patchID : SV_PrimitiveID)
{
PatchTess output = (PatchTess)0.f;
float minDistance = g_vec2_1.x;
float maxDistance = g_vec2_1.y;
float3 edge0Pos = (input[1].pos + input[2].pos) / 2.f;
float3 edge1Pos = (input[2].pos + input[0].pos) / 2.f;
float3 edge2Pos = (input[0].pos + input[1].pos) / 2.f;
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;
}
float CalculateTessLevel(float3 cameraWorldPos, float3 patchPos, float min, float max, float maxLv)
{
float distance = length(patchPos - cameraWorldPos);
if (distance < min)
return maxLv;
if (distance > max)
return 1.f;
float ratio = (distance - min) / (max - min);
float level = (maxLv - 1.f) * (1.f - ratio);
return level;
}
- 카메라와의 거리를 구하여 Tessellation Level을 계산해준다.
- 거리에 따라 Level을 달리해 폴리곤의 개수를 조절
결과
- 카메라와 가까워지는 지형의 구조가 약간 바뀌는 것을 볼 수 있다.
- 이는 카메라와의 거리가 가까워지면서 Tessellation Level이 변경되어 더 많은 폴리곤으로 표현되기 때문이다.