shader를 CSS transform 관점으로 읽기
shader라는 단어는 처음 들으면 그래픽스 전공 느낌이 납니다. 하지만 2D 에디터를 만드는 입장에서는 조금 단순하게 시작할 수 있습니다.
vertex shader는 좌표를 바꾸는 작은 함수입니다.
fragment shader는 픽셀 색을 정하는 작은 함수입니다.
shader를 최소 코드로 보면
2D editor 초반의 shader는 복잡하지 않아도 됩니다. vertex shader는 position을 matrix로 변환하고, fragment shader는 색을 반환합니다.
#version 300 es
in vec2 a_position;
uniform mat3 u_matrix;
void main() {
vec3 clip = u_matrix * vec3(a_position, 1.0);
gl_Position = vec4(clip.xy, 0.0, 1.0);
}
#version 300 es
precision highp float;
uniform vec4 u_color;
out vec4 outColor;
void main() {
outColor = u_color;
}
JavaScript 쪽에서는 uniform 위치를 찾아 값을 넣습니다.
const matrixLocation = gl.getUniformLocation(program, "u_matrix");
const colorLocation = gl.getUniformLocation(program, "u_color");
gl.useProgram(program);
gl.uniformMatrix3fv(matrixLocation, false, projectionCameraNodeMatrix);
gl.uniform4f(colorLocation, 0.05, 0.58, 0.53, 1);
gl.drawArrays(gl.TRIANGLES, 0, 6);
이 정도만 있어도 “CSS transform + background color”와 거의 같은 역할을 GPU에서 수행할 수 있습니다.
vertex shader는 transform 함수다
CSS에서 transform은 요소의 local 좌표를 화면 좌표로 바꿉니다.
transform: matrix(a, b, c, d, e, f);
WebGL의 vertex shader도 비슷한 일을 합니다.
gl_Position = u_matrix * vec4(a_position, 0.0, 1.0);
여기서 a_position은 vertex의 local 좌표이고, u_matrix는 좌표계를 바꾸는 행렬입니다. CSS matrix와 완전히 같은 표기는 아니지만 생각은 같습니다.
fragment shader는 fill을 정한다
사각형의 fill color를 CSS에서는 이렇게 씁니다.
background: #0d9488;
fragment shader에서는 픽셀 색을 직접 반환합니다.
outColor = vec4(0.05, 0.58, 0.53, 1.0);
처음에는 단색 fill만 다룹니다. gradient, texture, blur는 나중 문제입니다.
shader는 renderer 정책이다
scene model에는 “이 node의 fill은 teal” 같은 의미 있는 정보가 있어야 합니다. shader code 자체가 문서 모델이 되면 안 됩니다.
scene fill -> renderer uniform/attribute -> fragment shader color
이 선을 지키면 나중에 WebGPU의 WGSL로 옮길 때도 editor model은 그대로 유지됩니다.
오늘의 핵심
shader는 마법이 아닙니다. 2D editor 초반에는 이렇게 읽으면 됩니다.
vertex shader: 좌표 변환
fragment shader: 색 결정
CSS transform과 background를 GPU 함수로 옮겨 읽는 것이 첫 단계입니다.