2010년 9월 6일 월요일

Klotz 릴리즈까지 남은 것들

병특 시작한 이래 작업을 거의 못 하고 있었습니다. 계속 이렇게 방치해둘 수는 없다는 생각에 첫번째 베타 릴리즈까지 해야 할 점들을 정리해 둡니다.

렌더링 엔진 개선


1. Back Face Culling (BFC)


단순히 뒷면을 거르는 것만의 문제가 아닌, 제대로 된 surface normal vector를 구하기 위해서 꼭 구현해야 하는 거라서 릴리즈 전까지는 작업을 해야 하는 부분입니다.

보통 3D 하면 BFC는 기본이지만, LDraw 스펙에서 BFC는 필수가 아니며 일종의 확장으로 구현이 되어 있습니다. 물론 대부분의 primitive는 BFC-compilant하지만 만에 하나 그렇지 않은 경우를 위해서 예외 처리를 해 두어야 합니다.

지금 BFC 자체는 구현이 거의 되어 있지만 렌더링 코드에서 문제가 계속 발생하고 있습니다. 분명히 스펙대로 짰는데 subfile inclusion시 가끔 normal이 역전되는 문제가 발견되고 있습니다. 지금 여기서 작업이 막혀 있는데 그래서 요즘 능력의 부족함을 통감하고 있습니다. 고등학교때 수학 수업 좀 더 제대로 들어 놓을 걸 그랬네요.


2. Vertex Buffer Object (VBO)


지금 렌더링 코드는 전부 glBegin - glVertex - glEnd로 구현이 되어 있습니다. 가장 기본적이며 간단한 방법임과 동시에 가장 비효율적이기도 합니다. 정점 하나 찍거나 색깔 하나 찍는데 함수 호출 하나라니 함수 호출 오버헤드만 해도 상당한 수준이겠지요. 결국 이 방식은 OpenGL ES와 최신 OpenGL 4 스펙에서 (고정기능 파이프라인 함수들과 함께) deprecate된 semantics라 portability를 위하여 VBO 기반으로 코드를 전부 뜯어고칠 필요가 있습니다.

문제는 LDraw 포맷의 계층적 구조가 그닥 VBO와 친하지 않다는 것입니다.




보시다시피 LDraw 모델은 최상단에 모델 파일이 있고 거기서 다른 서브파일들을 참조하는 방식으로 구성이 되어 있습니다. 그리고 가장 밑에 있는 part 혹은 subpart, primitive에서 실제 선, 삼각형, 사각형과 같은 정보를 담고 있습니다.

그럼 여기서 어디까지를 VBO로 만들 것인지의 문제가 있습니다.

  1. 전체 모델 : 버퍼 하나를 만들어서 거기에 모든 데이터를 넣습니다. 가장 단순한 방식이나 모델에 수정이 가해지만 버퍼 전체의 내용을 새로 만들어야 합니다.
  2. Part : 모델 레벨에서 가장 기본적인 단위까지 VBO를 만듭니다. 그러니 part 하나 하나가 object가 되는 방식이지요. 언뜻 합리적으로 보이나 밑에 얽혀있는 수많은 primitive 데이터가 각 part마다 중복되어 들어가므로 메모리가 낭비되는 문제가 있습니다.
  3. Primitive : primitive 도형들에 대해서 VBO를 만듭니다. 다만 primitive의 색상은 caller의 색상을 따르므로, 그릴 때마다 버퍼의 색상 정보를 일일히 업데이트합니다. 색상 정보를 바꾸는 데 드는 오버헤드가 어느 정도인지는 아직 모릅니다.

1번은 그닥 고려할만한 가치가 없을 것 같고 2번 혹은 3번을 선택해야 할 것 같은데, 일단 두 가지 경우를 모두 테스트해 보고 최선이 무엇인지 가늠해 본 다음에 결정해야 하겠습니다.


3. Line type 5


