webgl教程韩语版(第一课)

来源:互联网 发布:算法基础pdf 编辑:程序博客网 时间:2024/04/29 19:48

번째 WebGL 레슨에 오신것을 환영합니다. 학습은 게임 개발자를 위한 3D 그래픽 학습 수단으로 인기가 높은 NeHe OpenGL 번째 튜토리얼 바탕으로 하고 있습니다. 고작 삼각형과 사각형이라니, 어찌보면 흥미가 떨어질만한 주제일지도 모르겠지만, 단원은 WebGL 배우는 기초의 중요한 도입부입니다. 레슨을 이해할 있다면 나머지 레슨 역시 쉽게 배울 것입니다.


static.png


WebGL 지원하는 브라우저를 사용중이라면 여기를 클릭하여 실재 WebGL 버전 확인할 있습니다. 지원하는 브라우저에 대한 정보는 레슨 0 참고하세요.

지금부터 작동방법에 대하여 알아봅시다.


시작에 앞서...

레슨은 충분한 자바스크립트 프로그래밍 지식이 있지만, 3D 그래픽 구현 경험이 없는 사람들을 대상으로 하고 있습니다. 그리고 가능한 빨리 자신만의 3D 구사하여 결과물을 만들수 있도록 하는 것에 목적을 둡니다. 레슨에 사용된 예제에서 실재 구현된 코드를 분석하여 어떤 일이 일어나는지 알아보고 그것을 이해하여 스스로 응용할 있도록 하는 것입니다.

저는 레슨을 스스로 학습하면서 작성했습니다. 그래서 분명히 효율적이지 못합니다. 효율적이지 못한 부분을 알아차렸다면 당신의 자산으로 삼아 이용하세요. 그리고 만약 뭔가 실수를 발견했다면 댓글을 통해 알려주세요. 즉시 수정 반영하도록 하겠습니다.

여기에 사용된 예제의 소스코드를 얻는 방법은 두가지가 있습니다실제 예제가 작동하는 에서 "소스 보기" 선택하거나, GitHub 사용할 있다면 저장소에서 동일한 예제를 다운로드할 있습니다.(앞으로 학습할 예제들도 포함되어 있습니다.) 추천하는 방법은 번째로, 저장소에서 모두 가져온 다음 즐겨쓰는텍스트 편집기에서 열어두고 학습하는 것입니다. 단원은 OpenGL 대한 지식이 있다해도 도입부 부터 두개의 쉐이더를 정의해 버리기 때문에 어리둥절 수도 있습니다. 쉐이더는 일반적으로 고도의 기술로 여겨지고 있지만, 좌절하지 마세요. 사실 생각보다 훨씬 쉽습니다.

다른 많은 프로그램과 마찬가지로 WebGL 예제는 저수준 함수를 정의하는 것으로부터 시작됩니다. 그리고 아래쪽에있는 코드에서 고수준 함수를 호출합니다. 그래서 이를 설명하기 위해 프로그램에 대한 설명은 아래에서 위로 진행합니다. 만약 지금 소스 코드를 보고 있다면 제일 아래로 건너뛰세요.


HTML 마크업

다음과 같은 HTML코드가 보입니다.

<body onload="webGLStart();">

  <a href="http://learningwebgl.com/blog/?p=28">&lt;&lt;Back to Lesson 1</a><br />

 

  <canvas id="lesson01-canvas" style="border:none;" width="500" height="500"></canvas>

 

  <br/>

  <a href="http://learningwebgl.com/blog/?p=28">&lt;&lt;Back to Lesson 1</a><br />

</body>

이것은 페이지의 body 속한 부분입니다. 다른 모든 것은 자바스크립트 속에 있습니다. (만약 "소스 보기" 코드를 보고있다면사이트 접속 분석에 이용하는 추가 코드가 보입니다만 무시해도 됩니다.)

물론 <body>안에는 더욱 다양한 HTML태그를 추가하여 WebGL 이미지를 있습니다. 그러나 간단한 데모는 블로그로 이동하는 링크와 WebGL 만든 3D 그래픽을 표시하는 <canvas>태그가 있을 뿐입니다.

