Normal Vector 와 렌더링 결과
Normal 벡터와 렌더링 결과
이전에 배운 SubDivision에서
‘정점’의 위치가 같으면
Normal은 같은 벡터를 사용
-> 원형 이기에 ‘부드러움’을 표현하기 위함
(SubDivision과 직접적인 연관은 딱히 없지만)
그렇지만 ‘사각형’의 예제 등에서는
‘같은 위치’라도
그 사각형이 속해있는 위치에 따라
Normald을 다르게 주었다
-> 사각형 이기에 ‘끊어짐’을 표현
예제 - 구체의 정점 노멀을 각각의 표면이 향하는 곳(Face Normal)으로 변경
auto UpdateFaceNormal = [](Vertex &v0, Vertex &v1, Vertex &v2) {
// v0, v1, v2로 이루어진 삼각형의 faceNormal 계산
auto faceNormal = v0.normal + v1.normal + v2.normal;
faceNormal.Normalize();
v0.normal = faceNormal;
v1.normal = faceNormal;
v2.normal = faceNormal;
};
// 버텍스가 중복되는 구조로 구현
MeshData newMesh;
uint16_t count = 0;
for (size_t i = 0; i < meshData.indices.size(); i += 3) {
size_t i0 = meshData.indices[i];
size_t i1 = meshData.indices[i + 1];
size_t i2 = meshData.indices[i + 2];
Vertex v0 = meshData.vertices[i0];
Vertex v1 = meshData.vertices[i1];
Vertex v2 = meshData.vertices[i2];
Vertex v3;
v3.position = (v0.position + v2.position) * 0.5f;
v3.texcoord = (v0.texcoord + v2.texcoord) * 0.5f;
ProjectVertex(v3);
Vertex v4;
v4.position = (v0.position + v1.position) * 0.5f;
v4.texcoord = (v0.texcoord + v1.texcoord) * 0.5f;
ProjectVertex(v4);
Vertex v5;
v5.position = (v1.position + v2.position) * 0.5f;
v5.texcoord = (v1.texcoord + v2.texcoord) * 0.5f;
ProjectVertex(v5);
UpdateFaceNormal(v4, v1, v5);
UpdateFaceNormal(v0, v4, v3);
UpdateFaceNormal(v3, v4, v5);
UpdateFaceNormal(v3, v5, v2);
newMesh.vertices.push_back(v4);
newMesh.vertices.push_back(v1);
newMesh.vertices.push_back(v5);
newMesh.vertices.push_back(v0);
newMesh.vertices.push_back(v4);
newMesh.vertices.push_back(v3);
newMesh.vertices.push_back(v3);
newMesh.vertices.push_back(v4);
newMesh.vertices.push_back(v5);
newMesh.vertices.push_back(v3);
newMesh.vertices.push_back(v5);
newMesh.vertices.push_back(v2);
for (uint16_t j = 0; j < 12; j++) {
newMesh.indices.push_back(j + count);
}
count += 12;
}
각각의 정점의 ‘노멀 방향’을 해당 ‘표면’이 향하는 부분으로 수정
(SubDivision 코드 사용)
예제 2 - 코드 수정시 결과가 다르다?
UpdateFaceNormal(v4, v1, v5);
newMesh.vertices.push_back(v4);
newMesh.vertices.push_back(v1);
newMesh.vertices.push_back(v5);
UpdateFaceNormal(v0, v4, v3);
newMesh.vertices.push_back(v0);
newMesh.vertices.push_back(v4);
newMesh.vertices.push_back(v3);
UpdateFaceNormal(v3, v4, v5);
newMesh.vertices.push_back(v3);
newMesh.vertices.push_back(v4);
newMesh.vertices.push_back(v5);
UpdateFaceNormal(v3, v5, v2);
newMesh.vertices.push_back(v3);
newMesh.vertices.push_back(v5);
newMesh.vertices.push_back(v2);
예제의 FaceNormal 호출 시점을 변경하면 이미지가 조금 다르게 보인다
왜 그럴까?
auto UpdateFaceNormal = [](Vertex &v0, Vertex &v1, Vertex &v2) {
// v0, v1, v2로 이루어진 삼각형의 faceNormal 계산
auto faceNormal = v0.normal + v1.normal + v2.normal;
faceNormal.Normalize();
v0.normal = faceNormal;
v1.normal = faceNormal;
v2.normal = faceNormal;
};
해당 부분에서 v0,v1,v2 에 해당하는 faceNormal을
‘바꿔주고 있기 때문’이다
그렇기에 ‘처음’에 전부 호출하는 방식은 ‘각각’ 전체를 기준으로
FaceNomral이 처리된 것이고
현재 방식은
중간 중간 FaceNormal이 적용된 것이 들어가고
그 이후에 들어가는 부분과 그 이전 같은 위치의 Normal이 ‘달라지기’ 때문이다
댓글남기기