이번에는 WebGL을 이용한 Animation을 표현해 보도록하겠다. OpenGL이든 Direct3D이든 Geometry에 대한 연산을 행렬 형태로 표현하고 있음을 잘 알고 있을 것이다. 이동/회전/크기변환 등을 행렬로 표현하면 여러가지 장점이 있어 사용할 뿐, 필수 사항은 아닐 것이다. 이번장에서는 행렬을 사용하지 않고 아주 간단한 Animation을 표현할 것인데, 그 이유는, 행렬을 표현함에 있어 javascript를 이용해야 하기 때문이다. 본 문서들은 javascript에 익숙하지 않다는 가정을 하고 있으므로, javascript로 행렬을 표현하는 방법은 차후 다루기로 하겠다.
WebGL에서 Animation을 표현하는 방법은 GLSL을 이용한 방법외에는 존재하지 않다라고 해도 무방할 것이다. 그 이유는 다음의 예를 보면 알 수 있을 것이다. 삼각형에 대한 이동을 수행하겠다고 가정하자. 가능한 방법은, 첫째 WebGL을 표현하는 Canvas를 직접 이동시키거나(이것은 어이없는 행동이 될 것이다.), 둘째 삼각형의 각 버텍스를 javascript를 이용하여 옮기거나(버텍스의 값이 변경 될 때 마다 GLSL로 넘어갈 버퍼의 갱신이 이루어 지므로 비효율), 셋째 javascript가 GLSL에게 삼각형의 이동을 위한 값(3차원 좌표, 더 나은 방법은 행렬)을 넘기는 방법(가장 이상적) 들이 있다. 본 예제에서는 당연히 세번째 방법을 사용할 것이다.
이전의 예제에서 아래와 같은 Vertex Shader 코드를 사용했음을 기억할 것이다.
이 코드에서 "버텍스의 위치값"에 해당하는 변수명이 "aPos"이다. 바로 "aPos"의 값을 적당히 변경하면 삼각형의 이동이 이루어 질 것이다. 그렇다면, 어떻게 적당히 변경할 것이가?
[code WebGL]
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0);
vColor= aColor;
}
</script>
[/code]
한 예로, gl_Position= vec4(aPos, 1.0)를 gl_Position= vec4(aPos, 1.0) + vec4(0.5, 0, 0, 0)으로 변경하면, 삼각형이 오른쪽으로 0.5만큼 이동할 것이며, 그 결과는 아래와 같을 것이다.
[code WebGL]
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + vec4(0.5, 0, 0, 0);
vColor= aColor;
}
</script>
[/code]