Canvas 요소는 HTML5에서 새롭게 추가되었습다. 이것은 웹페이지에 2D WebGL 통한 3D 자바스크립트 사용하여 렌더링하는 새로운 수단입니다. 아래 코드는 <canvas>요소의 레이아웃을 조정하는 간단한 속성만을 사용합니다. webGLStart라는 자바스크립트 함수에 선언되어 있으며 페이지가 로드될 번만 실행하도록 구성되었습니다.


WebGL 초기화 - webGLStart

이제 스크롤바를 조금 위로 올려 webGLStart() 함수를 보도록 합니다.

  function webGLStart() {

    var canvas = document.getElementById("lesson01-canvas");

    initGL(canvas);

    initShaders();

    initBuffers();

 

    gl.clearColor(0.0, 0.0, 0.0, 1.0);

    gl.enable(gl.DEPTH_TEST);

 

    drawScene();

  }


이러한 함수 호출을 보통 "초기화 한다."라고 합니다. 함수는 WebGL 3D 렌더링의 대상이 되는canvas요소를 전달하고 앞서 언급한 쉐이더를 초기화 합니다. 또한 initBuffers 함수를 호출하여 특정 버퍼(Buffer) 초기화도 실행합니다. 여기에서의 버퍼는 지금부터 그려야 삼각형과 사각형에 대한 정보를 유지하는 사용됩니다. 다음은 initGL 의하여 만들어진 엔진인 gl객체에서 배경색상을 검게하는 메서드와 depth test 위한 값을 기입하여 WebGL 사용할 기본 설정을 구성합니다. 마지막에 호출한 drawScene 함수는 setInterval 이용하여 0.015 간격으로 화면을 갱신하게 됩니다. 함수는 버퍼를 사용하여 개체를 그립니다.

WebGL 어떻게 작동하는지 이해하기 위해서는 initGL initShaders 함수가 매우 중요한 역할을 하지만 이들 함수는 나중에 자세히 다루도록 하고 initBuffers drawScene 먼저 살펴보도록 합니다.


  vartriangleVertexPositionBuffer;

  varsquareVertexPositionBuffer;

우선, 버퍼를 저장하기 위한 두개의 전역 변수 정의합니다.(실제 WebGL 구현할 마다 전역 변수 사용해야 하는 것은 아닙니다. 레슨에서는 코드를 단순화하기 위해 사용했습니다.)


버퍼설정 - initBuffers

  function initBuffers() {

    triangleVertexPositionBuffer = gl.createBuffer();

삼각형의 버텍(Vertex, 꼭지점 혹은 정점) 좌표를 기록하기 위해 미리 만들어 두었던 전역 변수 버퍼를 생성하여 할당합니다. 여기에서 꼭지점은 그리려고 하는 도형이 가상 공간에서 위치하게 좌표정보입니다. 삼각형은 3개의 꼭지점을 갖는 것입니다. 버퍼는 사실 그래픽 카드 메모리입니다. 꼭지점 좌표들을 초기화하는 동안 그래픽 카드 버퍼에 담긴 정보로 다시 그려내기 때문에 프로그램을 매우 효율적으로 작성할 있습니다. 물론 이번 레슨에는 3개의 버텍스만을 보내고 있기 때문에 그래픽 카드 전송하는 비용은 거의 들지 않습니다만, 거대한 모델을 취급하게 되는 상황에서 방법은 엄청난 장점이 있습니다.


   gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);

라인은 WebGL에게 행동중인 버퍼에 대한 작업은 모두 인수로 지정된 버퍼에 의해 실행하도록 알려주는 것입니다. 작업에서 대상의 버퍼를 지정하는 것이 아니라, 미리 "currentarray buffer" 지정하고 거기에 대한 작업을 수행한다는 개념은 항상 따라다닙니다. 이상하지요? 이렇게 하는 것은 성능상의 이유가 숨어있습니다.


    var vertices = [

         0.0,  1.0,  0.0,

        -1.0, -1.0,  0.0,

         1.0, -1.0,  0.0

    ];

코드는 자바스크립트 배열로 버텍스 좌표를 정의한 것입니다. 좌표를 자세히 보면 중심이 (0,0,0) 이등변 삼각형인 것을 유추할 있습니다.


  gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertices),gl.STATIC_DRAW);

