본문 바로가기
Computer/WebGL

016. WebGL – GWTGL – TextResource를 이용한 GLSL

by DogBull 2011. 6. 13.
  이전 예제들에서는 GLSL코드를 *.java 파일 내부에 String형식으로 작성하였었다. 이는 java코드와 GLSL코드가 한 곳에 섞여 있으므로, 수정 및 디버깅에 불편함을 초래한다.
(아래와 같이...)
String vsSource=
	"attribute vec2 vertPos;" +
	"void main(){" +
	"   gl_Position=    vec4(vertPos, 0.0, 1.0);" +
	"}";

String fsSource=
	"void main(){" +
	"   gl_FragColor=   vec4(1.0, 1.0, 1.0, 1.0);" +
	"}";

gl.shaderSource(vs, vsSource);  
gl.shaderSource(fs, fsSource);


  보통 CPU코드(java코드)와 GPU코드(GLSL코드)를 분리하여, GLSL코드를 텍스트 형식의 리소스 파일로 두는 것이 일반적(?)일 것이다. 이를 구현하기 위해 텍스트 파일을 런타임에 FileStream을 이용하여 읽어들일 수도 있지만, GWT에서 제공하는 com.google.gwt.resources.client.ClientBundle라는 클래스를 활용하는 것이 여러 모로 편리하다. 

 
위 그림과 같이 java코드(GWTGL_Prac05_ColorRect.java)와 GLSL코드(vs.txt, fs.txt)가 서로 분리되어 있음을 볼 수 있다. 편리한 점은 서로 분리된 두 코드가 컴파일 타임에 하나로 합쳐진다는 것이다.
  소스코드에서 독립된 파일로 존재하던 버텍스셰이더(vs.txt)와 플래그먼트셰이더(fs.txt)가 GWT 컴파일 완료 후에는 javascript내부에 포함된다. 아래는 컴파일후 생성된 javascript 파일의 코드를 보여주고 있으며, GLSL코드가 문자열 형식으로 포함되어 있음을 볼 수 있다.

<GWT 컴파일 후 javascript 내부에 포함된 셰이더 코드>

따라서 GWT 컴파일 후 셰이더 코드를 관리해야하는 불편함이 없다.

이를 구현하기 위해서는 아래와 같이 java1.5 버전부터 지원되는 어노테이션(Annotation)을 이용하게 된다.(어노테이션에 대한 설명은 [여기]를 참조)

package jrr.gwtgl.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.TextResource;

public interface JrrResource extends ClientBundle{
	
	public static JrrResource INSTANCE= GWT.create(JrrResource.class);
	
	@Source(value={"vs.txt"})
	TextResource vertexShader();
	
	@Source(value={"fs.txt"})
	TextResource fragmentShader();
}
  com.google.gwt.client.ClientBundle 클래스를 상속받으면, @Source라는 Annotation을 사용할 수 있다. 따라서 vs.txt파일의 내용은
String str=JrrResource.INSTANCE.vertexShader().getText();

와 같은 방법으로 얻을 수 있다.

Color Rect 그리기 [예제]

attribute vec2 aVert;
attribute vec4 aColor;

varying vec4 vColor;

void main(){
	vColor=	aColor;
	gl_Position=	vec4(aVert, 0.0, 1.0);
}
버텍스 셰이더 코드(vs.txt)
attribute로 버텍스의 위치를 나타내는 aVert변수와 버텍스의 생상을 나타내는 aColor변수가 설정되어 있고, 플래그먼트셰이더에 vColor변수를 통해 버텍스 색상을 넘겨준다.

precision mediump float;

varying vec4 vColor;

void main(){
	gl_FragColor=	vColor;
}
플래그먼트 셰이더 코드(fs.txt)
단순히 버텍스 셰이터로 부터 넘겨 받은 vColor을 이용하여 색상 출력.

 
package jrr.gwtgl.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.googlecode.gwtgl.array.Float32Array;
import com.googlecode.gwtgl.binding.*;

public class GWTGL_Prac05_ColorRect implements EntryPoint{

	@Override
	public void onModuleLoad() {
		final WebGLCanvas canvas=	new WebGLCanvas("400px", "300px");
		this.gl=	canvas.getGlContext();
		
		RootPanel.get("gwtGL").add(canvas);
		
		gl.viewport(0, 0, 400, 300);
		gl.clearColor(0.6f, 0.7f, 0.8f, 1.0f);
		
		this.vb=		initVertexBuffer();
		this.program=	initProgram();
		this.aVertPos=	gl.getAttribLocation(program, "aVert");
		this.aColor=	gl.getAttribLocation(program, "aColor");
		
		gl.clear(gl.COLOR_BUFFER_BIT);
		
		gl.useProgram(program);
		gl.enableVertexAttribArray(aVertPos);
		gl.enableVertexAttribArray(aColor);
		gl.bindBuffer(gl.ARRAY_BUFFER, vb);
		gl.vertexAttribPointer(aVertPos, 2, gl.FLOAT, false, 24, 0);
		gl.vertexAttribPointer(aColor, 4, gl.FLOAT, false, 24, 8);
		gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
		gl.disableVertexAttribArray(aVertPos);
		gl.disableVertexAttribArray(aColor);
	}
	
	private WebGLBuffer initVertexBuffer(){
		float[] verts={
				//버텍스 위치		//버텍스 색상
				-0.5f, -0.5f,		1.0f, 0.0f, 0.0f, 1.0f,
				 0.5f, -0.5f,		0.0f, 1.0f, 0.0f, 1.0f,
				-0.5f,  0.5f,		0.0f, 0.0f, 1.0f, 1.0f,
				 0.5f,  0.5f,		1.0f, 1.0f, 1.0f, 1.0f
		};
		Float32Array fAry=	Float32Array.create(verts);
		
		WebGLBuffer vb=	gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, vb);
		gl.bufferData(gl.ARRAY_BUFFER, fAry, gl.STATIC_DRAW);
		gl.bindBuffer(gl.ARRAY_BUFFER, null);
		
		return vb;
	}
	
	private WebGLProgram initProgram(){
		WebGLShader vs=	gl.createShader(gl.VERTEX_SHADER);
		WebGLShader fs=	gl.createShader(gl.FRAGMENT_SHADER);
		gl.shaderSource(vs, JrrResource.INSTANCE.vertexShader().getText());
		gl.shaderSource(fs, JrrResource.INSTANCE.fragmentShader().getText());
		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) );
		}
		
		WebGLProgram program=	gl.createProgram();
		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);
		
		return program;
	}
	
	private WebGLRenderingContext	gl;
	private WebGLBuffer				vb;
	private WebGLProgram			program;
	private int						aVertPos;
	private int						aColor;
}
39라인의 verts 배열에는 "버텍스의위치"와 "버텍스의색상"이 순서대로 들어간다.
따라서 31, 32라인에서와 같이 렌더링시 stride 값을 24(버텍스위치8바이트, 버텍스색상16바이트)로 설정한다.
또한, 32라인과 같이 버텍스색상은 버텍스위치값 때문에 8바이트 뒤에서 부터 시작하므로 offset값을 8로 설정해야 한다. 


'Computer > WebGL' 카테고리의 다른 글

015. WebGL – GWTGL – Simple Animation  (0) 2011.06.10
014. WebGL – GWTGL – White Triangle  (0) 2011.06.09
013. WebGL - GWTGL - GWTGL 기본  (0) 2011.05.25
012. WebGL - GWTGL - GWT 기본  (0) 2011.05.25
011. WebGL - GwtGL - About GwtGL  (0) 2011.05.11