[WebGL] WebGL #1 – 기초 1

개요

WebGL 스터디를 하면서 알게된 정보를 조금씩 정리합니다. WebGLFundamentals.org에서 정리된 내용을 직접 실습하면서 알게 된 지식과 느낌을 정리할 것입니다. 이 글은 첫번째 글입니다. 몇 편이 작성될지는 저 자신도 모르겠지만 글을 시작하게 된 이상 끝까지 가보려고 합니다.

기초를 다루는 글은 3편으로 나눠서 올릴 생각입니다. 최종적으로 2차원에 삼각형 및 사각형 정도를 그려볼 겁니다.

기초의 첫번째 글은 WebGL의 셰이더의 종류와 데이타를 제공하는 방법을 설명하고
두번째 글부터 실제 코드를 작성해볼 생각입니다.
세번째 글이 마무리 되면 WebGL을 이용해 삼각형 및 사각형을 그리는 것 정도는 어느 정도 쉽게 할 수 있을거라 생각합니다.

기초가 마무리되면 자연스럽게 셰이더, GLSL, 각종 변환등 3D 프로그래밍을 하는데 있어서 필요한 약간의 심화 지식을 다루게 될 것 같습니다.

WebGL에서 그림을 그리는 명령을 정의하는 방법 2가지

WebGL은 래스터화(rasterization) 엔진중 하나입니다. 여기서 래스터화라는 것은 벡터 또는 윤곽선 데이터를 비트맵으로 바꾸는 과정을 의미합니다. 개발자는 WebGL 3D API를 사용해 코드를 작성하면 점, 선, 삼각형등을 그릴 수 있습니다.

WebGL은 컴퓨터의 GPU(Graphic Processing Unit)에서 운영됩니다. 그러므로 GPU에 실행 명령을 수행하기 위한 2개의 함수가 제공되는데 각각 버텍스 셰이더(Vertex shader), 프래그먼트 셰이더(fragment shader)라고 합니다. 이 함수들은 GLSL(GL Shader Language)라고 불리는 C/C++과 같은 엄격히 규격화된 언어로 작성할 수 있습니다. GLSL에 대해서는 차차 알아가보겠습니다. 일단 이 2개의 셰이더가 무엇인지 살펴보지요.

버텍스 셰이더(Vertex shader)

버텍스 셰이더는 한국말로 꼭지점 및 정점 셰이더라고 불려도 될까요? 어쨌든 각 정점의 위치를 계산하는 역할을 하기 위해 버텍스 셰이더 함수가 호출됩니다. 작성된 함수가 최종적으로 반환하는 정점을 기준으로 점, 선 또는 삼각형을 비롯한 다양한 종류의 도형을 래스터화 할 수 있습니다. 이렇게 래스터화되면 그 다음으로 프래그먼트 셰이더의 함수가 호출됩니다.

프래그먼트 셰이더(fragment shader)

프래그먼트 셰이더는 버텍스 셰이더에 의해 래스터화된 도형 내에 각 픽셀에 들어가는 색상을 계산합니다.

2개의 셰이더의 역할을 더 쉽게 설명하자면, 버텍스 셰이더는 흰 도화지에 윤곽선을 그리는 행위를 한다면, 프래그먼트 셰이더는 물감으로 색을 칠하는 행위를 담당한다고 하면 이해가 편할까요? 사실은 셰이더가 그린다기 보다 셰이더는 GPU에게 그림을 그리도록 명령하는 것하는 것이고 그 결과가 모니터 화면에 출력되는 것이겠지요. ^^

WebGL 셰이더가 참고할 데이타를 제공하는 방법 4가지

WebGL API는 앞서 소개한 2개의 셰이더가 적절히 데이터를 참조해 그림 그리기를 실행시키는 것과 관련있습니다. 최종적으로 WebGL API에서 gl.drawArrays 나 gl.drawElements 함수를 호출하면 비로소 GPU에서 셰이더를 실행하게 됩니다. 셰이더는 그저 프로그램 조각 뿐입니다. 즉, 셰이더는 GPU에 공급된 데이터로 어떻게 그림을 그리는지 GPU에 시킬 명령들을 선언한 겁니다. 그러므로 명령을 수행하기에 앞서 셰이더가 그림을 그리기 위한 데이타를 GPU에 먼저 제공해야할 겁니다.

WebGL API에서 셰이더가 참고할 데이타를 GPU에게 제공하기 위한 방법으로 다음 4가지가 있습니다.

애트리뷰트(attributes)와 버퍼(buffers)

버퍼는 개발자가 GPU에 올릴 바이너리 배열 데이타입니다. 보통 버퍼에는 위치, 법선(normals), 텍스쳐 좌표, 버텍스 색 등과 같은 정보를 자유롭게 가질 수 있습니다.

애트리뷰트는 버퍼에서 데이타를 가져와 버텍스 셰이더에 이를 제공할 방법을 지정하는데 사용합니다. 가령, 3개의 위치를 32비트 부동소수점으로 버퍼에 넣었다면, 애트리뷰트는 버퍼에 쓰인 데이타가 버퍼의 어느 위치에 있고 몇 개를 어느 정도의 크기로 가져와야 하는지 알려주는 역할을 합니다.

이 때, 무작위로 순서로 가져올 수 없고 버텍스 셰이더가 지정한 수만큼 실행됩니다. 이 수만큼 실행 때마다 버퍼의 다음 값이 순차적으로 애트리뷰트의 값으로 할당됩니다.

유니폼(Uniforms)

유니폼은 셰이더 실행하기 전에 정의하는 전역 변수입니다. 이 전역 변수에 변환 행렬 정보나 특정 필터 정보 또는 뷰포트 정보 등을 정의해두면 셰이더가 이 변수의 데이타를 참고할 수 있습니다.

텍스쳐(Textures)

텍스처는 셰이더에서 무작위로 접근이 가능한 배열로 된 데이타입니다. 텍스처는 보통 이미지 데이터라고 생각할 수 있지만 텍스처 자체는 단순한 데이타이기 때문에 색상 뿐아니라 다른 것도 쉽게 추가시킬 수 있습니다.

배어링(Varyings)

배어링은 버텍스 셰이더에서 프래그먼트 셰이더로 데이타를 전달하는 방법을 제공합니다. 버텍스 셰이더에서 제공하는 데이타를 배어링을 통해서 프래그먼트 셰이더에 전달해줌으로써 프래그먼트 셰이더에 정의된 특정 보간 처리를 수행할 수 있습니다. 그래서 배어링은 버텍스 셰이더(제공 측)와 프래그먼트 셰이더(사용 측) 둘 다 선언되어 있어야 합니다.

결론

대략적인 기초를 살펴봤지만 처음 3D를 접한 분들에게는 생소하기만 할 겁니다. 언급한 각각의 용어들은 계속 사용되고 언급이 되기 때문에 익숙해질 수 있도록 자주 학습이 필요할 것 같네요.
WebGL 학습을 진행하면서 그 때마다 다시 돌아와 이 글을 읽으면 이해가 조금씩 되지 않을까 싶습니다.

다음 글은 삼각형을 그려보는 실습을 하면서 WebGL에 대해 구체적으로 이해해 보는 시간을 가져보겠습니다.

다음글 : WebGL #2 – 기초 2