이번에는 앞서 작성한 자바스크립트 배열을 바탕으로 Float32Array 객체를 만들고 "CurrentBuffer" 값을 설정하여 WebGL에게 알려줍니다. 물론 "CurrentBuffer" triangleVertexPositionBuffer입니다. Float32Array 대해서는 향후 레슨에서 다루도록 하겠습니다. 일단 지금 알아 두어야 것은, 방법으로자바스크립트 배열을 WebGL에서 사용할 있는 버퍼의 형태인 Float32Array 변경하여 넘겨줄 있다는 것입니다.


    triangleVertexPositionBuffer.itemSize = 3;

    triangleVertexPositionBuffer.numItems = 3;

버퍼의 마지막 작업은 두개의 새로운 속성을 추가하는 것입니다. 이것은 WebGL 내장된 기능을 수행하지는 않습니다만 나중에 아주 유용하게 사용됩니다자바스크립트 좋은 점은(나쁜 점이라고 하기도 하지만) 객체별 속성을 설정하기 위하여, 명시적으로 선언하는 것을 필요로하지 않다는 것입니다. 원래 버퍼객체는 itemSize numItems속성을 가지고 있지 않지만, 이제는 위와 같은 속성들을 가지게 되었습니다. 버퍼 속성으로 9개의 값으로 부터 분리된 3개의 버텍스 좌표정보(numItems) 있고 각각은 3개의 숫자(itemSize)값으로 구성되었다는 것을 나타낼 있습니다.

삼각형을 위한 버퍼의 설치가 끝났으니, 다음은 사각형입니다.

    squareVertexPositionBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ARRAY_BUFFER,squareVertexPositionBuffer);

    vertices = [

         1.0,  1.0,  0.0,

        -1.0,  1.0,  0.0,

         1.0, -1.0,  0.0,

        -1.0, -1.0,  0.0

    ];

    gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertices),gl.STATIC_DRAW);

    squareVertexPositionBuffer.itemSize = 3;

    squareVertexPositionBuffer.numItems = 4;

  }

모든 것들은 분명해야 합니다. 사각형은 4개의 버텍스를 가지므로 삼각형 보다 numItems값을 가지고 있습니다.

좋아요, 이것으로 두개의 도형이 가진 버텍스 정보를 그래픽 카드 보낼 수있게 되었습니다. 지금부터 만들어진 버퍼를 이용하여 실제로 도형들을 그리기 위한 함수인 drawScene 차근차근 살펴보도록 하겠습니다.


