Javascript를 사용한 WebGL에서 Animation 구현을 위해 javascript의 setInterval이라는 함수를 사용하였다.예제 그와 비슷하게, GWTGL에서는 com.google.gwt.user.cllient.Timer라는 클래스를 사용하였다. Multi-Thread환경을 GWT에서 지원하지 않는다고 하니, Timer와 같은 스케줄러를 사용해야 할 것이다.
간단하게 에니메이션은 연속적으로 변화하는 매 프레임을 갱신하는 것이라고 하면 아래와 같은 방법으로 간단한 에니메이션을 테스트해 볼 수 있다.
코드 85
라인에서 com.google.gwt.user.client.Timer 클래스의 인스턴스를 생성하고,
104
라인에서 Timer::scheduleRepeating(50); 함수를 이용하여 50ms마다 한번씩 88
라인의 run 함수를 호출해 준다.
아래의 코드는 작은 흰색 삼각형이 화면의 정 중앙을 중심으로 빙글빙글 돌아가는 예제이다. (50ms 당 0.1Radian 즉, 1초에 2Radian 정도 회전)
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package jrr.gwtgl.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.RootPanel;
import com.googlecode.gwtgl.array.Float32Array;
import com.googlecode.gwtgl.binding.*;
@SuppressWarnings("static-access")
public class GWTGL_Prac04_Animation implements EntryPoint{
@Override
public void onModuleLoad() {
final WebGLCanvas canvas= new WebGLCanvas("400px", "300px");
RootPanel.get("gwtGL").add(canvas);
this.gl= canvas.getGlContext();
//#0. 기본 설정
gl.viewport(0, 0, 400, 300);
gl.clearColor(0.6f, 0.7f, 0.8f, 1.0f);
//#1. 버텍스 버퍼 생성.
this.vertBuf= gl.createBuffer();
{
float[] vertAry= {
0.0f, 0.0f,
0.3f, 0.0f,
0.0f, 0.3f
};
Float32Array fAry= Float32Array.create(vertAry);
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.bufferData(gl.ARRAY_BUFFER, fAry, gl.STATIC_DRAW);
}
//#2. 프로그램(GLSL) 작성.
this.program= gl.createProgram();
{
String vsSource=
"attribute vec2 vertPos;" +
"uniform float fRot;" +
"void main(){" +
" float c= cos(fRot);" +
" float s= sin(fRot);" +
" vec2 vPos;" +
" vPos.x= vertPos.x* c + vertPos.y*s;" +
" vPos.y= vertPos.x*-s + vertPos.y*c;" +
" gl_Position= vec4(vPos, 0.0, 1.0);"+
"}";
String fsSource=
"void main(){" +
" gl_FragColor= vec4(1.0, 1.0, 1.0, 1.0);" +
"}";
WebGLShader vs= gl.createShader(gl.VERTEX_SHADER);
WebGLShader fs= gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vs, vsSource);
gl.shaderSource(fs, fsSource);
gl.compileShader(vs);
gl.compileShader(fs);
if( !gl.getShaderParameterb(vs, gl.COMPILE_STATUS) ){
System.out.println(gl.getShaderInfoLog(vs));
}
if( !gl.getShaderParameterb(fs, gl.COMPILE_STATUS) ){
System.out.println(gl.getShaderInfoLog(fs));
}
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if( !gl.getProgramParameterb(program, gl.LINK_STATUS) ){
System.out.println(gl.getProgramInfoLog(program));
}
gl.deleteShader(vs);
gl.deleteShader(fs);
}
gl.useProgram(program);
this.aVertPos= gl.getAttribLocation(program, "vertPos");
this.uRot= gl.getUniformLocation(program, "fRot");
fRot= 0.0f;
Timer timer= new Timer() {
@Override
public void run() {
//#3. 렌더링 루프
gl.clear(gl.COLOR_BUFFER_BIT);
fRot+=0.1;
gl.uniform1f(uRot, fRot);
gl.enableVertexAttribArray(aVertPos);
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 3);
gl.disableVertexAttribArray(aVertPos);
}
};
timer.scheduleRepeating(50);
}
private WebGLRenderingContext gl;
private WebGLProgram program;
private WebGLBuffer vertBuf;
private int aVertPos;
private WebGLUniformLocation uRot;
private float fRot;
}