본문 바로가기

DX

Subdivision

상세도가 낮은 모델을 높은 모델로 만드는 기술이다. 즉, 기존의 다각형을 더욱 잘게 나누어 부드러운 형태를 표현 하는 기술이다.

 

저해상도 모델에 서브디비전을 적용하겠다.

 

 

 

서브디비전 알고리즘은 굉장히 많은데 그 중에 정점을 *4 하는 알고리즘을 쓰겠다.

 

그럼 이 서브디비전을 왜 사용할까?? 이 기능은 GPU 에서 사용가능하다. 실제로 테셀레이션 단계에서 LOD 에 사용된다. 그리고 LOD 가 아니더라도 CPU 에서 적은 정점을 보내 GPU 에서 그 정점의 갯수를 늘려 최적화 할 수 있다.

 

다음은 가장 간단한 서브디비전이다. V0,1,2 정점에서 3,4,5 정점을 추가로 만들고 삼각형을 1개에서 4개로 늘리는 방식이다.

구현 시 중요한 것은 저렇게 중간점을 새로구하면 미세하게 저 새로 생성한 점을 구체 위에 그러니까 메쉬 위에 존재하는 것이 아니게 된다. 따라서 구체 기준 다시 반지름을 곱해서 구체 위에 존재하도록 해야한다.

 // 원점이 중심이라고 가정
 // 입력 받은 구 모델의 반지름 조절
 for (auto &v : meshData.vertices) {
     v.position = v.normal * radius;
 }

 // 구의 표면으로 옮기고 노멀 계산
 auto ProjectVertex = [&](Vertex &v) {
     v.normal = v.position;
     v.normal.Normalize();
     v.position = v.normal * radius;

 

 

위의 그림판 이미지를 그대로 코드로 바꾼것이다. v n 을 자세히 보면 위의 그림을 표현한 코드라는 것을 알 수 있다.

새로운 정점을 만들고 그것으로 폴리곤을 추가한 것이다

 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;


     Vertex v4;
     // 위치와 텍스춰 좌표 결정
     v4.position = (v0.position + v1.position) * 0.5f;
     v4.texcoord = (v0.texcoord + v1.texcoord) * 0.5f;

     Vertex v5;
     // 위치와 텍스춰 좌표 결정
     v5.position = (v1.position + v2.position) * 0.5f;
     v5.texcoord = (v1.texcoord + v2.texcoord) * 0.5f;

     ProjectVertex(v3);
     ProjectVertex(v4);
     ProjectVertex(v5);

     // 모든 버텍스 새로 추가
     // newMesh.vertices.push_back(...);
     // ...
     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;
 }

 

맨 위 사진에 위 알고리즘을 2번 적용한 형태가 바로 아래 사진이다.

 

'DX' 카테고리의 다른 글

Rim Lighting 실습  (0) 2025.07.13
구 매핑  (0) 2025.07.13
구체 만들기  (0) 2025.07.12
실린더 모델링  (0) 2025.07.12
격자 평면 만들기  (0) 2025.07.12