장면 그리기 - drawScene

  function drawScene() {

    gl.viewport(0, 0,gl.viewportWidth, gl.viewportHeight);

번째 단계는 viewport 함수를 사용하여 WebGL canvas 크기를 알려주는 것입니다. 작업이 중요 한지에 대해서는 한참 이후의 단원에서 다루게 됩니다. 지금 최소한 기억해야 것은 실재로 도형을 그리기 전에 canvas 크기를 정하는 함수를 호출하는 것입니다. 다음 코드는 다음 장면이 그려질 것을 대비하여 canvas 내용을 지우는 것입니다.

    gl.clear(gl.COLOR_BUFFER_BIT| gl.DEPTH_BUFFER_BIT);


... 그리고

    mat4.perspective(45,gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);

여기에 장면을 어떻게 보일지에 대한 설정을 위해 퍼스펙티브(perspective, "원근법") 설정합니다. 기본적으로 WebGL 가까운 것과 것을 같은 크기로 그립니다.(3D 용어, orthographicprojection - "직각 투영"이라고 합니다.) 그래서 것이 작게 보이도록하는 WebGL 퍼스펙티브에 대한 설정이 약간 필요합니다. 여기서는 장면(수직시야각으로 45, canvas 너비와 높이 비율 시점에 가까이 가면 숨기는 거리로 0.1, 이상 멀어지면 숨기라는 거리로 100 설정합니다.

위에서 있듯이, perspective 함수는 mat4라는 함수 모듈을 이용하여 호출합니다.  함수 모듈은 매우 유용하지만 WebGL 기본으로 포함되어 있지 않기 때문에 유틸리티 함수를 이용하여 정의하고 있습니다. 함수의 작동에 대한 자세한 설명은 나중에 다루겠지만, 세세한 것을 몰라도 손쉽게 사용할 있습니다

퍼스펙티브 설정이 끝났으니 이제 출력하는 코드를 만들 있습니다.

    mat4.identity(mvMatrix);


번째 단계는 3D 장면의 중심으로 이동하는 것입니다. OpenGL 장면을 그릴 대상 물체마다 현재(Current) 위치와 회전값을 전달합니다. - 예를 들어, "20 만큼 전진하고 32 만큼 회전하여 로봇 그려"라는 식으로 말이죠. 실제로 복잡한 부분은 "요만큼 움직였고 이만큼 회전하여 그렸다"라는 지침이 있습니다. 이것은 "로봇 그려라"라는 코드 한개의 함수로 캡슐화 있으므로 매우 편리합니다. 그리고함수 호출 전에 이동 회전값을 변경함으로써 마음데로 로봇 이동시킬 있습니다

현재 위치와 회전은 매트릭스(Matrix, 행렬) 유지되고 있습니다. 당신이 과거 학교에서 배운대로 매트릭스 이동(어디에서 어디로 이동하는지), 회전 혹은 다른 기하학적인 변형을 나타낼 있습니다. 자세한 내용으로 접근할 없지만, 4x4 행렬(3x3 아닌) 한개로 3D 공간 사이의 어떤 변형을 나타낼 있습니다. 처음에는 identitymatrix(단위 행렬)부터 시작합니다 - identitymatrix 아무런 변화가 없는 행렬입니다. 여기에 번째 전이를 나타내는 매트릭스를 겁니다. 그리고 번째 변형을 나타내는 매트릭스를 곱하면 됩니다. 합성된 매트릭스 한개로 전체의 변형을 나타냅니다. 현재 이동과 회전을 나타내는데 사용되는 매트릭스를 model-viewmatrix라고 합니다. 아마도 이미 깨닫고 있다고 생각 합니다만, mat4.identity 함수는 앞으로 model-viewmatrix 이동과 회전을 곱할 준비를 위해 identity matrix 설정합니다. , 3D 표현하기 위해 움직일 있는 위치에서 원점으로 돌아 왔다고 말할 있습니다.

주의 깊은 어떤 독자는 매트릭스 이야기의 시작 부분에 "WebGL" 아니라"OpenGL"이라고 알려주었습니다. 이것은mat4.perspective 함수처럼 매트릭스 처리를 위한 WebGL 내장 함수가 아니기 때문입니다. 대신, 스스로 구현 하거나, 이미 존재하는 서드-파티 매트릭스 라이브러리 사용해야 합니다. - Brandon Jones씨의 glMatrix 같은유틸리티 함수의 기능에 대한 자세한 내용은 나중에 설명 하겠지만, 다행히도 자세한 내용을 몰라도 사용하는데에 지장이 없다는 것입니다.

, 이제 canvas왼쪽 삼각형을 그리는 부분의 코드를 살펴봅시다.

    mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);

mat4.identity 함수에 의해 3D 공간의 중심으로 이동했기 때문에, 좌측 1.5(X 축을 따라 마이너스 방향) 안쪽에는 7(보고있는 사람으로부터 멀어질 Z축을 따라 마이너스 방향)(mat4.translate 예상 했을지도 모르지만, 이것은 지정한 매개 변수 따라 이동을 위한 매트릭스를 model-view matrix 거는 낮은 수준의 이동을 위한 기능입니다.) 

다음 단계에서는 실제로 렌더링을 시작합니다.

    gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);

    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);


앞서 선언한 버퍼들 하나를 사용하기 위해 gl.bindBuffer 호출해서 current buffer 할당하는 코드를 호출합니다. 여기에triangleVertexPositionBuffer 지정하여 WebGL에게 버텍스 좌표로 사용하는 ​​ 전달합니다. 나중에 어떻게 작동하는지 조금 자세히 설명 하겠지만 지금은 버퍼에 있는 요소가 3개의 숫자로 이루어진 것을 미리 담아 두었던 itemSize 속성을 사용하여 넘겨주고 있다는 사실을 발견할 있습니다.

다음은

    setMatrixUniforms();

이것은 WebGL 현재의 model-viewmatrix(또한 projection matrix 있지만 나중에 알아봅니다) 사용하도록 지시해야 합니다. 그리고 함수는 WebGL 내장 함수로 존재하지 않기 때문에 직접 준비해야 합니다. mvMatrix(model-vew matrix) 변수 변경하여 여러 곳으로 움직이는 것이 가능합니다. 그러나 이것은 전부 자바스크립트 의해서만 이루어지기 때문에 setMatrixUniforms 호출하여 매트릭스를 그래픽 카드 넘겨주는 일을 하게됩니다.

