WebGL Lesson 1 – A triangle and a square 에 대한 자습서 이고, 너무 길어서 나누어 올린다.

Lesson 2부터는 상당히 짧아질 것 같다. NeHe의 Article을 참고 하고 있다. Lesson 1의 소스는 GitHub에 있고, 라이브 데모는 여기. 나도 개 고생중이지만, 일반 웹개발자에게 webgl은 쉽지 않다. webgl이 어려운게 아니라 3D가 어렵다.(생소하다.)

getShader() and initShader()

이전 포스트에도 주저리주저리 설명했었는데, shader생성과정은 다음과 같다. WebGL에서 사용하는 용어는 일부러 영어로 적었다. (결과는 조사만 한글..) shaders는 vertex shader, fragment shader 모두를 말한다.

1.Shaders create -> 2. Shaders source로 GLSL string를 load -> 3. Shaders compile -> 4. Program Create -> 5. Program 에 shaders를 attach -> 6. Program안에서 vertex shader와 fragment shader를 link -> 7. Program을 use.

이 과정은 3D를 그리기 위해 거쳐야 하는 프로세스이다. 1~3 가지의 작업이 getShader()에서 일어나고, 4~7까지의 작업이 initShader()에서 일어나며, 정해진 프로세스이므로 함수로 정의하고 사용하면 된다.

getShader()

function getShader(gl, id) {
    //script 로 정의된 shader-fs, shader-vs를 가져오기.
    var shaderScript = document.getElementById(id);
    if (!shaderScript) {
        return null;
    }

    var str = "";
    var k = shaderScript.firstChild;
    while (k) {
        if (k.nodeType == 3) {
            str += k.textContent;
        }
        k = k.nextSibling;
    }

    //분기를 두어 fragment shader와 vertex shader중 생성. 
    var shader;
    if (shaderScript.type == "x-shader/x-fragment") {
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (shaderScript.type == "x-shader/x-vertex") {
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }
    //shader source로 GLSL String을 지정. 
    gl.shaderSource(shader, str);
    //compile.
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}

getShader() 함수이다. 이해에 도움이 되도록 주석을 달았다. gl.xxxx형태의 메소드들이 생소해서 그렇지 쉽게 이해될 수 있는 javascript코드이다. DOM id로 element를 가져와서 innerHTML내용(여기선 node fh c)을 string화 하고, gl.createShader()로 생성한 객체(shader)안에 GLSL을 넣고 컴파일 한다. 그러면 가용가능한 shader를 반환한다.

initShader()

var shaderProgram;

function initShaders() {
    //shader 생성
    var fragmentShader = getShader(gl, "shader-fs");
    var vertexShader = getShader(gl, "shader-vs");
    //program에 shader attach, link, use
    shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert("Could not initialise shaders");
    }

    gl.useProgram(shaderProgram);
    //attributes, Uniform Location가져오기.
    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

    shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
}

initShaders()이다. 이 함수의 목표는 shaderProgram이란 전역변수를 만드는 것이다. 위에서 설명했듯이 shader는 program이란 개체 안에 attache되고, link되고 use되어야 한다. (주석 찹조) gl.useProgram()까지 실행되면, shader를 사용할 준비가 끝났다. 이제 사용하면 되는데... 잠시 정리를 해보자.

여태까지 우리는 canvas.getContext()를 통해 webgl객체인 gl를 만들고, shader를 만들고 program를 만들었다. 하지만 fragment GLSL의 gl_Color를 제외하곤 구체적인 도형을 정의하지 않았다. 도형을 그리기 위한 프로그램을 만든것이다. (데이터가 아닌)

이제 (shader가 들어있는) program을 이용하여 도형데이터를 행열(Matrix)와 벡터(vector) 로 shader에 넣어주면 된다. 예를 들어 아래처럼?

gl.setSaderDateInProgram(vertexs, uniform);

GLSL에서 정의한 attribute와 uniform에 값을 넣어주면 되는데, 좀 생소하지만 WebGL은 위와 같은 메소드, 방법은 제공하지 않는다. attribute와 uniform의 위치값(location)알아야 값을 넘길 수 있다. (포인터로 이해해야 쉬우려나..) initShaders() 함수의 끝의 네줄은 바로 그 location을 가져오는 부분이다.

attritube 와 uniform은 Location을 가져오는 법이 다르다.

gl.getAttribLocation()는 shaderProgram에 attach된 vertexShader 에서 attribute의 정수형 index값을 가져오지만, gl.getUniformLocation()는 WebGLUniformLocation 객체를 가져온다. 게다가 attribute의 경우 gl.enableVertexAttribArray()를 이용해 해당 attribute를 enable해주어야만 사용가능하다.

자, 그럼 이제 그림을 그리기위한 프로그램 준비가 끝났다. 이제 무얼 그릴건지 그릴 데이터를 만들자. initBuffers();

Reference link

http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/loading.php

2011/04/24 14:12 2011/04/24 14:12
Trackback address :: http://zziuni.pe.kr/zziuni/trackback/564

Comments List

Write a comment.

[로그인][오픈아이디란?]