From 574871202af73ac18fb3f289287e83fe701e739b Mon Sep 17 00:00:00 2001 From: eupthere Date: Thu, 28 May 2026 13:39:47 +0900 Subject: [PATCH 1/2] Add Korean translation for `intro-to-shaders` --- src/content/tutorials/ko/intro-to-shaders.mdx | 857 ++++++++++++++++++ 1 file changed, 857 insertions(+) create mode 100644 src/content/tutorials/ko/intro-to-shaders.mdx diff --git a/src/content/tutorials/ko/intro-to-shaders.mdx b/src/content/tutorials/ko/intro-to-shaders.mdx new file mode 100644 index 0000000000..19c42ebf85 --- /dev/null +++ b/src/content/tutorials/ko/intro-to-shaders.mdx @@ -0,0 +1,857 @@ +--- +title: "셰이더 입문" +description: 컴퓨터의 GPU를 활용해 흥미로운 시각 효과를 만드는 여러 방법을 소개합니다. +category: webgl +categoryIndex: 3 +featuredImage: ../images/featured/intro-to-shaders.jpg +featuredImageAlt: 뒤틀리고 물결치는 도시 거리 +relatedContent: + examples: + - en/11_3d/04_filter_shader/description + - en/11_3d/05_adjusting_positions_with_a_shader/description + - en/11_3d/06_framebuffer_blur/description + references: + - en/p5/createfiltershader + - en/p5/loadshader + - en/p5/p5shader +authors: + - Dave Pagurek + - Austin Lee Slominski + - Adam Ferriss +--- + +import EditableSketch from "../../../components/EditableSketch/index.astro"; +import Callout from "../../../components/Callout/index.astro"; +import AnnotatedCode from "../../../components/AnnotatedCode/index.astro"; +import { Image } from "astro:assets"; +import uv from "../images/webgl/uv_example.png"; + +현대의 컴퓨터에는 GPU(Graphics Processing Unit)라는 특별한 하드웨어가 들어 있습니다. 셰이더는 이 GPU에서 실행되는 특수한 프로그램으로, 놀라운 것들을 해낼 수 있습니다. 셰이더는 GPU를 활용해 많은 픽셀을 한 번에 병렬로 처리하므로 매우 빠르며, 노이즈 생성, 블러 같은 필터 적용, 다각형에 음영 입히기처럼 컴퓨터 그래픽스 작업에 특히 잘 맞습니다. + +셰이더 프로그래밍은 처음에는 낯설고 어렵게 느껴질 수 있습니다. p5.js의 2D 드로잉과는 다른 방식으로 접근해야 하기 때문입니다. 이 튜토리얼에서는 셰이더 프로그래밍의 기초를 짚어 보고, 더 살펴볼 만한 자료도 함께 소개합니다. + + +## 준비 + +브라우저에서 GPU를 프로그래밍하는 데 [WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API)이라는 API를 사용합니다. p5.js는 셰이더 작업에 매우 유용합니다. WebGL의 반복적인 준비 과정을 대신 처리해 주기 때문에, 셰이더 코드에 집중할 수 있습니다. 셰이더를 사용해보려면 먼저 p5.js 캔버스를 WebGL 모드로 설정해야 합니다. 이를 위해 `createCanvas()`의 세 번째 매개변수로 `WEBGL` 상수를 추가합니다. + +```javascript +... + +function setup() { + createCanvas(200, 200, WEBGL); +} + +... +``` + +셰이더 프로그램은 두 부분으로 이루어집니다. 바로 **정점 셰이더**(vertex shader)와 **프래그먼트 셰이더**(fragment shader)입니다. 정점 셰이더는 도형의 각 정점마다 한 번씩 실행되며, 그 정점이 화면 어디에 그려질지를 결정합니다. 프래그먼트 셰이더는 도형의 모든 픽셀마다 한 번씩 실행되며, 각 픽셀의 색을 결정합니다. + + + + + + + + + + + + + + + + + + + + + + + +
+ +![빨간 구](../images/webgl/sphere.png) + + + +![시간에 따라 흔들리고 뒤틀리는 빨간 구](../images/webgl/vertshader.gif) + + + +![울퉁불퉁한 구의 실루엣 안이 빨강과 파랑 줄무늬로 채워진 모습](../images/webgl/fragshader.gif) + +
+ +*원래 형태* + + + +*커스텀 정점 셰이더는 도형 안의 정점 위치를 조정할 수 있습니다* + + + +*커스텀 프래그먼트 셰이더는 도형 내부의 색을 조정할 수 있습니다* + +
+ +{/* Note for contributors: Images/gifs generated from https://editor.p5js.org/davepagurek/sketches/gs-DbLzqV */} + +이 둘은 각각 별도의 파일에 들어 있으며, `loadShader()` 함수로 p5.js로 불러와 `setup()`, `draw()` 에서 사용할 수 있습니다. 다음 예제를 통해 p5.js에서 기본 셰이더를 설정하는 방법을 살펴봅시다. + +```javascript +let myShader; +function preload() { + // 각 셰이더 파일을 불러옵니다 + // (걱정 마세요, 이건 곧 다시 살펴볼 거예요!) + myShader = loadShader('shader.vert', 'shader.frag'); +} +function setup() { + // 캔버스는 WEBGL 모드로 만들어야 합니다 + createCanvas(windowWidth, windowHeight, WEBGL); +} +function draw() { + // shader()는 활성 셰이더를 설정하고, + // 이후 그려지는 것들에 적용됩니다 + shader(myShader); + // 캔버스 전체를 덮는 사각형에 셰이더를 적용합니다 + plane(width, height); +} +``` + +추가로 `createShader()`라는 함수도 있는데, 이 함수는 스케치 안에 문자열로 직접 작성한 셰이더를 불러올 때 사용할 수 있습니다.  + + +## 셰이더 작성하기 + +이제 `loadShader()`에서 참조한 정점, 프래그먼트 셰이더 파일 안에 무엇이 들어가는지 살펴보겠습니다. + + +### 셰이딩 언어(GLSL) + +셰이더 파일은 Graphics Library Shading Language, 즉 GLSL(OpenGL 2.0, GLSL ES 1.00 기반)로 작성합니다. 문법과 구조가 우리가 익숙한 자바스크립트와는 꽤 다릅니다. GLSL은 C와 비슷한 문법을 가지므로, 자바스크립트에는 없는 개념들도 함께 등장합니다. + +우선 셰이딩 언어는 타입에 훨씬 엄격합니다. 만드는 모든 변수에는 어떤 데이터를 저장하는지 타입을 명시해야 합니다. 아래는 자주 쓰이는 타입 몇 가지입니다. + +```glsl +vec2(x,y) // 두 개의 float로 이루어진 벡터 +vec3(x,y,z) // 세 개의 float로 이루어진 벡터 + // (r,g,b로도 볼 수 있음) +vec4(x,y,z,w) // 네 개의 float로 이루어진 벡터 + // (r,g,b,a로도 볼 수 있음) +float // 소수점을 가지는 숫자 +int // 소수점이 없는 정수 +sampler2D // 텍스처를 참조하는 값 +mat2 // 2x2 행렬 +mat3 // 3x3 행렬 +mat4 // 4x4 행렬 +bool // true 또는 false +``` + +전반적으로 셰이딩 언어는 자바스크립트보다 훨씬 엄격합니다. 세미콜론 하나만 빠져도 오류가 발생합니다. float와 int 같은 서로 다른 숫자 타입을 섞어서 쓸 수도 없습니다. 또 `float` 값은 반드시 소수점까지 써 주어야 하므로, `0.0`이나 `1.0` 같은 숫자를 자주 쓰게 됩니다. + +다음은 GLSL에서 달라지는 몇 가지 예시입니다. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +Javascript + + + +GLSL + +
+ +모든 변수에 타입이 필요합니다. + + + +```javascript +let a = 1; +let b = 0.5; +``` + + + +```glsl +int a = 1; +float b = 0.5; +``` + +
+ +함수는 매개변수의 타입과 반환값의 타입을 모두 선언해야 합니다. + + + +```javascript +function isBetween(val, start, end) { +  return val >= start && val <= end; +} +``` + + + +```glsl +bool isBetween(float val, float start, float end) { +  return val >= start && val <= end; +} +``` + +
+ +int와 float 사이의 변환은 직접 해 주어야 합니다. + + + +```javascript +let a = 1; +let b = 0.5; +let c = b + 2; +let d = a + b; +``` + + + +```glsl +int a = 1; +float b = 0.5; +float c = b + 2.0; +float d = float(a) + b; +``` + +
+ +GLSL의 반복문은 상수 값에서 멈춰야 합니다. 조건에 따라 중간에 끝내고 싶다면 `break`를 사용할 수 있습니다. + + + +```javascript +let maxVal = 10; +if (something) { +  maxVal = 20; +} +for (let i = 0; i < maxVal; i++) { +  // 무언가를 합니다 +} +``` + + + +```glsl +int maxVal = 10; +if (something) { +  maxVal = 20; +} +for (int i = 0; i < 20; i++) { +  if (i == maxVal) { +    break; +  } +  // 무언가를 합니다 +} +``` + +
+ +제약이 많기는 하지만, 어떤 면에서는 GLSL이 더 편하게 느껴질 수도 있습니다! 특히, 벡터를 다루는 데 유용한 여러 축약 표현이 있습니다. + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +`vec4`가 있다면, 그 데이터를 색처럼 읽을 수도 있고 좌표처럼 읽을 수도 있습니다. 둘은 완전히 같으니, 코드가 더 읽기 쉬운 쪽을 골라 사용하면 됩니다. + + + +```glsl +// 각 쌍은 서로 같습니다: +myVec.x +myVec.r + +myVec.y +myVec.g + +myVec.z +myVec.b + +myVec.w +myVec.a +``` + +
+ +모든 값이 같은 벡터를 만들고 싶을 때는 같은 값을 여러 번 반복해서 쓰지 않아도 됩니다. 한 번만 써도 충분합니다. + + + +```glsl +// 두 표현은 같습니다 +myVec = vec3(0.5, 0.5, 0.5); +myVec = vec3(0.5); +``` + +
+ +더 큰 벡터에서 더 작은 벡터를 꺼낼 수도 있습니다. 이를 "스위즐링(swizzling)"이라고 하며, `.` 뒤에 원하는 순서대로 여러 속성을 이어 붙여 새 벡터를 만듭니다. + + + +```glsl +vec4 bigVec = vec4(1.0, 2.0, 3.0, 4.0); +// vec2(bigVec.z, bigVec.y)와 같습니다 +vec2 smallVec = bigVec.zy; +``` + +
+ + +### 정점 셰이더 + +다음은 간단한 정점 셰이더 예시입니다. p5.js에서 제공하는 변환과 카메라 원근을 적용합니다. + + +`${begin('precision')} + precision highp float; +${end('precision')} +${begin('attributes')} + attribute vec3 aPosition; +${end('attributes')} +${begin('uniforms')} + // 그려지는 객체의 변환 + uniform mat4 uModelViewMatrix; + // 3D 좌표를 2D 화면 좌표로 변환합니다 + uniform mat4 uProjectionMatrix; +${end('uniforms')} +${begin('main')} + void main() { + // 카메라 변환을 적용합니다 + vec4 viewModelPosition = + uModelViewMatrix * vec4(aPosition, 1.0); + // 이 정점이 어디에 그려질지 WebGL에 알려 줍니다 + gl_Position = + uProjectionMatrix * viewModelPosition; + } +${end('main')}`}> + + 셰이더는 `precision` 줄로 시작합니다. 여기에는 `lowp`, `mediump`, `highp` 중 하나를 씁니다. 처음에는 가장 높은 품질을 선택하는 것이 좋습니다. 그래야 다양한 환경에서 비슷하게 보입니다. 데스크톱이나 노트북은 어떤 값을 써도 보통 최고 품질로 처리됩니다. 휴대폰에서는 더 낮은 품질을 사용하는 것이 빠를 수 있지만, 렌더링 결과가 달라질 수 있습니다. + + + 셰이더의 *attribute*는 각 정점마다 달라지는 값을 담고 있으며, p5.js는 이를 통해 각 정점의 위치 같은 정보를 셰이더에 전달합니다. 이 셰이더에서 attribute는 `vec3` 타입으로, x, y, z 값을 담고 있습니다. Attribute는 정점 셰이더에서만 사용하는 특별한 변수 타입이며, 보통 p5.js가 제공합니다. `rect()`나 `vertex()` 같은 p5.js 함수를 사용할 때 p5.js가 정점 정보를 자동으로 셰이더에 넘겨 줍니다. + + + 셰이더의 *uniform*은 그려지는 도형 전체에서 일정한 값을 뜻합니다. 이 셰이더에서는 각 uniform이 `mat4` 타입인데, 이는 이동, 크기 조절, 회전 같은 변환을 표현할 때 자주 쓰이는 타입입니다. 점에 `mat4`를 곱하면 그 행렬이 나타내는 변환이 적용됩니다. 이 셰이더의 uniform들은 p5.js가 자동으로 제공하지만, 뒤에서 직접 커스텀 uniform을 전달하는 방법도 보게 될 것입니다. 참고로 행렬 곱셈에서는 순서가 중요합니다. 대부분의 경우 행렬을 먼저 쓰고, 그 뒤에 곱할 값을 씁니다. + + + 모든 정점 셰이더에는 `main()` 함수가 필요합니다. 이 안에서 `gl_Position`에 값을 할당해 정점의 위치를 정합니다. 이 값은 *클립 공간*(clip space)에 있으며, x, y, z 값은 한쪽 끝에서 다른 쪽 끝으로 갈 때 -1에서 1까지의 범위를 가집니다. `uProjectionMatrix`로 3D 점을 곱하면 p5.js의 카메라 설정을 이용해 이 변환을 자동으로 해 줍니다. 그 전에 이 셰이더는 `uModelViewMatrix`도 곱해 주는데, 이는 도형을 그리기 전에 설정된 누적 변환을 적용하기 위해서입니다. + + + +아직 이 내용이 완전히 이해되지 않아도 괜찮습니다. 정점 셰이더는 중요한 역할을 하지만, 대개 프래그먼트 셰이더에서 만든 결과가 도형 위에 올바르게 보이도록 하는 것이 전부입니다. 아마 여러 프로젝트에서 같은 정점 셰이더를 반복해서 사용하게 될 것입니다. 다음은 정점별 색과 텍스처 좌표 등 정보를 처리하는 표준 정점 셰이더입니다. + +```glsl +precision highp float; +attribute vec3 aPosition; +attribute vec2 aTexCoord; +attribute vec4 aVertexColor; +uniform mat4 uModelViewMatrix; +uniform mat4 uProjectionMatrix; +varying vec2 vTexCoord; +varying vec4 vVertexColor; +void main() { + // 카메라 변환을 적용합니다 + vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); + // 이 정점이 어디에 그려질지 WebGL에 알려 줍니다 + gl_Position = uProjectionMatrix * viewModelPosition;  + // 데이터를 프래그먼트 셰이더로 전달합니다 + vTexCoord = aTexCoord; + vVertexColor = aVertexColor; +} +``` + +### 프래그먼트 셰이더 + +프래그먼트 셰이더는 셰이더의 색 출력 결과를 담당합니다. 셰이더 프로그래밍의 많은 부분이 여기서 이루어집니다. 다음은 단순히 빨간색을 표시하는 간단한 프래그먼트 셰이더입니다. + + +`${begin('precision')} + precision highp float; +${end('precision')} +${begin('main')} + void main() { + vec4 myColor = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragColor = myColor; + } +${end('main')}`}> + + 프래그먼트 셰이더도 float의 `precision`을 지정하는 줄로 시작합니다. 이 값은 정점 셰이더의 `precision`과 동일해야 합니다. + + + 정점 셰이더와 마찬가지로 프래그먼트 셰이더에도 `main()` 함수가 필요합니다. 다만 여기서는 `gl_Position`을 설정하는 대신, GLSL이 제공하는 특별한 변수 `gl_FragColor`에 색을 할당합니다. + + `myColor` 변수는 `vec4`로 정의되어 네 개의 값을 저장합니다. 지금은 색을 다루고 있으므로, 빨강, 초록, 파랑, 알파입니다. 셰이더는 기본 p5.js 스케치처럼 0~255 범위의 색을 쓰지 않습니다. 대신 0.0에서 1.0 사이의 값을 사용합니다. + + + +이제 정점 셰이더와 프래그먼트 셰이더를 모두 갖추었으니, 이 코드를 각각 별도의 파일(`shader.vert`, `shader.frag`)로 저장해 `loadShader()`로 스케치에 불러올 수 있습니다. + + +## 유니폼: 스케치에서 셰이더로 데이터 전달하기 + +이처럼 단순한 셰이더도 충분히 유용할 수 있지만, p5.js 스케치의 변수를 셰이더와 주고받아야 할 경우도 있습니다. 이럴 때 사용하는 것이 유니폼입니다. 유니폼은 스케치에서 셰이더로 보낼 수 있는 변수의 한 종류입니다. 유니폼을 사용하여 자바스크립트에서 셰이더를 훨씬 더 세밀하게 제어할 수 있습니다. + +유니폼은 파일의 맨 위, `main()` 바깥에서 정의합니다. 이는 정점 셰이더와 프래그먼트 셰이더 양쪽 모두에서 접근할 수 있습니다. 아래 예제에서는 p5.js의 `millis()` 메서드가 반환하는 값을 `time`이라는 유니폼으로 전달해, 정점 셰이더에 움직임을 더합니다. + + + +프래그먼트 셰이더에서도 유니폼을 똑같이 사용할 수 있습니다. 다음 예제에서는 `myColor`라는 색 유니폼을 만들어 자바스크립트 쪽에서 색을 바꿀 수 있게 합니다. 다만 셰이더에서는 색 채널 값이 0\~255가 아니라 0\~1 범위라는 점을 기억해 두세요. + + + + +p5.js가 제공하는 유니폼의 전체 목록은 [p5.js WebGL Mode Architecture](https://github.com/processing/p5.js/blob/main/contributor_docs/webgl_mode_architecture.md) 문서에서 확인할 수 있습니다. + + +## Varyings: 정점 셰이더에서 프래그먼트 셰이더로 데이터 전달하기 + +*Varying* 변수는 정점 셰이더와 프래그먼트 셰이더 사이에서 데이터를 공유합니다. 덕분에 위치나 다른 기하 정보도 프래그먼트 셰이더 안에서 활용할 수 있습니다. + +예를 들어 프래그먼트 셰이더에서 도형의 텍스처 좌표를 사용하고 싶을 수 있습니다. 이 값은 `vec2` 형태로 들어오며, 좌표 범위는 0에서 1 사이입니다. 처음에는 p5.js가 제공하는 `attribute`로 들어오고, `attribute`는 정점 셰이더에서만 접근할 수 있습니다. 그럼 표준 정점 셰이더가 이 정보를 프래그먼트 셰이더로 어떻게 전달하는지 보겠습니다. + + +`precision highp float; + +attribute vec3 aPosition; +${begin('texcoord')} +attribute vec2 aTexCoord; +${end('texcoord')} + +uniform mat4 uModelViewMatrix; +uniform mat4 uProjectionMatrix; + +${begin('varying')} +varying vec2 vTexCoord; +${end('varying')} + +void main() { + // 카메라 변환을 적용합니다 + vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); + // 이 정점이 어디에 그려질지 WebGL에 알려 줍니다 + gl_Position = uProjectionMatrix * viewModelPosition; + ${begin('assign')} + vTexCoord = aTexCoord; + ${end('assign')} +} +`}> + + 텍스처 좌표는 처음에 `aTexCoord`라는 `attribute` 형태로 들어옵니다. 이 값은 p5.js가 자동으로 채워 줍니다. + + + 여기서는 `varying` 변수를 선언합니다. 정점 셰이더에서 선언한 varying은 프래그먼트 셰이더에서도 다시 선언할 수 있습니다. 이를 통해 정점 셰이더가 할당한 값을 프래그먼트 셰이더에서 사용할 수 있습니다. + + + *attribute*의 값을 *varying* 변수에 할당함으로써, 프래그먼트 셰이더가 읽을 수 있는 자리로 데이터를 복사합니다. + + + +정점 셰이더에서 `vTexCoord`라는 varying을 정의했으므로, 프래그먼트 셰이더에서도 이를 사용할 수 있습니다. 아래의 단순한 프래그먼트 셰이더는 x 값을 빨간 채널에, y 값을 초록 채널에 대응시킵니다. `vTexCoord`는 정점 셰이더에서는 *각 정점별* 값이지만, 프래그먼트 셰이더에서는 *각 픽셀별* 값이라는 점에 주목하세요. 픽셀별 값을 얻기 위해 WebGL은 각 면의 꼭짓점 값 사이를 부드럽게 보간합니다. + + +`${begin('shader')} + precision highp float; + varying vec2 vTexCoord; + void main() { + // 좌표를 셰이더의 색 출력으로 할당합니다 + gl_FragColor = vec4(vTexCoord.x, vTexCoord.y, 1.0, 1.0); + } +${end('shader')}`}> + + + 이 셰이더를 `plane(width, height)`에 적용하면 다음과 같은 결과가 나옵니다. + + 왼쪽 위는 검정, 오른쪽 위는 마젠타, 오른쪽 아래는 흰색, 왼쪽 아래는 시안으로 보이는 직사각형 그라데이션. + + + + + +## 필터 셰이더 + +p5.js에서 필터란 캔버스의 모든 픽셀을 살펴본 뒤 그것들을 다른 값으로 바꾸는 것입니다. 색을 반전하거나 캔버스에 블러를 적용하는 등 다양한 내장 필터가 있습니다. 직접 프래그먼트 셰이더를 작성해 자신만의 필터를 만들 수도 있습니다. + +필터 셰이더에는 프래그먼트 셰이더만 있으면 됩니다. 정점 셰이더는 주로 도형의 위치를 정하는 역할인데, 필터는 늘 캔버스 전체에 적용되기 때문입니다. 그래서 p5.js가 필터 셰이더에 기본 정점 셰이더를 제공해 줍니다. `loadShader` 대신 `createFilterShader(src)`를 사용하고, 셰이더 소스 코드를 담은 문자열을 넣으면 됩니다. + +필터 셰이더에서는 사용할 수 있는 `uniform`들이 몇 가지 있으며, 자세한 내용은 [`createFilterShader` 문서](https://p5js.org/reference/p5/createFilterShader)에서 확인할 수 있습니다. 시작할 때 특히 알아 두면 좋은 두 가지는 다음과 같습니다. + +- `uniform sampler2D tex0`는 캔버스의 내용을 담고 있는 텍스처입니다. +- `varying vec2 vTexCoord`는 현재 픽셀의 캔버스 좌표를 담고 있으며, 범위는 0에서 1입니다. + +이 둘을 조합하여 `texture2D(tex0, vTexCoord)`로 현재 픽셀의 색을 반환하고, 그 색을 원하는 대로 바꿀 수 있습니다. 아래 예제에서는 파란 채널 값을 빨강과 초록 채널로 복사해, 사용자 정의 흑백 필터를 만듭니다. + + + +또 다른 시도는 `texture2D`의 *출력*을 바꾸는 대신 *입력*을 바꾸는 것입니다. 사용하는 텍스처 좌표를 조정하면 원본에서 살짝 밀린 효과를 만들 수도 있고, 픽셀마다 오프셋을 다르게 주면 뒤틀림(warp) 효과도 만들 수 있습니다. + + + +## 마무리 + +여기까지의 내용만으로도 기본적인 셰이더를 만들 수 있습니다. 하지만 셰이더 프로그래밍의 세계는 훨씬 더 깊고 넓으며, 이 튜토리얼에서 다루지 못한 다양한 주제와 기법이 존재합니다. p5.js의 셰이더는 시각 효과, 텍스처, 3D 기하 구조 위에 입힐 수 있는 다양한 표현을 만드는 데 강력한 도구가 됩니다. + +셰이더를 더 배우고 싶다면 아래 자료도 살펴보세요! + +- [The Book of Shaders](https://thebookofshaders.com/), Patricio Gonzalez Vivo와 Jen Lowe의 셰이더 가이드 +- [p5.js shaders](https://itp-xstory.github.io/p5js-shaders/#/), Casey Conchinha와 Louise Lessél의 셰이더 가이드 +- [Shadertoy](https://www.shadertoy.com/), 브라우저 편집기에서 작성된 셰이더를 모아 둔 방대한 온라인 컬렉션 +- [p5js Shader Examples](https://github.com/aferriss/p5jsShaderExamples), Adam Ferriss가 모아 둔 자료 모음 +- [OpenGL ES 2.0 Specification](https://registry.khronos.org/OpenGL/specs/es/2.0/es_cm_spec_2.0.pdf), GLSL에 대한 매우 기술적인 명세 문서 +- [WebGL Quick Reference card](https://www.khronos.org/files/webgl/webgl-reference-card-1_0.pdf), 다소 빽빽하지만 GLSL 함수에 관한 유용한 정보가 많은 참고 카드 +- [Shaderific GLSL ES reference](https://shaderific.com/glsl.html), GLSL 내장 함수와 데이터 타입을 조금 더 간결하게 정리한 레퍼런스  + + +## 용어집 + +#### 셰이더 + +다양한 시각 효과와 필터를 효율적으로 만들어 낼 수 있는 GPU 프로그램입니다. + + +#### GLSL + +Graphics Library Shader Language(GLSL)는 셰이더를 작성할 때 사용하는 프로그래밍 언어입니다. + + +#### 유니폼 (Uniform) + +스케치에서 셰이더로 전달되는 변수입니다. + + +#### Varying + +정점 셰이더에서 프래그먼트 셰이더로 전달되는 변수입니다. + + +#### 벡터 (`vec2` / `vec3` / `vec4`) + +흔히 두 개, 세 개, 또는 네 개의 숫자를 묶어서 저장하는 데이터 타입으로, 색, 위치 등을 표현하는 데 사용됩니다. + + +#### Float + +소수점을 가질 수 있는 부동소수점 숫자를 저장하는 데이터 타입입니다. + + +#### Int + +소수점이 없는 정수를 저장하는 데이터 타입입니다. + + +#### Sampler + +셰이더로 전달되는 텍스처를 나타내는 데이터 타입입니다. GLSL에서는 보통 `sampler2D`로 표현합니다. + + +#### Attribute + +p5.js 스케치에서 생성되어 정점 셰이더에서 사용할 수 있게 되는 GLSL 변수입니다. 대부분의 경우 p5.js가 이를 제공합니다. + + +#### 텍스처 + +셰이더 프로그램에 전달되는 이미지입니다. `texture2D()` 함수를 사용해 샘플링할 수 있습니다. + + +#### 타입 + +int, float, vector 등 데이터의 형식을 설명하는 라벨입니다. + + +#### 정점 셰이더 (Vertex Shader) + +3D 공간에서 기하학적 객체의 위치를 정하는 셰이더 프로그램의 부분입니다. + + +#### 프래그먼트 셰이더 (Fragment Shader) + +셰이더가 출력하는 각 픽셀의 색과 외형을 담당하는 셰이더 프로그램의 부분입니다. From 9d657c16f1938cac67fd28d259adfdbbf442ccbb Mon Sep 17 00:00:00 2001 From: eupthere Date: Thu, 28 May 2026 13:40:10 +0900 Subject: [PATCH 2/2] Fix typo in `intro-to-shaders` --- src/content/tutorials/en/intro-to-shaders.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/tutorials/en/intro-to-shaders.mdx b/src/content/tutorials/en/intro-to-shaders.mdx index db0f551d96..5f81de8b1e 100644 --- a/src/content/tutorials/en/intro-to-shaders.mdx +++ b/src/content/tutorials/en/intro-to-shaders.mdx @@ -585,7 +585,7 @@ function draw() { shader(myShader); // Create a color using the mouse's x position as red and - // its y position as blue, and pass it into the shader + // its y position as green, and pass it into the shader myShader.setUniform('myColor', [ map(mouseX, 0, width, 0, 1, true), // Red map(mouseY, 0, width, 0, 1, true), // Green @@ -643,7 +643,7 @@ void main() { -Since we defined a `varying` called `vTexCoord` in the vertex shader, we can now use it in the fragment shader as well. Here is a simple fragment shader that maps the x value to the red channel and the y value to the blue channel. Note that while `vTexCoord` is defined *per vertex* in the vertex shader, its value is defined *per pixel* in the fragment shader. To get the per-pixel value, WebGL smoothly interpolates between the per-vertex values on each face. +Since we defined a `varying` called `vTexCoord` in the vertex shader, we can now use it in the fragment shader as well. Here is a simple fragment shader that maps the x value to the red channel and the y value to the green channel. Note that while `vTexCoord` is defined *per vertex* in the vertex shader, its value is defined *per pixel* in the fragment shader. To get the per-pixel value, WebGL smoothly interpolates between the per-vertex values on each face. `${begin('shader')}