이것이 완료 되면, WebGL 버텍스의 위치를 가진 숫자 배열과 매트릭스를 알아차리게 되고, 다음과정에서 값들을 어떻게 사용하는지 알려줍니다.


    gl.drawArrays(gl.TRIANGLES, 0,triangleVertexPositionBuffer.numItems);

코드를 다른 말로한다면 "앞서 전달된 버텍스 배열로 삼각형을 그리세요. 버텍스는 배열의 0 요소, 그리고 numItems 위치한 요소로 사용하세요

여기까지 끝나면 WebGL 삼각형을 그릴 것입니다. 다음은 사각형을 그려봅시다.

    mat4.translate([3.0, 0.0, 0.0])

model-view matrix 오른쪽으로 3만큼 이동한 곳에서 시작합니다. 기억하세요. 지금은 이미 좌측 1.5, 스크린에서 7.0 안쪽에 위치하기 때문에 결과 오른쪽 1.5, 뒤쪽이 7만큼 떨어진 위치에 있습니다

다음은

    gl.bindBuffer(gl.ARRAY_BUFFER,squareVertexPositionBuffer);

    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

WebGL에게 사각형의 버텍스 버퍼를 알려줍니다.


   setMatrixUniforms();

model-view matrix projectionmatrix 다시 보냅니다.(마지막에서 mvTranslate 결과가 반영되도록) 이제 드디어 마지막 과정입니다.


    gl.drawArrays(gl.TRIANGLE_STRIP,0, squareVertexPositionBuffer.numItems);

그리기를 실행하세요. 여기서 triangle strip 무엇인지 궁금하시죠? 그래요, 이것은 삼각형의 연속들입니다. 처음 3개의 버텍스를 지정하여 삼각형을 그리고 다음 마지막으로 이용한 2개의 버텍스에 새로운 1개의 버텍스를 추가하고 다음의 삼각형을 그리고 하나를 추가하는 일을 계속합니다. 이것은 사각형을 지정하는 빠르고 간편한 길이지만 그리 좋은 방식은 아닙니다만, 복잡한 형상을 여러 삼각형으로 표현하는 매우 편리한 방법이기도 합니다.

어쨌든 여기까지 끝나면 drawScene 함수는 끝입니다.

  }



실험 - Go crazy!

만약 당신이 여기까지 도달했다면 이제 직접 실험할 준비가 확실히 갖추어진 것입니다GitHub 또는 "소스 보기" 통해 얻어낸 파일을 로컬에 복사하세요. 만약 후자의 방법을 선택한다면 index.html glMatrix-0.9.4.min.js 필요합니다. 직접 브라우저에서 실행하여 제대로 작동하는지 확인하세요. 그리고 어떤 버텍스의 좌표를 변경해 보세요. 지금 장면은 완전히 평평하지만 얻을 사각형의 Z값을 2 또는 3으로 변경해 보세요. 위치가 뒤바뀌기 때문에 커지기도합니다. 한개 또는 두개의 버텍스를 변경하여 외관에 발생하는 왜곡을 살펴보세요. Go crazy, anddon’t mind me. I’ll wait.

...

~ 다시 돌아오셨나요? 이제부터는 지금까지 가지고 놀았던 프로그램을 가능하게 지원했던 함수들을 살펴보도록 합니다. 전에 말했듯이, 만약 세부 사항을 모르고 initBuffers 같은 함수를 그냥 복사해서 쓰는 것에 만족한다면 어쩌면 자세한 부분을 이해하지 않아도 당신은 재미있는 WebGL 페이지를 만들 있을지 모릅니다.(비록 흑백이라도 - 색상은 다음 레슨) 하지만 자세한 내용들에는 이해하기 어려운 것이 없어요. 어떻게 작동하는지에 대하여 이해하는 것은 분명히 나은 WebGL 프로그램을 개발할 있게 되는 것임을 명심하세요.


초기화 함수 - initGL

저와 계속 함께 하시겠어요? 감사합니다. 이제, 가장 지루한 함수를 먼저 끝내 버립시다. 처음에는 webGLStart에서 호출되는 initGL 함수입니다. 코드는 웹페이지 상단에 있습니다

  var gl;

  function initGL(canvas) {

    try {

      gl = canvas.getContext("experimental-webgl");

      gl.viewportWidth = canvas.width;

      gl.viewportHeight = canvas.height;

    } catch(e) {

    }

    if (!gl) {

      alert("Could notinitialise WebGL, sorry :-(");

    }

  }


