WebGL - Shaders: 초보자 가이드

안녕하세요, 미래의 프로그래머 여러분! 오늘 우리는 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);
}

이를 분해해 보겠습니다:

  1. attributeaVertexPosition를 선언합니다 - 이는 우리의顶点의 위치입니다.
  2. 두 개의 uniform 행렬을 가집니다 - 이들은 우리의 3D 모델을 위치시키고 화면에 투영하는 데 도움을 줍니다.
  3. 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;
}

이 함수는 몇 가지 작업을 합니다:

  1. HTML 문서에서 셰이더 코드를 찾습니다.
  2. 적절한 타입의 셰이더를 생성합니다 (顶点 또는 프래그먼트).
  3. 셰이더를 컴파일하고 오류를 확인합니다.

결합 프로그램

마지막으로, 우리는顶点과 프래그먼트 셰이더를 프로그램으로 결합해야 합니다:

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