웹에서 3D 그래픽을 그리려고 WebGL을 써보려고 하면, “셰이더가 뭐지?”, “버퍼는 왜 써야 하지?” 같은 질문부터 들게 됩니다.
이 글에서는 WebGL 셰이더(Shader)에 대해 다룹니다.
🌏 Shader
✅ WebGL은 Low Level API
WebGL은 GPU를 직접 제어할 수 있게 해주는 API의 구현체입니다. 다양한 구현 방식 중에 WebGL은 Low-Level API라서, 우리가 GPU에게 모든 걸 직접 지시해야 하는 방식입니다.
예를 들어서, "삼각형을 이렇게 이렇게 그려줘!" 라고 명령하기 위해서는 내가 그리고 싶은 삼각형을 화면 상에 어떤 점에 세 가지 꼭지점을 표시하고 각 픽셀을 어떤 색으로 칠할 지 일일이 명령해야 합니다. (추가로, 각 꼭짓점을 GPU에 전송하고 연결, 렌더링 방식을 설정하고 실행도 직접 해야 합니다.)
이런 명령을 쉽게 하기 위해 GPU에 돌아가는 두 가지 (작은) 프로그램이 있는데, 이것이 바로 Shader입니다.
Shader는 크게 두 가지로 나누어집니다.
꼭지점을 어디에 둘 지 → Vertex Shader 각 픽셀의 색을 뭘로 칠할 지 → Fragment Shader
✅ Shader의 필요성: 마인크래프트에서 정육면체를 삐딱하게 띄우고 싶다면?
아직 Shader가 왜 필요한지 잘 와닿지 않는다면 이런 예시를 통해 이해해 봅시다.
내가 마인크래프트 같은 게임을 만들고 있고, 공중에 떠 있는 정육면체(큐브) 하나를 멀리서 비스듬히 바라보는 장면을 구현하고 싶다고 해 볼게요-
이걸 WebGL에서 표현하려면 다음과 같은 계산이 필요합니다.
- 정육면체의 꼭짓점 8개를 만든다 local space
- 이 정육면체를 특정 위치로 이동 (translation)
- 화면을 기준으로 회전 (rotation)
- 카메라에서 멀리 떨어뜨리기 (z 방향 이동)
- 결국 이 꼭짓점들이 화면 위 어느 위치에 찍히는지 계산
👉 바로 이 모든 위치 계산을 담당하는 것이 Vertex Shader입니다.
자연스럽게 알 수 있는 것은, 정육면체 하나에 꼭짓점이 8개 있다면, Vertex Shader는 그 8개 각각 꼭지점에 대해서 한 번씩 실행된다는 것입니다.
✅ Shader는 GPU 위에서 실행되는 작은 프로그램
Shader는 GPU 위에서 실행되는 작은 프로그램이며, 크게 두 가지 종류가 있습니다
- Vertex Shader
"이 꼭짓점은 화면 어디에 위치해야 해?"
→ 꼭짓점 위치 계산 담당
- Fragment Shader
"이 위치의 색깔은 뭐야?"
→ 픽셀 색상 결정 담당
🌏 Vertex Shader
내가 그리고 싶은 도형이 화면 상에 어떤 위치에 표시될 지 꼭지점의 위치를 계산하는 데 사용됩니다.
✅ 특징
- 각 꼭짓점마다 한 번씩 실행됨
- 삼각형 하나 → 꼭짓점 3개 → 3번 실행
📥 input (from JS)
(프로그래밍 언어에서 전달되는 값들인데, 우리 예시는 자바스크립트를 사용하기 때문에 js라고 하겠습니다)
- a_position: 꼭짓점 위치 (local space)
- a_normal: 법선 벡터 → 조명 효과 계산
- a_color: 색상 (fragment shader에서 보간됨)
- a_texCoord: 텍스처 좌표 (이미지 맵핑용)
📤 output
- gl_Position: 화면 상에 이 점을 어디에 찍을지 결정하는 좌표 clip space
- vNormal, vColor, vTexCoord: fragment shader로 넘기는 값 (선택)
- 선택이지만, 외부에서 오는 빛을 반영하는 경우 해당 점의 법선 벡터를 고려해 색을 정해야 하는 상황 등이 있으므로 더 사실적인 색깔을 결정하기 위해서 필요함
✅ 예시 코드
#version 300 es
layout(location = 0) in vec3 a_position; // 꼭짓점 위치 (x, y, z) from JS
uniform mat4 u_modelViewProjection; // 모든 변환이 적용된 행렬 (내가 만들 도형을 화면에 옮기기 위한 행렬 연산)
void main() {
gl_Position = u_modelViewProjection * vec4(a_position, 1.0);
}
🌏 Fragment Shader
앞에서 계산한 꼭짓점들로 삼각형이 만들어졌다면, 이제 삼각형 안에 있는 각 픽셀을 무슨 색으로 칠할지 결정해야 합니다.
✅ 특징
- 화면의 픽셀 단위로 실행됨 → 연산이 무거워지는 경우 주의해야 함 (픽셀은 꼭지점 개수보다 압도적으로 많기 때문)
- 실제로 화면에 보이는 색상을 결정
📥 input (from vertex shader)
- vNormal, vColor, vTexCoord 등
📤 output
- FragColor: 픽셀 최종 색상 (vec4(RGBA) 형식)
✅ 코드 예시
#version 300 es
precision mediump float;
out vec4 FragColor; // 최종 픽셀 색상 (RGBA)
void main() {
FragColor = vec4(0.2, 0.6, 1.0, 1.0); // 모든 픽셀을 연한 파란색으로 칠함.
}
🌏 Shader 공통 변수
변수 종류 셰이더 사용 가능 위치 설명
attribute | Vertex Shader 전용 | JS에서 꼭짓점별로 넘겨주는 입력 값 |
uniform | Vertex/Fragment 둘 다 사용 | JS에서 공통으로 전달하는 전역 설정 값 |
varying | Vertex → Fragment 연결용 | 꼭짓점 기준으로 픽셀에 보간됨 |
🌏 셰이더 프로그램 사용법
WebGL에서 셰이더를 사용하는 기본 절차는 다음과 같습니다:
// 1. 셰이더 객체 생성
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// 2. 셰이더 소스 설정
gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);
// 3. 컴파일
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
// 4. 프로그램 생성 및 셰이더 attach
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
// 5. 링크 및 사용
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);

