정보공간_1

[6기 수원 최웅엽] WebGL 애니메이션과 셰이더 본문

IT 놀이터/Elite Member Tech & Talk

[6기 수원 최웅엽] WebGL 애니메이션과 셰이더

알 수 없는 사용자 2014. 11. 26. 14:51

WebGl의 에니메이션 



WebGl의 에니메이션에는

window.setTimeout(고정된 지연시간 후 함수호출)

window.setInterval(고정 주기를 갖고 반복적으로 호출)

window.requestAnimationFrame(비슷하지만 활성화된 브라우져만 실행, 모바일기기에서 효율이 좋다.)

이 세가지 함수를 이용하여 animation함수를 지속적으로 호출하는 방법으로 만들게 됩니다.


하지만 마지막 함수는 지원하는 브라우저가 정해져있고 몇가지 문제점이 있습니다.

첫번째는 브라우저에 따라 cancelAnimationFrame라는 requestAnimationFrame를 취소하는 기능을 가진 함수가 없을 수 있습니다. 두번째는 iOS6이상에 touchend시점에 requestAnimationFrame이 처음 실행하면 동작하지 않는 경우가 있습니다. 이런 여러 문제를 해결하기 위해 동작하지 않는 기능을 만들어주어 작동하게 하는 방법이 연구되고 이를 polyfill이라고 합니다


(https://gist.github.com/paulirish/1579671 에서 requestAnimationFrame에 대한 polyfill.js를 받을 수 있습니다. - MIT Licence)

 

전 강의의 코드를 prototype으로 바꾸고 setupBuffers함수를 수정하여 간단한 애니메이션을 만들어 보면






지금은 카메라를 구현하지않고 물체만 이동시키기 때문에 z좌표를 아무리 변화시켜도 확실히 보이지 않습니다그래서 우리는 카메라의 투영 매트릭스로 변환을 해야합니다.

이를 위해 수학의 행렬연산이 필요하고 또한 이외에도 물체를 이동, 회전, 크기변화를 하기 위해서도 행렬연산은 필수입니다. 이를 위해 라이브러리를 사용합니다. https://github.com/toji/gl-matrix



이를 돌리면 오른쪽 화면으로 삼각형이 잘리는 것을 볼 수 있는데 이는

this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);

이렇게 뷰포트를 재설정해 줍니다.



 

이제까지 물체를 그리고 셰이더를 적용하고 간단하게 움직이고 카메라를 바꿔보는 작업을 했다면 이번에는 셰이더에 대해서 더 알아보겠습니다.


셰이더를 사용하면 보다 현실감있는 그래픽을 구현 가능합니다. 광원이나 안개, 투명하게 비치는 효과를 낼 수도 있고 속도 면에서도 GPU가속을 사용할 수 있어 단일 쓰레드로 도는 웹 상에서 그래픽 성능을 끌어올릴 수 있습니다.(javascript로 하는 것보다 css3로 움직임을 표현하는 것이 더 자연스럽고 빠른 것과 같습니다.)


셰이더는 고정 셰이더와 유동 셰이더가 있는데, 말 그대로 고정 셰이더는 처음 프로그래밍한 좌표와 색상으로 광원이나 반사광 색 등을 끄거나 키는 것 외에는 고정되는 것이고 유동 셰이더는 이를 수정할 수 있는 것입니다.


웹 지엘에서는 자바스크립트를 이용해 셰이더 코딩을 하면 위의 코드와 같이 <script type=”x-shader/x-vertex”> 또는 <script type=”x-shader/x-fragment”>라고 표시하게 되고, 이는 브라우져에서 일반 javascript가 아닌것으로 인식 되어 무시하게 됩니다.


1.     픽셀 셰이더

모든 정점 변환을 여기에 프로그래밍하며 정점의 위치나 법선 텍스쳐 광원 색상등을 함께 하기도 합니다. 앞에서의 코드에서는 버텍스 셰이더에서 색상을 지정했지만 양쪽에서 다 가능합니다. 단 어느쪽에 코드를 적느냐에 따라 총 연산량에 영향을 미치기도 하는데 이는 나중에 다시 알아보겠습니다.


2.     버텍스 셰이더

버텍스 셰이더는 만들어진 도형에 대한 픽셀에 대해 작업을 합니다. 최종 픽셀별 생상과 텍스쳐 좌표를 계산하기도 하며 안개 효과를 내는데도 사용됩니다. 이때 픽셀 셰이더에서 보낸 값을 최종 수정하고 확정하는 곳이며 보내준 값들을 변경할 수 있습니다.


3.     사용법

셰이더 프로그램을 만들고
var shader_pro = gl.createProgram();


버텍스 셰이더와 정점 셰이더를 생성한다.
vertex_shader = gl.createShader(GL.VERTEX_SHADER)
fragment_shader = gl.createShader(GL.FRAGMENT_SHADER)


각 셰이더의 코드를 생성하고 이를 셰이더에 대입한다.
<script id=”shader_vs_code” type=”x-shader/x-vertex”></script>
<script id=”shader_fs_code” type=”x-shader/x-fragment”></script>

gl.shaderSource(vertex_shader, document.getElementById(“shader_vs_code”));
gl.shaderSource(fragment _shader, document.getElementById(“shader_fs_code”));


그리고 이를 컴파일하라는 명령을 API에 보내고

gl.compileShader(vertex_shader);
gl.compileShader(fragment_shader);
if( !(gl.getShaderParameter(vertex_shader, gl.COMPILE_STATUS)) ||
!( gl.getShaderParameter(fragment_shader, gl.COMPILE_STATUS) ){
console.log(“error:compile_shader”);return;
}
 


프로그램에 대입한다.

gl.attachShader(shader_pro, vertex_shader);
gl.attachShader(shader_pro, fragment_shader);


이를 gl에 링크시키고 사용하게 만든다

gl.linkProgram(shader_pro);
if(!gl.getProgramParameter(shader_pro, gl.LINK_STATUS,)){
console.log(“error:link_shader_pro”); return ;
}

gl.useProgram(shader_pro)


4.     해제법


gl.detachShader(shader_pro, vertex_shader)
gl.detachShader(shader_pro, fragment_shader)

gl.deleteShader(vertex_shader)
gl.deleteShader(fragment_shader)

gl.deleteProgram(shader_pro)


지금까지 애니메이션을 하기위한 loop를 만드는 법. Shader의 기본과 shader를 사용하기위한 순서를 배웠고 다음에는 shader에 대해 더 깊이 알아보도록 하겠습니다.