WebGL - Shaders: 초보자 가이드
안녕하세요, 미래의 프로그래머 여러분! 오늘 우리는 WebGL Shaders의 세계에 흥미로운 여정을 떠납니다. 코드를 한 줄도 작성해 본 적이 없더라도 걱정하지 마세요 - 이 컬러풀한 컴퓨터 그래픽의 세계에서 여러분의 친절한 안내자가 될게요.
Shaders는 무엇인가요?
들어가기 전에 shaders가 무엇인지 이해해 보겠습니다. 그림을 그리는 상상해 봅시다. 캔버스는 여러분의 컴퓨터 화면이고, shaders는 컴퓨터가 각 픽셀을 어떻게 색칠해야 하는지 정확히 알려주는 마법의 붓입니다. 멋지죠?
데이터 타입
shader 세계에서 우리는 특별한 데이터 타입을 사용합니다. 이들을 살펴보겠습니다:
데이터 타입 | 설명 | 예시 |
---|---|---|
float | 단 정밀 부동소수점 수 | 3.14 |
vec2 | 2D 벡터 | vec2(1.0, 2.0) |
vec3 | 3D 벡터 | vec3(1.0, 2.0, 3.0) |
vec4 | 4D 벡터 | vec4(1.0, 2.0, 3.0, 4.0) |
mat2 | 2x2 행렬 | mat2(1.0, 2.0, 3.0, 4.0) |
mat3 | 3x3 행렬 | mat3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0) |
mat4 | 4x4 행렬 | mat4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0) |
이게 무서운 것 같지 않으세요 - 우리는 단계별로 사용하겠습니다!
퀼리파이어
퀼리파이어는 우리의 변수에 붙이는 특별한 레이블입니다. 이 퀼리파이어는 shader가 이 변수들을 어떻게 다루어야 하는지 알려줍니다. 주요 퀼리파이어를 소개하겠습니다:
퀼리파이어 | 설명 |
---|---|
attribute | 각顶점에 변화하는 입력 값 |
uniform | 모든顶점에 대해 일정한 입력 값 |
varying | 顶점 셰이더에서 프래그먼트 셰이더로 전달되는 값 |
顶点 셰이더
顶点 셰이더는 우리의 3D 모델의 뼈대입니다. 이 셰이더는 우리의 모델의 각 점(顶点)이 화면에 어디에 있어야 하는지 계산합니다. 간단한顶点 셰이더를 보겠습니다:
attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}
이를 분해해 보겠습니다:
-
attribute
인aVertexPosition
를 선언합니다 - 이는 우리의顶点의 위치입니다. - 두 개의
uniform
행렬을 가집니다 - 이들은 우리의 3D 모델을 위치시키고 화면에 투영하는 데 도움을 줍니다. -
main
함수에서 우리는顶点의 최종 위치를 계산합니다.
프래그먼트 셰이더
顶点 셰이더가 뼈대라면, 프래그먼트 셰이더는 피부입니다. 이 셰이더는 각 픽셀의 색상을 결정합니다. 간단한 프래그먼트 셰이더를 보겠습니다:
precision mediump float;
void main(void) {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
이 셰이더는 모든 것을 빨간색으로 칠입니다! vec4(1.0, 0.0, 0.0, 1.0)
는 전체 빨간색, 녹색이 없고, 파란색이 없고, 전체 투명도를 의미합니다.
셰이더 프로그램 저장 및 컴파일
이제 우리가 쓴 셰이더를 WebGL에 알리는 필요가 있습니다. 이를 JavaScript로 어떻게 하는지 보겠습니다:
function getShader(gl, id) {
const shaderScript = document.getElementById(id);
if (!shaderScript) return null;
const str = shaderScript.text;
let 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;
}
이 함수는 몇 가지 작업을 합니다:
- HTML 문서에서 셰이더 코드를 찾습니다.
- 적절한 타입의 셰이더를 생성합니다 (顶点 또는 프래그먼트).
- 셰이더를 컴파일하고 오류를 확인합니다.
결합 프로그램
마지막으로, 우리는顶点과 프래그먼트 셰이더를 프로그램으로 결합해야 합니다:
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("셰이더를 초기화할 수 없습니다");
}
gl.useProgram(shaderProgram);
이 코드는 프로그램을 생성하고, 셰이더를 첨부하고, 프로그램을 링크하고, WebGL이 이를 사용하도록 지시합니다.
그렇게 해서! 여러분이 WebGL 셰이더의 세계로的第一步을 걸었습니다. 새로운 언어를 배우는 것처럼, 연습이 필요합니다. 바로 이해가 되지 않더라도 실망하지 마세요 - 계속 실험하면 곧 웹 브라우저에서 놀라운 3D 그래픽을 만들 수 있을 것입니다!
제가 가르친 연간 동안 많은 학생들이 완전한 초보자에서 셰이더 마법사로 변모했습니다. 한 학생은 이 기술을 사용하여 최종 프로젝트로 가상 미술관을 만들었습니다 - 웹 브라우저에서 3D 미술관을 걸어 다니는 것을 상상해 보세요!
그렇다면 여러분은 새로운 셰이더 기술로 무엇을 만들 것인가요? 상상력이 유일한 제한입니다! 행복한 코딩, 미래의 그래픽 마법사 여러분!
Credits: Image by storyset