LDraw 스펙 문서에 보면 Line type 5가 있습니다. 간단히 설명하면 두 쌍의 벡터가 있는데, 각 벡터를 현재 projection 행렬에 곱합니다. 그럼 그 두개의 벡터가 2차원 평면에 사상되는데, 이 벡터가 서로 평행(identical)이라면 그립니다. 한 마디로 말하면 둥근 오브젝트의 경계선을 그리기 위한 엘리먼트라고 보시면 됩니다.

현재 카메라 시점에 따라 그리는 결과물이 달라지므로 미리 계산할 수는 없고 매번 렌더링할 때마다 검사하여 그리는 엘리먼트이기 때문에 아직 렌더러를 프로파일링해보지 않아 모르긴 몰라도 아마 부하가 상당할 겁니다.

그러므로 이걸 최적화하는 것도 과제 중 하나인데, vertex shader를 이용할 생각입니다. 몇십 줄의 ARB program으로도 구현이 가능할 것 같네요.

단, 요즘 대부분 그래픽 카드가 프로그래머블 파이프라인이라 걱정할 필요는 없지만 리눅스 환경에서 몇몇 오픈 소스 3D 드라이버는 아직 쉐이더 구현이 미비하거나 아예 없으므로 CPU fallback을 마련해야 할 것 같습니다.

레이트레이서(POV-Ray) 연동


POV-Ray 3.6까지는 정상 작동하나 POV-Ray 3.7 베타로 테스트해보니 안 되더군요. 그래서 문제를 분석하다가 POV-Ray 소스 코드를 뒤져보니 stdout으로 출력물을 보내는 기능 전체가 주석 처리되어 있었습니다. 지금 구현은 POV-Ray에서 targa 포맷의 이미지를 stdout으로 스트리밍하고 Klotz에서 이걸 받아서 실시간으로 보여주게 되어 있는데 POV-Ray 3.7이 베타라서 이 기능을 임시로 빼 놓은 모양이더군요. 하긴 3.7에 SMP 기능이 들어가서 렌더링 결과가 깍두기로 나오더니 제대로 되려나 싶었습니다.

이걸 발견한 게 작년의 일이니 지금은 고쳐졌을지 모르겠군요. 시간 되면 한번 알아봐야겠습니다.


UI 및 편집기 개선사항


1. de-KDE-ify


Klotz에서 KDE 라이브러리를 쓴 건 다음 이유에서였습니다.

  1. XMLGUI
  2. 설정 파일 통합
  3. KDE와의 UX integration

리눅스의 KDE 환경에서 KDE와의 통합은 적절한 선택이었다고 생각하지만 다른 플랫폼(Mac OS X, 윈도)으로 가면 상황이 달라집니다. 고작 캐드 프로그램 하나 쓰겠답시고 그 크고 무거운 KDE 환경 전체를 끌고 와야 할 필요는 없지요.

그래서 윈도와 맥의 경우 (그리고 리눅스에서도 선택적으로) KDE 라이브러리를 제외하는 작업이 필요합니다. KDE에 의존적인 코드가 많지 않아서 그나마 다행이지만 더 급한 문제가 많으니 지금 당장은 어렵고 장기적으로 해야 하겠습니다.


2. Cut, Copy and Paste


이거 안되면 캐드 맞나요? (…)


3. 설정 GUI


기본 설정은 너무 빈약하고, 레이트레이서 설정은 아예 없습니다. 이런 단순한 UI 작업은 단지 노가다일 뿐이라 선뜻 손이 가지 않네요.


4. Data model 개선


가끔씩 편집하다 보면 DataModel이 깨지더군요. Model은 솔직히 귀찮아서 야매로 구현했는데 (Qt의 MVC 구현이 너무 복잡해서…) 조금 시간이 걸릴 것 같긴 하지만 시간 들여서 조금씩 고쳐 나가야 하겠습니다.




인증샷. 앞서 말한 BFC 버그 때문에 쉐이딩이 엉망이군요.

0 개의 댓글:

댓글 쓰기