출처: webglfundamentals.org 사이트
해당 사이트의 내용과 설명이 필요한 개념들을 추가하여 재구성한 내용입니다.
Fragment Shader의 역할은 래스터화되는 현재 픽셀의 색상을 제공하는 것이다.
항상 아래와 같은 형식으로 나타낸다.
precision mediump float;
void main() {
gl_FragColor = doMathToMakeAColor;
}
Fragment Shader는 각 픽셀마다 한 번씩 호출된다. 호출될 때마다 특수 전역 변수인 gl_FragColor
를 어떠한 색상으로 설정해줘야 한다.
Fragment Shader는 데이터가 필요하다. 3가지 방법으로 데이터를 가져올 수 있다.
셰이더의 텍스처에서 값을 가져오면 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은 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;
}