이것은 아주 간단합니다. 당신도 눈치챘을지 모르지만, initBuffers drawScene으로 불리는 함수는 자주 gl이라는 개체를 참조했었습니다. 이것은 WebGL 중심이되는 무언가의 단순한 참조입니다. 함수는 무언가를 가져옵니다. 무언가는 WebGL 컨텍스트라는 것으로, standardcontext name 사용하여 canvas 부터 해당 컨텍스트를 얻을 있습니다. 컨텍스트가 생기면 자바스크립트 객체에 어떤 property 추가할 있는 멋진 기능을 이용하여 canvas너비와 높이를 저장 둡니다. 값은 drawScene 함수의 시작 부분 뷰포트와 퍼스펙티브를 설정하는 사용할 있습니다. 그렇습니다. gl canvas요소를 통하여 WebGL 사용하기 위한 컨텍스트입니다.


지원 함수 - mat4.create

initGL() 호출한 webGLStart 함수는 initShaders() 호출합니다. 물론 함수는 쉐이더를 초기화 합니다. 코드는 나중에 보기로 하고, 먼저 model-viewmatrix 취급하는 유틸리티 함수들을 살펴봅시다. 아래가 바로 코드입니다.

  var mvMatrix = mat4.create();

  var pMatrix = mat4.create();


model-view matrix 유지하기 위한 mvMatrix라는 변수 정의합니다. mat4.create 의해 만들어진 매트릭스에는 모두 0으로 비어있는 행렬입니다. 당신은 기억할 것입니다. drawScene 함수를 분석하면서 glMatrix 포함된mat4.perspective 함수를 이용하여 변수 할당하여 시점을 설정한 일을 말예요. mat4.perspective 함수는 WebGL 내장 함수가 없기 때문에 사용했었죠. model-viewmatrix 물체의 이동 회전을 캡슐화 있는 것과 마찬가지로 멀리 갔다거나, 물체가 거리에 비례하여 가까이 있을 보다 작아짐을 나타내기에 아주 적합한 매트릭스입니다. 그리고mat4.perspective 당신이 짐작대로 projection matrix 수행합니다. 인수로 지정된 투시 법을 적용하는 필요한 특수 매트릭스를 반환하는 함수입니다

그렇습니다. 이제 앞에서 설명한 model-view matrix projectionmatrix 자바스크립트에서 WebGL 보내기 위해setMatrixUniforms 함수에서 파생된 모든것을 보고 왔습니다. 무서운 쉐이더에 관한 것도 말이죠. 그들은 내부적으로 관련되어 있습니다. 그래서 살짝 그들의 배경을 살펴보도록 하겠습니다.

쉐이더(Shader) 무엇인가, 생각해 보신적 있나요? , 3D 그래픽 역사의 어느 시점에서 그들은 이렇게 생각하고 있었을 것입니다. - 화면에 부분에 어떤 그늘을 클릭하거나, 무슨 색깔인지 여부를 시스템에 전달하는 코드 질량. 그러나 시간이 흘러 지속적으로 기능이 향상되어 지금은 그리기 전에 하고 싶은 것은 무엇이든 가능한 코드 덩어리 정도로 인식되는 같습니다. 그리고 이것은 사실 매우 유용합니다. (a)그래픽카드에서 작동하기 때문에 매우 빠르게 동작 가능. (b)그들이 있는 변환 프로세스는 이러한 간단한 예제에서 정말 유용하게 다룰 있음.

이러한 간단한 WebGL 예제(적어도 OpenGL 튜토리얼의"intermediate"입니다)에도 쉐이더를 도입하는 이유는 WebGL 구조를 이용하기 위해서입니다. 다행히 쉐이더는 그래픽 카드에서 작동하기 때문에 우리의 model-view matrix projectionmatrix 정의되어 있는 모든 지점과 버텍스를 상대적으로 느린 자바스크립트 처리하지 않아도 장면을 그릴수 있기 때문입니다. 이것은 믿을 없을 정도로 편리하며, 이로인한 추가적인 오버헤드가 발생하더라도 그에 상응하는 가치를 얻을 있습니다.


