본문 바로가기
Computer/WebGL

015. WebGL – GWTGL – Simple Animation

by DogBull 2011. 6. 10.

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 정도 회전)

예제는 [여기]에서 확인 가능.

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;				
}