본문 바로가기

WebGL

WebGL Fundamentals > Fundamentals : Varying

https://webglfundamentals.org/webgl/lessons/webgl-how-it-works.html

 

WebGL How It Works

What WebGL is really doing under the hood

webglfundamentals.org

https://github.com/Myoungmin/WebGL_Fundamentals

 

GitHub - Myoungmin/WebGL_Fundamentals: WebGL 학습 프로젝트

WebGL 학습 프로젝트. Contribute to Myoungmin/WebGL_Fundamentals development by creating an account on GitHub.

github.com

 

 

◈ 이번 실습에서 복습할 포인트

- Varying을 사용하는 방법.

- 2개 이상의 속성을 사용하고, 데이터를 vertex shader에서 fragment shader로 전달하는 방법.

이미지 처리를 하려면 텍스처 좌표를 전달하기 위해, 이 예시와 마찬가지로 추가적인 attribute를 사용해야 한다

 

 

Varying

vertex shader는 GLSL로 작성하는 함수이다. 

이 함수는 각 vertex마다 한 번씩 호출된다. 

몇 가지 계산한 다음 현재 vertex의 클립 공간 값으로 특수 변수 gl_Position을 설정한다. 

GPU는 이 값을 가져와서 내부에 저장한다.

 

TRIANGLES를 그린다고 가정하면,

정점 3개를 생성할 때마다 GPU는 이걸 이용해 삼각형을 만든다.

어떤 픽셀이 삼각형의 점 3개에 해당하는지 확인한 다음, 

삼각형을 픽셀로 그리는 과정인 래스터화한다.

 

이렇게 생성된 픽셀은 픽셀마다 fragment shader를 호출하여 어떤 색상으로 만들지 결정한다.

fragment shader는 특수 변수 gl_FragColor를 해당 픽셀에 원하는 색상으로 설정해야 한다.

 

vertex shader에서 fragment shader로 더 많은 정보를 전달하려면 전달하려는 각 값에 "varying"을 정의하는 방법이 있다.

 

 

◈ 더 많은 정보를 전달하기 위해 vertex shader와 fragment shader에 varying을 선언한다.

1. fragment shader로 데이터를 전달하기 위해 vertex shader에 varying을 선언한다.

varying vec4 v_color;
//...
void main() {
  // 위치에 행렬 곱하기
  gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
 
  // 클립 공간에서 색상 공간으로 변환
  // 클립 공간 -1.0에서 +1.0까지에서 색상 공간 0.0에서 1.0까지로 변환하는 식
  v_color = gl_Position * 0.5 + 0.5;
}

 

2. fragment shader에 동일한 varying을 선언한다.

precision mediump float;
 
varying vec4 v_color;
 
void main() {
  gl_FragColor = v_color;
}

 

위 설정에서 우리는 vertex 3개만을 계산했다. 

위 shader를 사용하면 vertex shader는 3번만 호출되므로 3개의 색상만을 계산하지만 삼각형은 여러 색상으로 표출된다. 

이게 varying이라고 불리는 이유다.

 

WebGL은 각 정점을 계산한 3개의 값을 가져오고, 
삼각형을 래스터화할 때 계산된 vertex들 사이를 보간한다. 
각 픽셀마다 해당 픽셀에 대해 보간된 값으로 fragment를 호출한다.

 

shader의 아래 식을 통해 색상 공간으로 변환하고 우리가 선언한 varying에 작성된다.

// 클립 공간에서 색상 공간으로 변환
// 클립 공간 -1.0에서 +1.0까지에서 색상 공간 0.0에서 1.0까지로 변환하는 식
v_color = gl_Position * 0.5 + 0.5;


v_color에 vertex를 통해 작성된 3개의 값들은 보간되어 각 픽셀에 대한 fragment shader로 전달된다.
각 픽셀로 보간된 값들에 의해 색상이 결정되므로 삼각형이 여러 색상으로 표출된다.
이러한 과정 때문에 삼각형을 이동하면 픽셀 위치가 바뀌기 때문에 varying에 의해 삼각형 색상이 바뀐다.

 

 

◈ 더 많은 데이터를 vertex shader에 전달하여 fragment shader에 전달할 수 있다.

vertex shader에 attribute를 추가하고, 이를 통해 넘겨 받은 데이터를 varying에 입력하여 fragment shader에 전달한다.

attribute vec2 a_position;
attribute vec4 a_color;
...
varying vec4 v_color;
 
void main() {
  ...
  // 속성에서 베링으로 색상 복사
  v_color = a_color;
}

자바스크립트에서 색상 데이터를 생성하고 추가한 attribute에 이 색상 데이터를 전달한다.

// 정점 데이터가 필요한 곳 탐색
var positionLocation = gl.getAttribLocation(program, "a_position");
var colorLocation = gl.getAttribLocation(program, "a_color");
...
// 색상을 위한 버퍼 생성
var colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
// 색상 설정
setColors(gl);
...
 
// 사각형을 만드는 두 삼각형의 색상으로 버퍼 채우기
function setColors(gl) {
  // 모든 정점을 다른 색상으로 만들기
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([
      Math.random(), Math.random(), Math.random(), 1,
      Math.random(), Math.random(), Math.random(), 1,
      Math.random(), Math.random(), Math.random(), 1,
      Math.random(), Math.random(), Math.random(), 1,
      Math.random(), Math.random(), Math.random(), 1,
      Math.random(), Math.random(), Math.random(), 1
    ]),
    gl.STATIC_DRAW
  );
}

Rendering할 때 생성한 buffer에서 색상 데이터를 attribute로 어떻게 가져올지 설정한다.

gl.enableVertexAttribArray(colorLocation);
 
// 색상 버퍼 할당
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
 
// colorBuffer(ARRAY_BUFFER)의 데이터를 가져오는 방법을 색상 속성에 지시
var size = 4;          // 반복마다 4개의 컴포넌트
var type = gl.FLOAT;   // 데이터는 32비트 부동 소수점
var normalize = false; // 데이터 정규화 안 함
var stride = 0;        // 0 = 다음 위치를 가져오기 위해 반복마다 size * sizeof(type) 만큼 앞으로 이동
var offset = 0;        // 버퍼의 처음부터 시작
gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);

 

 

 

 

 

https://myoungmin.github.io/WebGL_Fundamentals/

 

WebGL_Fundamentals

WebGL이란? WebGL은 Web Graphics Library의 약자로 웹상에서 2D 및 3D 그래픽을 렌더링하기 위한 로우 레벨 Javascript API.

myoungmin.github.io