이는 삼각형이 이동만 했을 뿐 당연히 Animation이라고 부를 수 없다. Animation이라 부를 수 있으려면 적어도 움직인다라는 느낌이 들 수 있어야 하므로, 적당한 매 시간마다 이동의 값을 바꾸어가며 화면을 갱신할 필요가 있다. javascript에서는 setInterval(...)이라는 함수를 이용하여, '사용자가 설정한 매 시간마다, 특정 함수를 호출'하는 기능을 수행할 수 있다. 이 함수에서 삼각형의 위치값을 변경하고, 변경된 값을 GLSL로 넘긴 후, 화면의 갱신을 수행하게 한다면, Animation 표현이 가능하게 될 것이다. 주의할 점은, Animation 표현을 위해 매 시간마다(이하 매 프레임 마다) 불려져야할 구문들과 단 한번만 불려져도 되는 구문들을 구분해야 한다는 것이다. 매 프레임마다 버퍼를 생성한다거나, Shader Script를 읽기/컴파일/링킹등을 수행하는 것과 같은 불필요한 작업은 반드시 피해야 한다.
(지금부터 변수명을 조금 수정해 보도록하겠다. GLSL에서의 변수명 "aPos"에 대한 핸들을 var vertexPositionAttribute; 로 선언 했었는데, 이를 g_hVertPos로 변경하고, "aColor" 핸들에 대한 변수명을 g_hVertColor로 변경한다. "g_"는 전역에 위치한 변수라는 뜻이고, h는 핸들, 그 다음은 변수 고유의 이름)
앞서 살펴보았던 Vertex Shader코드를 다음과 같이 변경한다.
[code WebGL]
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
uniform vec4 trans;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + trans;
vColor= aColor;
}
</script>
[/code]
위의 코드는 GLSL의 Vertex Shader로 넘어오는 mesh의 각 Vertex의 위치에 trans값을 더해 줌을 볼 수 있다. 따라서 mesh의 모든 Vertex의 위치값에 trans를 더해 줌으로서 mesh의 이동이 수행되는 것이다. 이제, javascript에서 변수명 "trans"의 핸들을 얻을 차례이다. 이 핸들이 있어야만 GLSL에 값을 넘길 수 있기 때문이다.(==Vertex Shader에 값을 넘길 수 있기 때문이다.)
[code WebGL]
//GLSL에서 "trans"라는 변수명의 핸들을 얻음
g_hTrans= gl.getUniformLocation(shaderProgram, "trans");
if( g_hTrans==-1 ){
alert("Unable to find 'trans' Uniform Location.");
return false;
}
[/code]
javascript의 변수명 "g_hTrans"가 GLSL의 "trans"의 핸들이다. "trans"가 uniform으로 선언되어 있으므로, 핸들을 얻는 함수역시 getUniformLocation이다. 이제 g_hTrans을 이용하여, GLSL에 값을 넘길 차례이다.
아래는 g_hTrans핸들을 통해 GLSL에 값을 전달하는 함수이다.
[code WebGL]
gl.uniform4f(g_hTrans, 0.5, 0, 0, 0);
[/code]
g_hTrans핸들은 GLSL에서의 uniform vec4 trans;를 참조하고 있으므로, 값을 넘길 때 uniform4f를 사용해야 한다. 여기까지 수행 하면 앞서 보였던 결과와 같은 결과를 얻을 수 있다.
소소코드는 아래와 같다.
[code WebGL]
<html>
<head>
<title>WebGL - Prac06 - Animation</title>
<script type="text/javascript">
var gl;
var g_hVertPos;
var g_hVertColor;
var g_hTrans;
function start(){
if( !initWebGL() ){
return;
}
if( !initShader() ){
return;
}
var verAry= [
0.0, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 1.0, 0.0
];
var colorAry= [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
var glBufVert= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verAry), gl.STATIC_DRAW);
var glBufColor= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorAry), gl.STATIC_DRAW);
gl.clearColor(0.4, 0.5, 0.6, 1.0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.vertexAttribPointer(g_hVertPos, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.vertexAttribPointer(g_hVertColor, 4, gl.FLOAT, false, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//x좌표 값을 변경 시킨 후 GLSL에 넘긴다.
gl.uniform4f(g_hTrans, 0.5, 0, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function initWebGL(){
var canvas= document.getElementById("WebGL-Canvas");
if( !canvas ){
alert("Can't find WebGL-Canvas.");
return false;
}
try{
gl= canvas.getContext("experimental-webgl");
}catch(e){
}
if( !gl ){
alert("Unable to initialize WebGL. Your browser may not support it.");
return false;
}
return true;
}
function initShader(){
var vertexShaderDesc= getShader("VertexShader");
var vertexShader= gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderDesc);
gl.compileShader(vertexShader);
if( !gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) ){
alert("Error(VertexShader): " + gl.getShaderInfoLog(vertexShader));
return false;
}
var fragmentShaderDesc= getShader("FragmentShader");
var fragmentShader= gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderDesc);
gl.compileShader(fragmentShader);
if( !gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) ){
alert("Error(FragmentShader): " + gl.getShaderInfoLog(fragmentShader));
return false;
}
var shaderProgram= gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) ){
alert("Unagle to initialize the shader program.");
return false;
}
gl.useProgram(shaderProgram);
g_hVertPos= gl.getAttribLocation(shaderProgram, "aPos");
if( g_hVertPos==-1 ){
alert("Unable to find Vertex Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertPos);
g_hVertColor= gl.getAttribLocation(shaderProgram, "aColor");
if( g_hVertColor==-1 ){
alert("Unable to find Vertex Color Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertColor);
//GLSL에서 "trans"라는 변수명의 핸들을 얻음
g_hTrans= gl.getUniformLocation(shaderProgram, "trans");
if( g_hTrans==-1 ){
alert("Unable to find 'trans' Uniform Location.");
return false;
}
return true;
}
function getShader(id){
var shaderScript= document.getElementById(id);
if( !shaderScript ){
alert("Unable to get shader script. id='" + id + "'");
return null;
}
var shaderDesc= "";
var currentChild= shaderScript.firstChild;
while( currentChild ){
if( currentChild.nodeType==3 ){
shaderDesc+= currentChild.textContent;
}
currentChild= currentChild.nextSibling;
}
return shaderDesc;
}
</script>
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
uniform vec4 trans;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + trans;
vColor= aColor;
}
</script>
<script id="FragmentShader" type="x-shader/x-vertex">
precision mediump vec4;
varying vec4 vColor;
void main(){
gl_FragColor= vColor;
}
</script>
</head>
<body onload="start()">
<canvas id="WebGL-Canvas" style="border: 1px solid green" width="400" height="300">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
</body>
</html>
[/code]

이제 javascript의 setInterval(...)함수를 이용하여, 매 프레임을 갱신하고, 삼각형의 위치를 변경시켜 보도록 하겠다. 본 예제에서는 아주 단순히 삼각형의 x좌표의 위치만 변경시켜 보도록 하겠다. 삼각형의 x좌표는 매 프레임 마다 어떤 함수에서 갱신될 것이므로 x좌표에 대한 변수는 전역으로 선언해 두고 값을 갱신해 나가야 할 것이다.
소스코드는 아래와 같다.
[code WebGL]
<html>
<head>
<title>WebGL - Prac06 - Animation</title>
<script type="text/javascript">
var gl;
var g_hVertPos;
var g_hVertColor;
var g_hTrans;
var g_transPosX=0;
function start(){
if( !initWebGL() ){
return;
}
if( !initShader() ){
return;
}
var verAry= [
0.0, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 1.0, 0.0
];
var colorAry= [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
var glBufVert= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verAry), gl.STATIC_DRAW);
var glBufColor= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorAry), gl.STATIC_DRAW);
gl.clearColor(0.4, 0.5, 0.6, 1.0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.vertexAttribPointer(g_hVertPos, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.vertexAttribPointer(g_hVertColor, 4, gl.FLOAT, false, 0, 0);
//0.05초 마다 drawScene 호출
setInterval(drawScene, 50);
}
function drawScene(){
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//x좌표 값을 변경 시킨 후 GLSL에 넘긴다.
g_transPosX+= 0.01;
if( g_transPosX>0.5 ) g_transPosX= 0;
gl.uniform4f(g_hTrans, g_transPosX, 0, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function initWebGL(){
var canvas= document.getElementById("WebGL-Canvas");
if( !canvas ){
alert("Can't find WebGL-Canvas.");
return false;
}
try{
gl= canvas.getContext("experimental-webgl");
}catch(e){
}
if( !gl ){
alert("Unable to initialize WebGL. Your browser may not support it.");
return false;
}
return true;
}
function initShader(){
var vertexShaderDesc= getShader("VertexShader");
var vertexShader= gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderDesc);
gl.compileShader(vertexShader);
if( !gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) ){
alert("Error(VertexShader): " + gl.getShaderInfoLog(vertexShader));
return false;
}
var fragmentShaderDesc= getShader("FragmentShader");
var fragmentShader= gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderDesc);
gl.compileShader(fragmentShader);
if( !gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) ){
alert("Error(FragmentShader): " + gl.getShaderInfoLog(fragmentShader));
return false;
}
var shaderProgram= gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) ){
alert("Unagle to initialize the shader program.");
return false;
}
gl.useProgram(shaderProgram);
g_hVertPos= gl.getAttribLocation(shaderProgram, "aPos");
if( g_hVertPos==-1 ){
alert("Unable to find Vertex Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertPos);
g_hVertColor= gl.getAttribLocation(shaderProgram, "aColor");
if( g_hVertColor==-1 ){
alert("Unable to find Vertex Color Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertColor);
//GLSL에서 "trans"라는 변수명의 핸들을 얻음
g_hTrans= gl.getUniformLocation(shaderProgram, "trans");
if( g_hTrans==-1 ){
alert("Unable to find 'trans' Uniform Location.");
return false;
}
return true;
}
function getShader(id){
var shaderScript= document.getElementById(id);
if( !shaderScript ){
alert("Unable to get shader script. id='" + id + "'");
return null;
}
var shaderDesc= "";
var currentChild= shaderScript.firstChild;
while( currentChild ){
if( currentChild.nodeType==3 ){
shaderDesc+= currentChild.textContent;
}
currentChild= currentChild.nextSibling;
}
return shaderDesc;
}
</script>
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
uniform vec4 trans;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + trans;
vColor= aColor;
}
</script>
<script id="FragmentShader" type="x-shader/x-vertex">
precision mediump vec4;
varying vec4 vColor;
void main(){
gl_FragColor= vColor;
}
</script>
</head>
<body onload="start()">
<canvas id="WebGL-Canvas" style="border: 1px solid green" width="400" height="300">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
</body>
</html>
[/code]
WebGL에서 Animation을 표현하는 방법은 GLSL을 이용한 방법외에는 존재하지 않다라고 해도 무방할 것이다. 그 이유는 다음의 예를 보면 알 수 있을 것이다. 삼각형에 대한 이동을 수행하겠다고 가정하자. 가능한 방법은, 첫째 WebGL을 표현하는 Canvas를 직접 이동시키거나(이것은 어이없는 행동이 될 것이다.), 둘째 삼각형의 각 버텍스를 javascript를 이용하여 옮기거나(버텍스의 값이 변경 될 때 마다 GLSL로 넘어갈 버퍼의 갱신이 이루어 지므로 비효율), 셋째 javascript가 GLSL에게 삼각형의 이동을 위한 값(3차원 좌표, 더 나은 방법은 행렬)을 넘기는 방법(가장 이상적) 들이 있다. 본 예제에서는 당연히 세번째 방법을 사용할 것이다.
이전의 예제에서 아래와 같은 Vertex Shader 코드를 사용했음을 기억할 것이다.
이 코드에서 "버텍스의 위치값"에 해당하는 변수명이 "aPos"이다. 바로 "aPos"의 값을 적당히 변경하면 삼각형의 이동이 이루어 질 것이다. 그렇다면, 어떻게 적당히 변경할 것이가?
[code WebGL]
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0);
vColor= aColor;
}
</script>
[/code]
한 예로, gl_Position= vec4(aPos, 1.0)를 gl_Position= vec4(aPos, 1.0) + vec4(0.5, 0, 0, 0)으로 변경하면, 삼각형이 오른쪽으로 0.5만큼 이동할 것이며, 그 결과는 아래와 같을 것이다.
[code WebGL]
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + vec4(0.5, 0, 0, 0);
vColor= aColor;
}
</script>
[/code]
이는 삼각형이 이동만 했을 뿐 당연히 Animation이라고 부를 수 없다. Animation이라 부를 수 있으려면 적어도 움직인다라는 느낌이 들 수 있어야 하므로, 적당한 매 시간마다 이동의 값을 바꾸어가며 화면을 갱신할 필요가 있다. javascript에서는 setInterval(...)이라는 함수를 이용하여, '사용자가 설정한 매 시간마다, 특정 함수를 호출'하는 기능을 수행할 수 있다. 이 함수에서 삼각형의 위치값을 변경하고, 변경된 값을 GLSL로 넘긴 후, 화면의 갱신을 수행하게 한다면, Animation 표현이 가능하게 될 것이다. 주의할 점은, Animation 표현을 위해 매 시간마다(이하 매 프레임 마다) 불려져야할 구문들과 단 한번만 불려져도 되는 구문들을 구분해야 한다는 것이다. 매 프레임마다 버퍼를 생성한다거나, Shader Script를 읽기/컴파일/링킹등을 수행하는 것과 같은 불필요한 작업은 반드시 피해야 한다.
(지금부터 변수명을 조금 수정해 보도록하겠다. GLSL에서의 변수명 "aPos"에 대한 핸들을 var vertexPositionAttribute; 로 선언 했었는데, 이를 g_hVertPos로 변경하고, "aColor" 핸들에 대한 변수명을 g_hVertColor로 변경한다. "g_"는 전역에 위치한 변수라는 뜻이고, h는 핸들, 그 다음은 변수 고유의 이름)
앞서 살펴보았던 Vertex Shader코드를 다음과 같이 변경한다.
[code WebGL]
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
uniform vec4 trans;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + trans;
vColor= aColor;
}
</script>
[/code]
위의 코드는 GLSL의 Vertex Shader로 넘어오는 mesh의 각 Vertex의 위치에 trans값을 더해 줌을 볼 수 있다. 따라서 mesh의 모든 Vertex의 위치값에 trans를 더해 줌으로서 mesh의 이동이 수행되는 것이다. 이제, javascript에서 변수명 "trans"의 핸들을 얻을 차례이다. 이 핸들이 있어야만 GLSL에 값을 넘길 수 있기 때문이다.(==Vertex Shader에 값을 넘길 수 있기 때문이다.)
[code WebGL]
//GLSL에서 "trans"라는 변수명의 핸들을 얻음
g_hTrans= gl.getUniformLocation(shaderProgram, "trans");
if( g_hTrans==-1 ){
alert("Unable to find 'trans' Uniform Location.");
return false;
}
[/code]
javascript의 변수명 "g_hTrans"가 GLSL의 "trans"의 핸들이다. "trans"가 uniform으로 선언되어 있으므로, 핸들을 얻는 함수역시 getUniformLocation이다. 이제 g_hTrans을 이용하여, GLSL에 값을 넘길 차례이다.
아래는 g_hTrans핸들을 통해 GLSL에 값을 전달하는 함수이다.
[code WebGL]
gl.uniform4f(g_hTrans, 0.5, 0, 0, 0);
[/code]
g_hTrans핸들은 GLSL에서의 uniform vec4 trans;를 참조하고 있으므로, 값을 넘길 때 uniform4f를 사용해야 한다. 여기까지 수행 하면 앞서 보였던 결과와 같은 결과를 얻을 수 있다.
소소코드는 아래와 같다.
[code WebGL]
<html>
<head>
<title>WebGL - Prac06 - Animation</title>
<script type="text/javascript">
var gl;
var g_hVertPos;
var g_hVertColor;
var g_hTrans;
function start(){
if( !initWebGL() ){
return;
}
if( !initShader() ){
return;
}
var verAry= [
0.0, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 1.0, 0.0
];
var colorAry= [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
var glBufVert= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verAry), gl.STATIC_DRAW);
var glBufColor= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorAry), gl.STATIC_DRAW);
gl.clearColor(0.4, 0.5, 0.6, 1.0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.vertexAttribPointer(g_hVertPos, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.vertexAttribPointer(g_hVertColor, 4, gl.FLOAT, false, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//x좌표 값을 변경 시킨 후 GLSL에 넘긴다.
gl.uniform4f(g_hTrans, 0.5, 0, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function initWebGL(){
var canvas= document.getElementById("WebGL-Canvas");
if( !canvas ){
alert("Can't find WebGL-Canvas.");
return false;
}
try{
gl= canvas.getContext("experimental-webgl");
}catch(e){
}
if( !gl ){
alert("Unable to initialize WebGL. Your browser may not support it.");
return false;
}
return true;
}
function initShader(){
var vertexShaderDesc= getShader("VertexShader");
var vertexShader= gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderDesc);
gl.compileShader(vertexShader);
if( !gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) ){
alert("Error(VertexShader): " + gl.getShaderInfoLog(vertexShader));
return false;
}
var fragmentShaderDesc= getShader("FragmentShader");
var fragmentShader= gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderDesc);
gl.compileShader(fragmentShader);
if( !gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) ){
alert("Error(FragmentShader): " + gl.getShaderInfoLog(fragmentShader));
return false;
}
var shaderProgram= gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) ){
alert("Unagle to initialize the shader program.");
return false;
}
gl.useProgram(shaderProgram);
g_hVertPos= gl.getAttribLocation(shaderProgram, "aPos");
if( g_hVertPos==-1 ){
alert("Unable to find Vertex Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertPos);
g_hVertColor= gl.getAttribLocation(shaderProgram, "aColor");
if( g_hVertColor==-1 ){
alert("Unable to find Vertex Color Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertColor);
//GLSL에서 "trans"라는 변수명의 핸들을 얻음
g_hTrans= gl.getUniformLocation(shaderProgram, "trans");
if( g_hTrans==-1 ){
alert("Unable to find 'trans' Uniform Location.");
return false;
}
return true;
}
function getShader(id){
var shaderScript= document.getElementById(id);
if( !shaderScript ){
alert("Unable to get shader script. id='" + id + "'");
return null;
}
var shaderDesc= "";
var currentChild= shaderScript.firstChild;
while( currentChild ){
if( currentChild.nodeType==3 ){
shaderDesc+= currentChild.textContent;
}
currentChild= currentChild.nextSibling;
}
return shaderDesc;
}
</script>
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
uniform vec4 trans;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + trans;
vColor= aColor;
}
</script>
<script id="FragmentShader" type="x-shader/x-vertex">
precision mediump vec4;
varying vec4 vColor;
void main(){
gl_FragColor= vColor;
}
</script>
</head>
<body onload="start()">
<canvas id="WebGL-Canvas" style="border: 1px solid green" width="400" height="300">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
</body>
</html>
[/code]
이제 javascript의 setInterval(...)함수를 이용하여, 매 프레임을 갱신하고, 삼각형의 위치를 변경시켜 보도록 하겠다. 본 예제에서는 아주 단순히 삼각형의 x좌표의 위치만 변경시켜 보도록 하겠다. 삼각형의 x좌표는 매 프레임 마다 어떤 함수에서 갱신될 것이므로 x좌표에 대한 변수는 전역으로 선언해 두고 값을 갱신해 나가야 할 것이다.
소스코드는 아래와 같다.
[code WebGL]
<html>
<head>
<title>WebGL - Prac06 - Animation</title>
<script type="text/javascript">
var gl;
var g_hVertPos;
var g_hVertColor;
var g_hTrans;
var g_transPosX=0;
function start(){
if( !initWebGL() ){
return;
}
if( !initShader() ){
return;
}
var verAry= [
0.0, 0.0, 0.0,
0.5, 0.0, 0.0,
0.0, 1.0, 0.0
];
var colorAry= [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
var glBufVert= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verAry), gl.STATIC_DRAW);
var glBufColor= gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorAry), gl.STATIC_DRAW);
gl.clearColor(0.4, 0.5, 0.6, 1.0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufVert);
gl.vertexAttribPointer(g_hVertPos, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, glBufColor);
gl.vertexAttribPointer(g_hVertColor, 4, gl.FLOAT, false, 0, 0);
//0.05초 마다 drawScene 호출
setInterval(drawScene, 50);
}
function drawScene(){
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
//x좌표 값을 변경 시킨 후 GLSL에 넘긴다.
g_transPosX+= 0.01;
if( g_transPosX>0.5 ) g_transPosX= 0;
gl.uniform4f(g_hTrans, g_transPosX, 0, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
}
function initWebGL(){
var canvas= document.getElementById("WebGL-Canvas");
if( !canvas ){
alert("Can't find WebGL-Canvas.");
return false;
}
try{
gl= canvas.getContext("experimental-webgl");
}catch(e){
}
if( !gl ){
alert("Unable to initialize WebGL. Your browser may not support it.");
return false;
}
return true;
}
function initShader(){
var vertexShaderDesc= getShader("VertexShader");
var vertexShader= gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderDesc);
gl.compileShader(vertexShader);
if( !gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) ){
alert("Error(VertexShader): " + gl.getShaderInfoLog(vertexShader));
return false;
}
var fragmentShaderDesc= getShader("FragmentShader");
var fragmentShader= gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderDesc);
gl.compileShader(fragmentShader);
if( !gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) ){
alert("Error(FragmentShader): " + gl.getShaderInfoLog(fragmentShader));
return false;
}
var shaderProgram= gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if( !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS) ){
alert("Unagle to initialize the shader program.");
return false;
}
gl.useProgram(shaderProgram);
g_hVertPos= gl.getAttribLocation(shaderProgram, "aPos");
if( g_hVertPos==-1 ){
alert("Unable to find Vertex Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertPos);
g_hVertColor= gl.getAttribLocation(shaderProgram, "aColor");
if( g_hVertColor==-1 ){
alert("Unable to find Vertex Color Attribute Location.");
return false;
}
gl.enableVertexAttribArray(g_hVertColor);
//GLSL에서 "trans"라는 변수명의 핸들을 얻음
g_hTrans= gl.getUniformLocation(shaderProgram, "trans");
if( g_hTrans==-1 ){
alert("Unable to find 'trans' Uniform Location.");
return false;
}
return true;
}
function getShader(id){
var shaderScript= document.getElementById(id);
if( !shaderScript ){
alert("Unable to get shader script. id='" + id + "'");
return null;
}
var shaderDesc= "";
var currentChild= shaderScript.firstChild;
while( currentChild ){
if( currentChild.nodeType==3 ){
shaderDesc+= currentChild.textContent;
}
currentChild= currentChild.nextSibling;
}
return shaderDesc;
}
</script>
<script id="VertexShader" type="x-shader/x-vertex">
attribute vec3 aPos;
attribute vec4 aColor;
uniform vec4 trans;
varying vec4 vColor;
void main(){
gl_Position= vec4(aPos, 1.0) + trans;
vColor= aColor;
}
</script>
<script id="FragmentShader" type="x-shader/x-vertex">
precision mediump vec4;
varying vec4 vColor;
void main(){
gl_FragColor= vColor;
}
</script>
</head>
<body onload="start()">
<canvas id="WebGL-Canvas" style="border: 1px solid green" width="400" height="300">
Your browser doesn't appear to support the HTML5 <code><canvas></code> element.
</canvas>
</body>
</html>
[/code]
'Computer > WebGL' 카테고리의 다른 글
009. WebGL - Prac08 - Texture (0) | 2010.04.10 |
---|---|
008. WebGL - Prac07 - JavaScript 파일 (0) | 2010.04.07 |
006. WebGL - Prac05 - DrawTriangleWithColor (0) | 2010.04.06 |
005. WebGL - Prac04 - Shader를 위한 Script 구문 (0) | 2010.04.06 |
004. WebGL - Prac03 - DrawPoints, DrawLines, DrawTriangles. (0) | 2010.04.05 |