OBJ: Wave Front 사에서 만든 그래픽스 모델 규격
파일 안에는 정점위치, 노멀 벡터 위치, 텍스처 좌표가 기록되어져있다.
이런식으로...
g default
v -1.708279 2.424356 1.104725
v -0.853093 2.524068 1.104725
v -1.708279 2.424356 -1.127302
v -0.853093 2.524068 -1.127302
해당 폴리곤이 어떤 재질을 선택하고 있는지는
usemtl 이라는 키워드로 지시하고 있다.
usemtl initialShadingGroup # initialShadingGroup mtl을 선택함
f 1/1/1 6/2/2 39/3/3 40/4/4
s 2
f 14/5/5 15/6/6 77/99/7 76/98/8
mtl은 재질의 성질, 텍스처 정보를 담고있는 파일이다.
newmtl D:blinn1SG
illum 4
Kd 0.50 0.50 0.50 // diffuse
Ka 0.00 0.00 0.00 // Ambient
Tf 1.00 1.00 1.00 // Transmission filter
Ni 1.00 // Refraction Index (Opacity)
Ks 0.50 0.50 0.50 // Specular
webgl로 화면에 띄우기 위해서는 OBJ와 MTL을 둘 동시에 파싱해야한다.
WebGL을 사용한다는 것은 그래픽 카드를 이용한다는 의미이다.
그래픽 카드의 경우 CPU -> GPU로 데이터를 넘길때 병목이 많이 일어난다.
따라서 최대한 이득을 취하기 위해선 한번에 CPU -> GPU로 데이터를 많이 뽑아내어야한다.
따라서 파싱한 OBJ정보는 최대한 직렬화 시켜서 GPU로 보내야 할것이다.
그래픽 카드에서 돌릴 쉐이더 프로그램에 대해서도 생각해보자. 대략 이렇게 생겼을것이다.
uniform vec3 u_materialAmbient; // MTL 파일에 있는 정보
uniform vec3 u_materialDiffuse; // MTL 파일에 있는 정보
uniform vec3 u_materialSpecular; // MTL 파일에 있는 정보
uniform vec3 u_materiaShininess; // MTL 파일에 있는 정보
out vec4 o_color;
void main() {
color = BlinnPhong(...);
o_color;
}
uniform으로 material 정보를 내려주고 프래그먼트 쉐이더에서 이를 받아 처리해야한다.
하나의 Object에서 material은 여러개이므로 중간중간 uniform buffer를 바꿔가면서 그려야할것이다.
이제 OBJ MTL 데이터에 대해서 생각해보자. 그림으로 간략하게 표현하다면 이런 느낌일것이다.
하나의 MTL을 여러 OBJ 정보가 선택해서 사용하는 N:1 관계일것이다.
이 관계에서 내가 생각한 최선의 방법은
MTL을 기준으로 그리는것이 최선일것이라 생각했다.
OBJ, MTL을 모두 파싱하여 데이터를 뽑아낸 후
MTL 기준으로 OBJ를 다시 정렬한다.
렌더링 할때는 MTL을 돌면서 OBJ들을 하나씩 렌더링한다. (draw elements)
물론 모든 object 정보들은 첫 객체 생성 시점에 데이터를 직렬화 시켜서 vertex array를 만드는것도 잊지않는다.
그렇게 만든 코드가 이것이다.
https://github.com/lacomaco/laco3DRenderer/blob/main/src/models/model.ts
그냥 일반적인 프로그래밍은 이렇게 세세한 하드웨어까지 신경써주지 않아도 되는데 그래픽스 프로그래밍 할때는 고려해야한다.
그렇기 때문에 더 재밌고, 더 성능이 좋고, JS만으로는 할 수 없는 일들을 할 수 있게 만들어준다.
계속진행하자. 다음 글은 Blinn Phong에 대해서 글을 써볼까한다.