초기화 함수 - initShaders

다시 초기화 부분입니다. webGLStart 함수는 initShaders 함수를 읽고 있었어요. 라인씩 살펴보도록 합시다.


  var shaderProgram;

  function initShaders() {

    var fragmentShader= getShader(gl, "shader-fs");

    var vertexShader = getShader(gl, "shader-vs");

 

    shaderProgram = gl.createProgram();

    gl.attachShader(shaderProgram,vertexShader);

    gl.attachShader(shaderProgram,fragmentShader);

    gl.linkProgram(shaderProgram);

 

    if (!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)) {

      alert("Could notinitialise shaders");

    }

 

    gl.useProgram(shaderProgram);

위와 같이 getShader 함수를 사용하여 "fragmentshader" "vertex shader" 가지를 검색하여 WebGL"program"이라는 녀석이 붙어 있습니다Program WebGL 시스템 옆에 배치되는 코드의 일부입니다. 이것은 그래픽 카드에서 작동하는 무언가를 지정하는 방법을 간파할 있습니다. 기대 했을지도 모르지만 program 여러 쉐이더와 연결됩니다. 쉐이더는 program중인 코드 조각을 있습니다. 각각의 program 한개의 fragment shader 한개의 vertex shader 유지할 있습니다. 그것은 조금 나중에 봅시다.


    shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");

    gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

program 설치되고 shader 연결되면"attribute" 대한 참조를 검색합니다. 그것은 programvertexPositionAttribute라는 새로운 필드에 저장됩니다. 다시 말하지만 자바스크립트 어떠한 객체든지 다양한 새로운 필드를 추가할 있다는 특징이 있습니다. 이를 이용하여 program 기본적으로 존재하지 않는vertexPositionAttribute라는 필드를 추가합니다. 필요한 정보를 모아 두는 것이 편리하기 때문에"attribute" program 해당 할당해 버립니다.

그런데, vertexPosionAttribute 무엇을 위해 있는 것일까요? 기억 할지 모르지만, drawScene 함수에서 사용되었습니다. 만약 삼각형의 버텍스 좌표를 적절한 버퍼에서 설정하는 코드로 돌아오면, 버퍼와 애트리뷰트를 연계하고 있는 것을 있을 것입니다. 분명히 나중에 의미를 있습니다. 지금은gl.enableVertexAttribArray 함수를 사용하여 WebGL 배열에서 애트리뷰트 값을 제공하려는 것을 전하고 있다는 부분에만 주목합시다.


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

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

  }

initShader 마지막 부분은 program에서 두개의 값을 보유하고 있습니다. uniformvariable라고 하는 것의 location입니다. 나중에 빨리 설명하기 때문에 당분간은 애트리뷰트와 비슷한 것이라고 생각합시다. 값을 편리하게 처리할 있도록 program 객체에 저장해 둡니다


지원 함수 - getShader

이제 getShader 함수를 살펴보도록 합니다.

  function getShader(gl, id) {

      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;

      }

 

      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;

      }

 

      gl.shaderSource(shader, str);

      gl.compileShader(shader);

 

      if (!gl.getShaderParameter(shader,gl.COMPILE_STATUS)) {

          alert(gl.getShaderInfoLog(shader));

          return null;

      }

 

      return shader;

  }


함수도 보기보다 훨씬 쉽습니다. 여기서 하고 있는 일은 인수로 전달된 ID 일치하는 요소를 HTML에서 찾아 내용물을 꺼내 fragment vertex 하나인 shader 가지는 type(type 차이점은 미래의 학습) 따라 작성하여 WebGL 그래픽 카드에서 작동하게 컴파일을 걸어놓고 있는 것입니다. 다음 코드에 오류가 없는지 확인했습니다. 물론 쉐이더를 자바스크립트 코드에 문자열로 통합할 있었습니다. 경우에는 HTML에서 불러올 부분은 필요하지 않습니다. 그러나 이번 방법은 쉐이더가 페이지의 스크립트가 되므로 자바스크립트처럼 쉽게 읽을 있습니다.


하드웨어 언어 - Shader

그것을 근거로 쉐이더코드를 살펴봅시다.

<script id="shader-fs" type="x-shader/x-fragment">

  #ifdef GL_ES

  precision highp float;

  #endif

 

  void main(void) {

    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);

  }

