DX 기능으로 실린더 만들기 실습.
이런 실린더 같은 3D 모델링을 할 때 중요한 것은 노멀 벡터이다. 이전에도 얘기했으나, 노멀 벡터는 트랜스폼 시 정점의 월드 매트릭스를 그대로 따라가면 값이 이상하게 튀게 된다. 정점의 값을 그대로 따라가게 되는 것이다. 이를 방지하기 위해서 월드 행렬을 역전치 시키면 된다.
따라서 아래 VS 함수를 보면 역전치로 노멀 벡터를 감싸주었다.
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.posModel, 1.0f);
// Normal 먼저 변환
float4 normal = float4(input.normalModel, 0.0f);
output.normalWorld = mul(normal, invTranspose).xyz;
//output.normalWorld = mul(normal, model).xyz;
output.normalWorld = normalize(output.normalWorld);
pos = mul(pos, model);
float t = input.texcoord.x;
pos.xyz += output.normalWorld * t * scale;
output.posWorld = pos.xyz;
pos = mul(pos, view);
pos = mul(pos, projection);
output.posProj = pos;
output.texcoord = input.texcoord;
output.color = float3(1.0, 1.0, 0.0) * (1.0 - t) + float3(1.0, 0.0, 0.0) * t;
return output;
}
먼저 실린더의 정점을 구해보기
실린더는 각 면의 정점을 만약 n 개 로 표현한다면, 실제로는 n + 1 개여야한다. 이유는, 텍스처 좌표에서는 0 으로 시작해 1로 와야하기 때문에 처음 시작 정점을 0 그 자리 그대로 끝 정점 1 짜리를 정해줘야한다.
// 옆면의 바닥 버텍스들 (인덱스 0 이상 sliceCount 미만)
for (int i = 0; i <= sliceCount; i++) {
Vertex v;
// TODO: 작성 (텍스춰 좌표계, 버텍스 노멀 필요)
v.position =
Vector3::Transform(Vector3(bottomRadius, -0.5f * height, 0.f),
Matrix::CreateRotationY(dTheta * float(i)));
v.normal = v.position - Vector3(0.f, -0.5f * height, 0.f);
v.normal.Normalize();
v.texcoord = Vector2(float(i) / sliceCount, 1.f);
vertices.push_back(v);
}
// 옆면의 맨 위 버텍스들 (인덱스 sliceCount 이상 2 * sliceCount 미만)
for (int i = 0; i <= sliceCount; i++) {
Vertex v;
// TODO: 작성 (텍스춰 좌표계, 버텍스 노멀 필요)
v.position =
Vector3::Transform(Vector3(topRadius, 0.5f * height, 0.f),
Matrix::CreateRotationY(dTheta * float(i)));
v.normal = v.position - Vector3(0.f, 0.5f * height, 0.f);
v.normal.Normalize();
v.texcoord = Vector2(float(i) / sliceCount, 0.f);
vertices.push_back(v);
}
vector<uint16_t> &indices = meshData.indices;
for (int i = 0; i < sliceCount; i++) {
indices.push_back(i);
indices.push_back(i + sliceCount + 1);
indices.push_back(i + 1 + sliceCount + 1);
indices.push_back(i);
indices.push_back(i + 1 + sliceCount + 1);
indices.push_back(i + 1);
}
실린더 완성. 노멀 벡터의 위치도 문제가 없다.