도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
비밀댓글과 메일을 통해 오는 개인적인 질문은 받지 않고 있습니다. 꼭 공개댓글로 남겨주세요!
'Computer Science > Graphics' 카테고리의 다른 글
[컴퓨터그래픽스] WebGL API와 그래픽 기초 (1) | 2025.04.18 |
---|
웹에서 3D 그래픽을 그리려고 WebGL을 써보려고 하면, “셰이더가 뭐지?”, “버퍼는 왜 써야 하지?” 같은 질문부터 들게 됩니다.
이 글에서는 WebGL 셰이더(Shader)에 대해 다룹니다.
🌏 Shader
✅ WebGL은 Low Level API
WebGL은 GPU를 직접 제어할 수 있게 해주는 API의 구현체입니다. 다양한 구현 방식 중에 WebGL은 Low-Level API라서, 우리가 GPU에게 모든 걸 직접 지시해야 하는 방식입니다.
예를 들어서, "삼각형을 이렇게 이렇게 그려줘!" 라고 명령하기 위해서는 내가 그리고 싶은 삼각형을 화면 상에 어떤 점에 세 가지 꼭지점을 표시하고 각 픽셀을 어떤 색으로 칠할 지 일일이 명령해야 합니다. (추가로, 각 꼭짓점을 GPU에 전송하고 연결, 렌더링 방식을 설정하고 실행도 직접 해야 합니다.)
이런 명령을 쉽게 하기 위해 GPU에 돌아가는 두 가지 (작은) 프로그램이 있는데, 이것이 바로 Shader입니다.
Shader는 크게 두 가지로 나누어집니다.
꼭지점을 어디에 둘 지 → Vertex Shader 각 픽셀의 색을 뭘로 칠할 지 → Fragment Shader
✅ Shader의 필요성: 마인크래프트에서 정육면체를 삐딱하게 띄우고 싶다면?
아직 Shader가 왜 필요한지 잘 와닿지 않는다면 이런 예시를 통해 이해해 봅시다.
내가 마인크래프트 같은 게임을 만들고 있고, 공중에 떠 있는 정육면체(큐브) 하나를 멀리서 비스듬히 바라보는 장면을 구현하고 싶다고 해 볼게요-
이걸 WebGL에서 표현하려면 다음과 같은 계산이 필요합니다.
- 정육면체의 꼭짓점 8개를 만든다 local space
- 이 정육면체를 특정 위치로 이동 (translation)
- 화면을 기준으로 회전 (rotation)
- 카메라에서 멀리 떨어뜨리기 (z 방향 이동)
- 결국 이 꼭짓점들이 화면 위 어느 위치에 찍히는지 계산
👉 바로 이 모든 위치 계산을 담당하는 것이 Vertex Shader입니다.
자연스럽게 알 수 있는 것은, 정육면체 하나에 꼭짓점이 8개 있다면, Vertex Shader는 그 8개 각각 꼭지점에 대해서 한 번씩 실행된다는 것입니다.
✅ Shader는 GPU 위에서 실행되는 작은 프로그램
Shader는 GPU 위에서 실행되는 작은 프로그램이며, 크게 두 가지 종류가 있습니다
- Vertex Shader
"이 꼭짓점은 화면 어디에 위치해야 해?"
→ 꼭짓점 위치 계산 담당
- Fragment Shader
"이 위치의 색깔은 뭐야?"
→ 픽셀 색상 결정 담당
🌏 Vertex Shader
내가 그리고 싶은 도형이 화면 상에 어떤 위치에 표시될 지 꼭지점의 위치를 계산하는 데 사용됩니다.
✅ 특징
- 각 꼭짓점마다 한 번씩 실행됨
- 삼각형 하나 → 꼭짓점 3개 → 3번 실행
📥 input (from JS)
(프로그래밍 언어에서 전달되는 값들인데, 우리 예시는 자바스크립트를 사용하기 때문에 js라고 하겠습니다)
- a_position: 꼭짓점 위치 (local space)
- a_normal: 법선 벡터 → 조명 효과 계산
- a_color: 색상 (fragment shader에서 보간됨)
- a_texCoord: 텍스처 좌표 (이미지 맵핑용)
📤 output
- gl_Position: 화면 상에 이 점을 어디에 찍을지 결정하는 좌표 clip space
- vNormal, vColor, vTexCoord: fragment shader로 넘기는 값 (선택)
- 선택이지만, 외부에서 오는 빛을 반영하는 경우 해당 점의 법선 벡터를 고려해 색을 정해야 하는 상황 등이 있으므로 더 사실적인 색깔을 결정하기 위해서 필요함
✅ 예시 코드
#version 300 es
layout(location = 0) in vec3 a_position; // 꼭짓점 위치 (x, y, z) from JS
uniform mat4 u_modelViewProjection; // 모든 변환이 적용된 행렬 (내가 만들 도형을 화면에 옮기기 위한 행렬 연산)
void main() {
gl_Position = u_modelViewProjection * vec4(a_position, 1.0);
}
🌏 Fragment Shader
앞에서 계산한 꼭짓점들로 삼각형이 만들어졌다면, 이제 삼각형 안에 있는 각 픽셀을 무슨 색으로 칠할지 결정해야 합니다.
✅ 특징
- 화면의 픽셀 단위로 실행됨 → 연산이 무거워지는 경우 주의해야 함 (픽셀은 꼭지점 개수보다 압도적으로 많기 때문)
- 실제로 화면에 보이는 색상을 결정
📥 input (from vertex shader)
- vNormal, vColor, vTexCoord 등
📤 output
- FragColor: 픽셀 최종 색상 (vec4(RGBA) 형식)
✅ 코드 예시
#version 300 es
precision mediump float;
out vec4 FragColor; // 최종 픽셀 색상 (RGBA)
void main() {
FragColor = vec4(0.2, 0.6, 1.0, 1.0); // 모든 픽셀을 연한 파란색으로 칠함.
}
🌏 Shader 공통 변수
변수 종류 셰이더 사용 가능 위치 설명
attribute | Vertex Shader 전용 | JS에서 꼭짓점별로 넘겨주는 입력 값 |
uniform | Vertex/Fragment 둘 다 사용 | JS에서 공통으로 전달하는 전역 설정 값 |
varying | Vertex → Fragment 연결용 | 꼭짓점 기준으로 픽셀에 보간됨 |
🌏 셰이더 프로그램 사용법
WebGL에서 셰이더를 사용하는 기본 절차는 다음과 같습니다:
// 1. 셰이더 객체 생성
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
// 2. 셰이더 소스 설정
gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);
// 3. 컴파일
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
// 4. 프로그램 생성 및 셰이더 attach
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
// 5. 링크 및 사용
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);

도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
비밀댓글과 메일을 통해 오는 개인적인 질문은 받지 않고 있습니다. 꼭 공개댓글로 남겨주세요!
'Computer Science > Graphics' 카테고리의 다른 글
[컴퓨터그래픽스] WebGL API와 그래픽 기초 (1) | 2025.04.18 |
---|