</script>

 

<script id="shader-vs" type="x-shader/x-vertex">

  attribute vec3 aVertexPosition;

 

  uniform mat4 uMVMatrix;

  uniform mat4 uPMatrix;

 

  void main(void) {

    gl_Position = uPMatrix * uMVMatrix *vec4(aVertexPosition, 1.0);

  }

</script>


가장 명심해야 것은 이들은 자바스크립트 작성되어 있지 않다는 것입니다. 사실쉐이더코드는 C언어의 영향을 강하게 받은(물론 자바스크립트) 특별한 쉐이더언어로 작성되어 있습니다. 번째 스크립트는 fragment shader입니다. 하지만 그리 복잡해 보이지는 않군요. 코드에는 그래픽 카드 float 정밀도를 지정하는데 반드시 포함하지 않으면 안되는 마스크의 일부분이 있습니다. 아래는 렌더링되는 모든 것이 간단하게 흰색으로 렌더링하도록 지정합니다.(색상에 관한 사항은 다음 레슨에서 설명합니다) 다음 쉐이더는 더욱 재미있습니다. 이것은 vertex shader입니다. 기억 하겠지만, vertex shader vertex 사용하여 매우 여러가지 일을 꾸밀수 있게 하며, 역시 그래픽 카드에서 실행되는 코드입니다.

여기에 관련한 uMVMatrix uPMatrix라는 두개의 uniform 변수 있습니다. uniform 변수 쉐이더외부에서 액세스할 있기 때문에 유용합니다. - 특히, program 있는 곳과 관계가 있습니다. initShaders에서 location 꺼내는데 다음으로 보이는 model-view projectionmatrix 설정하는 부분입니다. 당신은 쉐이더프로그램을 (객체 지향의) object uniform 변수 field 정도로 간주해 버릴지도 모르겠네요

이제 모든 버텍스에 대해 쉐이더가 호출됩니다. 그리고 버텍스는 drawScene 내부vertexPositionAttribute으로 애트리뷰트와 버퍼를 연관지 쉐이더에 VertexPosition 전달됩니다. vertex shader main 함수 내부의 작은 코드는 버텍스에 model-viewmatrix projection matrix 곱한 결과를 최종 버텍스 좌표로 출력하는 것입니다

그래서, webGLStart initShaders 부르고 안에 getShader 사용하여 fragment vertex shader 페이지 내의 스크립트에서 검색하여 컴파일하고 WebGL 전달하여 3D 화면을 그릴 사용되는 것입니다.


지원 함수 -setMatrixUniforms

이제 끝으로 설명할 녀석은 setMatrixUniforms 함수입니다. 이것은 지금까지의 내용을 알고 있다면 매우 간단하게 이해할 있습니다.

  function setMatrixUniforms() {

    gl.uniformMatrix4fv(shaderProgram.pMatrixUniform,false, new Float32Array(pMatrix.flatten()));

    gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform,false, new Float32Array(mvMatrix.flatten()));

  }


여기에서는 initShader 함수에서 얻은 projectionmatrix model-view matrix 나타내는 uniform 변수 대한 참조를 사용하여 WebGL 자바스크립트 형식의 매트릭스를 전달합니다

~ 처음 학습치고는 양이 많았네요. 레슨은 여러분과 제가 앞으로 더욱 재미있는 것을 만드는데 필요한 것들입니다. 기본적으로 필요한 항목을 모두 이해했습니다. 색상, 운동, 실재 3차원 입체 WebGL 모델들에 대하여 말예요. 그리고 많은 것을 공부하기 위해 레슨 2 이어집니다.


짬짬히 작성 하다보니 많이 늦어졌네요. 정확하게 모두 이해하지는 못했지만 몇몇 그래픽 용어를 숙지하고 대략적인 작동 원리를 이해하는 중요한 학습이였습니다. 그리고 보시다시피 문서는 다소 어눌합니다. 확실히 이해하고 작성한 것이 아니기 때문에 저도 무슨 말을 하려고 하는지 모르는 부분이 상당수 있었습니다. 그리고 원문을 보면 이양반 말하는 스타일이 그리 논리적이지는 못한 느낌을 자주 받았는데, 일단 그런 부분들은 대략적으로 직역했지만 계속 학습하면서 조금씩 다듬어 가도록 하겠습니다.

原创粉丝点击