WebGL - 그래픽 파이프라인
안녕하세요, 야심찬 프로그래머 여러분! 오늘 우리는 WebGL 그래픽 파이프라인을 통해 흥미로운 여정을 떠납니다. 프로그래밍에 처음이라면 걱정하지 마세요 - 나는 당신의 친절한 안내자가 될 것이며, 단계별로 함께 나아갈 것입니다. 이 튜토리얼의 끝을 맞아서, 여러분은 WebGL이 코드를 어떻게 스크린에 훌륭한 시각적으로 변환하는지 확실하게 이해하게 될 것입니다.
자바스크립트: 시작점
WebGL의 깊이로 뛰어들기 전에, 익숙한 것으로부터 시작해 보겠습니다 - 자바스크립트. WebGL은 자바스크립트를 통해 접근되므로, 우리의 모험의 완벽한 출발점입니다.
첫 번째 WebGL 프로그램
간단한 예제로 시작해 보겠습니다:
// 캔버스 요소 가져오기
const canvas = document.getElementById('myCanvas');
// WebGL 컨텍스트 가져오기
const gl = canvas.getContext('webgl');
// 배경색 설정
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 캔버스 지우기
gl.clear(gl.COLOR_BUFFER_BIT);
이 코드 조각에서 우리는 몇 가지 일을 합니다:
- HTML 캔버스 요소에 대한 참조를 가져옵니다.
- WebGL 렌더링 컨텍스트를 얻습니다.
- 배경색을 설정합니다 (이 경우, 검정색).
- 지정된 색상으로 캔버스를 지웁니다.
이것이 많이 보이지 않을 수 있지만, 축하합니다! 여러분은 첫 번째 WebGL 프로그램을 만들었습니다. 마치 거대한 캔버스를 준비하는 것과 같습니다.
베릭스 셰이더: 세상을 형성하는 것
이제 캔버스가 준비되었으므로, 베릭스 셰이더에 대해 이야기해 보겠습니다. 베릭스 셰이더는 3D 세상의 조각가라고 생각해 보세요. 그들은 오브젝트의 원시 데이터 - 베릭스 -을 다룹니다.
간단한 베릭스 셰이더
기본 베릭스 셰이더의 예제를 보겠습니다:
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
이 셰이더는 간단하지만 매우 중요한 일을 합니다 - 각 베릭스의 위치를 gl_Position
에 할당합니다. 마치 3D 오브젝트의 각 점에게 "여기로 가라"고 말하는 것과 같습니다.
원시 어셈블리: 점을 연결하는 것
베릭스 셰이더가 그 일을 마친 후, WebGL은 원시 어셈블리 단계로 넘어갑니다. 이 단계는 마치 점을 연결하는 퍼즐과 같습니다 - 개별 베릭스를 연결하여 형태를 형성합니다.
예를 들어, 삼각형을 그리는 경우, 원시 어셈블리는 세 개의 베릭스를 가져와서 그들이 단일 삼각형을 형성한다고 이해합니다.
래스터라이제이션: 어디서나 픽셀
이제 래스터라이제이션의 마법이 시작됩니다. 이 단계는 3D 형태를 2D 픽셀로 변환합니다. 마치 3D 조각을 상세한 사진으로 만드는 것과 같습니다.
프래그먼트 셰이더: 세상을 칠하는 것
프래그먼트 셰이더는 진정한 예술이 일어나는 곳입니다. 베릭스 셰이더가 오브젝트의 구조를 다루었다면, 프래그먼트 셰이더는 그것을 칠합니다.
간단한 프래그먼트 셰이더
적색으로 칠하는 기본 프래그먼트 셰이더를 보겠습니다:
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
이 셰이더는 gl_FragColor
를 적색 벡터로 설정합니다 (전체 적색, 녹색과 파란색 없음, 전체 불투명도). 마치 전체 3D 세상을 적색 페인트로 덮는 것과 같습니다.
프래그먼트 연산: 최종 터치
프래그먼트 셰이더 후, WebGL은 프래그먼트에 다양한 연산을 수행합니다. 이는 깊이 테스트(어느 오브젝트가 다른 오브젝트 앞에 있는지 결정), 투명도 처리(투명한 오브젝트가 어떻게 상호작용하는지) 등을 포함합니다.
프레임 버퍼: 대단한 결말
마지막으로, 프레임 버퍼에 도달합니다. 이는 렌더링된 이미지가 화면에 표시되기 전에 저장되는 곳입니다. 마치 무대 뒤쪽에서 최종 터치를 가하는 것과 같습니다.
모든 것을 함께 모음
이제 각 단계를 거쳐가 보았으므로, 모든 것을 함께 모아보겠습니다. 완전한 WebGL 프로그램을 보겠습니다:
// 베릭스 셰이더 소스 코드
const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;
// 프래그먼트 셰이더 소스 코드
const fsSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
// 셰이더 초기화
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
// 셰이더 프로그램 생성
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
// 프로그램 사용
gl.useProgram(shaderProgram);
// 버퍼 생성 및 데이터 전송
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
const positions = [
1.0, 1.0,
-1.0, 1.0,
1.0, -1.0,
-1.0, -1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
// 베릭스 데이터를 베릭스 포지션 속성으로 끌어올리는 방법 지정
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.vertexAttribPointer(
gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, 'aVertexPosition'));
// 시ーン 그리기
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
이 프로그램은 검정 배경에 간단한 적색 사각형을 그립니다. 이를 분해해 보겠습니다:
- 우리는 베릭스와 프래그먼트 셰이더를 정의합니다.
- 셰이더를 컴파일하고 프로그램에 연결합니다.
- 버퍼를 생성하고 데이터를 전송합니다.
- 베릭스 데이터를 베릭스 포지션 속성으로 끌어올리는 방법을 지정합니다.
- 캔버스를 지우고 시ーン을 그립니다.
각 단계는 우리가 논의한 그래픽 파이프라인의 단계에 해당합니다. 마치 생산 라인을 지켜보는 것처럼, 원시 데이터(베릭스 데이터)가 완성된 제품(화면에 표시되는 픽셀)으로 변환됩니다.
메서드 표
이 튜토리얼에서 사용한 주요 WebGL 메서드 표입니다:
메서드 | 설명 |
---|---|
gl.createShader() |
셰이더 오브젝트 생성 |
gl.shaderSource() |
셰이더의 소스 코드 설정 |
gl.compileShader() |
셰이더 컴파일 |
gl.createProgram() |
프로그램 오브젝트 생성 |
gl.attachShader() |
셰이더 프로그램에 연결 |
gl.linkProgram() |
프로그램 링크 |
gl.useProgram() |
현재 렌더링 상태로 프로그램 설정 |
gl.createBuffer() |
버퍼 오브젝트 생성 |
gl.bindBuffer() |
버퍼 오브젝트를 대상에 바인드 |
gl.bufferData() |
버퍼 오브젝트의 데이터 저장소 생성 및 초기화 |
gl.vertexAttribPointer() |
베릭스 데이터 레이아웃 지정 |
gl.enableVertexAttribArray() |
베릭스 속성 배열 활성화 |
gl.clearColor() |
색상 버퍼 지우기 시 사용할 색상 설정 |
gl.clear() |
버퍼 지우기 |
gl.drawArrays() |
배열 데이터를 사용하여 원시 그리기 |
이제 WebGL 그래픽 파이프라인을 통해 여러분의 여정이 끝났습니다. 기억하시라, 어떤 기술도 연습이 필요합니다. 하지만 각 코드 줄을 작성할 때마다, 웹 브라우저에서 훌륭한 3D 그래픽을 만드는 데 한 걸음 더 다가갑니다. 계속 실험하고, 배우고, 가장 중요한 것은 즐겁게 만들어 보세요!
Credits: Image by storyset