WebGL Shader: Fragment Shader

mango·2023년 9월 7일
0

🪡WebGL

목록 보기
5/5
post-thumbnail

출처: webglfundamentals.org 사이트
해당 사이트의 내용과 설명이 필요한 개념들을 추가하여 재구성한 내용입니다.


Fragment Shader의 역할은 래스터화되는 현재 픽셀의 색상을 제공하는 것이다.

항상 아래와 같은 형식으로 나타낸다.

precision mediump float;
 
void main() {
  gl_FragColor = doMathToMakeAColor;
}

Fragment Shader는 각 픽셀마다 한 번씩 호출된다. 호출될 때마다 특수 전역 변수인 gl_FragColor 를 어떠한 색상으로 설정해줘야 한다.

Fragment Shader는 데이터가 필요하다. 3가지 방법으로 데이터를 가져올 수 있다.

  1. 유니폼 - 단일 그리기 호출의 모든 정점에 동일하게 유지되는 값
  2. 텍스처 - 픽셀/텍셀 데이터
  3. Varying - Vertex Shader에서 전달되고 보간된 데이터

Fragment Shader의 텍스처

셰이더의 텍스처에서 값을 가져오면 sampler2D유니폼을 생성하고 값을 추출하기 위해 GLSL 함수 texture2D를 사용한다.

precision mediump float;
 
uniform sampler2D u_texture;
 
void main() {
  vec2 texcoord = vec2(0.5, 0.5);  // 텍스처 중앙에서 값 가져오기
  gl_FragColor = texture2D(u_texture, texcoord);
}

텍스처에서 나오는 데이터는 설정에 따라 달라진다.

아래의 코드는 최소한의 텍스처 데이터를 생성하고 넣어보는 예제이다.

var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
var level = 0;
var width = 2;
var height = 1;
var data = new Uint8Array([
  255, 0, 0, 255,   // 빨강 픽셀
  0, 255, 0, 255,   // 초록 픽셀
]);
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

초기화 할때 Shader 프로그램의 유니폼 위치를 찾고

var someSamplerLoc = gl.getUniformLocation(someProgram, "u_texture");

렌더링할 때 텍스처 유닛에 텍스처를 할당한 뒤에

var unit = 5;  // 텍스처 유닛 선택
gl.activeTexture(gl.TEXTURE0 + unit);
gl.bindTexture(gl.TEXTURE_2D, tex);

텍스처를 바인딩한 유닛이 무엇인지 Shader에 알려준다.

gl.uniform1i(someSamplerLoc, unit);

Varying

Varying은 Vertex Shader에서 Fragment Shader로 값을 전달하는 방법이다.

Varying을 사용하려면 Vertex Shader와 Fragment Shader 양쪽에 일치하는 varying을 선언한다.

Vertex Shader에 잇는 varying을 각 정점마다 어떤 값으로 정하고, WebGL 이 픽셀을 그릴 때 이 값을 보간해 Fragment Shader의 varying으로 전달한다.

Vertex Shader

attribute vec4 a_position;
 
uniform vec4 u_offset;
 
varying vec4 v_positionWithOffset;
 
void main() {
  gl_Position = a_position + u_offset;
  v_positionWithOffset = a_position + u_offset;
}

Fragment Shader

precision mediump float;
 
varying vec4 v_positionWithOffset;
 
void main() {
  // 클립 공간에서 (-1 <-> +1) color space로 (0 -> 1) 변환
  vec4 color = v_positionWithOffset * 0.5 + 0.5;
  gl_FragColor = color;
}

profile
https://mangode.tistory.com/

0개의 댓글