WebGL 기초( 1 - 시작 )

WebGL 기초( 1 - 시작하기 )

기초에서는 삼각형을 그리는것을 목표로 합니다.

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

WebGL은 컴퓨터의 GPU(Graphic Processing Unit)에서 운영됩니다.
그래서 GPU에 실행명령을 수행하기 위해 셰이더가 필요하고
그 셰이더에는 2개의 함수가 제공되는데,
각각을 정점 셰이더(or 버텍스 셰이더), 프래그먼트 셰이더(or 픽셀 셰이더) 라고합니다.

이 셰이더 함수들은 GLSL(GL Shader Language)라고 하는 C/C++ 언어로 작성할 수 있습니다.
(GLSL에 대해서는 후에 설명)

셰이더(Shader)

셰이더란 화면에 출력할 픽셀의 위치와 색상을 계산하는 함수입니다.

정점은 셰이더로 넘겨줄 수 있는 어트리뷰트를 갖고 있습니다.
또한 각 정점별로 일정한 유니폼 값도 셰이더로 넘겨 줄 수 있는데,
자세한 내용은 뒤에 다루기로 하겠습니다.

지금은 셰이더엔 정점 셰이더프래그먼트 셰이더가 있고,
하는일은 아래와 같다는 정도만 알고 있기로 합니다.

  • 정점(vertex) 셰이더 : 정점의 최종 위치를 설정
  • 프래그먼트 셰이더 : 각 픽셀의 최종 색상을 설정

화면안의 그려줄 영역의 위치를 계산해 주는 함수를 정점 셰이더라고 하고,
영역안의 픽셀들마다 색상을 계산해서 그려주는 함수를
프래그먼트 셰이더(픽셀 셰이더) 라고합니다.

셰이더과정
이미지 출처 : [https://github.com/ejonghyuck/TIL/blob/master/Shader/shader.md]

셰이더가 참고할 데이터를 제공하는 방법

셰이더는 GPU에 공급된 데이터로 어떻게 그림을 그리는지 GPU에 시킬 명령들을 선언한 함수일뿐입니다.
함수를 실행하기 전에 셰이더가 그림을 그리기 위한 데이터를 GPU에 제공해야하는데

방법으로는 4가지가 있습니다.

  1. 애트리뷰트
    애트리뷰트는 버터를 사용합니다.
    버퍼 : 개발자가 GPU에 올려줄 바이너리 배열 데이터입니다.
    또한 애트리뷰트는 vertex shader에서만 사용되며 읽기 전용 값 입니다.

  2. 유니폼
    유니폼은 셰이더 실행하기 전에 정의하는 전역 변수입니다.
    이 전역 변수에 변환 행렬 정보나 특정 필터 정보 또는 뷰포트 정보 등을 정의해두면 셰이더가 이 변수의 데이타를 참고할 수 있습니다.
    JavaScript에서 uniformMatrix#fv()를 통해 전달 받은 값을 저장하며 주로 변형(이동, 회전, 스케일)을 계산하기 위한 벡터가 넘어옴

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

  4. 배어링
    버텍스 셰이더에서 만든 데이터를 프래그먼트 셰이더에게 전달하는데 쓰입니다.
    vertex shader에서 계산된 값을 fragment shader로 전달해 줄 때 사용합니다.

Ex) 버텍스 셰이더와 프래그먼트 셰이더

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!doctype html>
<html>
<head>
<title>WebGL</title>
<style>
body { background: grey; }
canvas { background: white; }
</style>
</head>
<body>
<!-- 캔버스 정의 - WebGL의 결과 랜더링 -->
<canvas id="my-canvas" width="500" height="500"></canvas>

<!-- 버텍스 셰이더 작성 -->
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;

void main(void) {
gl_Position = vec4(aVertexPosition, 1.0);
}
</script>

<!-- 프래그먼트 셰이더 작성 -->
<script id="shader-fs" type="x-shader/x-fragment">
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
</body>
</html>

코드를 보시면 각 셰이더에서
type 은 text/javascript가 아닌 임의의 값을 주면 됩니다.
이유는 셰이더가 javascript로 해석되지 않도록 하는 것이 목적이기 때문입니다.

셰이더에서 attribute vec3 aVertexPosition
attribute : 셰이더 변수 종류( attribute | uniform | varying )
vec3 : 배열 타입, vec3는 3행 배열
aVertexPosition : 배열 이름, 한 개의 버텍스를 나타냅니다. 관습적으로 맨 앞에 a를 붙여서 attribute임을 표시를 나타냅니다.

WebGL의 기본이 되는 canvas는 HTML5 스펙입니다.

1
2
3
4
5
<div>
<canvas id="my-canvas" width="400" height="300">
해당 브라우저는 html5 canvas element를 지원하지 않습니다.
</canvas>
</div>

기본 canvas 화면

※ html5 canvas 미지원시
‘해당 브라우저는 html5 canvas element를 지원하지 않습니다.’를 출력합니다.

WebGL 기초

canvas는 ‘2D’와 ‘webgl’이라는 두개의 캔버스 context가 있습니다.

canvas는 둘 중 어떤 컨텍스트를 사용하든 상관하지 않지만
원하는 API를 노출하는 적절한 객체를 제공해주려면
canvas에게 명시적으로 알려줘야 합니다.

context를 가져오려면 canvas의 getContext 메소드를 호출하면됩니다.

  • getContext
  • 첫번째 파라미터 : context 타입
  • 두번째 파라미터 : context 속성

Ex) canvas.getContext(‘experimental-webgl’, {
antialias: false, // 앤티 앨리어싱을 수행할지 여부를 나타내는 부울 값입니다.
depth: false // 캔버스에 알파 버퍼가 있는지 여부를 나타내는 부울입니다.
});
// experimental-webgl은 WebGL이 정식으로 지원되지 않을 때 사용되던 이름

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
window.onload = setupWebGL;
var gl = null;
// gl 은 웹지엘에서 컨텍스트 객체를 참조할 때 관례적으로 사용하는 변수명
function setupWebGL() {
var canvas = document.getElementById("my-canvas");
try{
gl = canvas.getContext('experimental-webgl');
}catch (e){
//컨텍스트 가져오지 못하여 에러 발생시
}

if(gl){
gl.clearColor(1.0, 0.5, 1.0, 1,0);
// clearColor(R,G,B,A)
gl.clear(gl.COLOR_BUFFER_BIT);
}else {
alert('WebGL 지원 안함')
}
}

Comments: