-
🌏 WebGL: Canvas, Viewport, 그리고 렌더링까지
-
✅ HTML Canvas: 픽셀을 담는 공간
-
✅ WebGL2 Context: 그래픽 API의 진입점
-
🌏 왜 WebGL은 Low-Level API일까?
-
✅ 모든 것을 직접 제어해야 한다
-
✅ Viewport: 어디에 그릴 것인가?
-
✅ 여러 Viewport로 나누기
-
✅ Canvas와 좌표계: (0, 0)은 어디인가?
-
🌏 Frame Buffer와 Raster: 화면에 보여주는 최종 이미지
-
✅ Frame Buffer란?
-
✅ Raster란?
-
✅ Scan Conversion: 도형을 픽셀로
-
🌏 render() 함수는 어디에 그리고 있을까?
-
✅ Back Buffer → Front Buffer로
-
✅ resize 이벤트와 다시 그리기
🌏 WebGL: Canvas, Viewport, 그리고 렌더링까지
WebGL을 처음 접하면 가장 먼저 만나는 개념은 canvas, gl, 그리고 render() 함수다. 이 글에서는 처음으로 WebGL로 그래픽을 그릴 때 꼭 이해해야 하는 요소들을 하나하나 짚어보며, 실제로 어떻게 동작하는지도 함께 알아보자.
✅ HTML Canvas: 픽셀을 담는 공간
HTML5에서 제공하는 <canvas> 요소는 브라우저 안에서 그림을 그릴 수 있는 공간을 제공한다. 이 공간은 비트맵 형식의 2D 또는 3D 그래픽을 표현할 수 있다.
<canvas id="myCanvas"></canvas>
자바스크립트로 접근할 수 있으며, 이렇게 사용할 수 있다:
const canvas = document.getElementById('myCanvas');
canvas.width,canvas.height: 캔버스의 실제 픽셀 해상도를 의미한다.- 크기가 클수록 메모리를 더 많이 사용한다는 점도 염두에 두어야 한다.
✅ WebGL2 Context: 그래픽 API의 진입점
HTML <canvas>는 그 자체로 그림을 그릴 수 있는 기능을 가지고 있지는 않다. 대신, WebGL2와 같은 그래픽 API를 부여해야 한다.
const gl = canvas.getContext('webgl2');
여기서 gl은 WebGL2의 rendering context로, 이후 모든 WebGL 명령어들은 이 gl 객체를 통해 이루어진다. 예를 들어:
gl.clearColor(0.1, 0.2, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
이처럼 WebGL2는 하드웨어 수준의 세밀한 설정이 필요한 low-level API다.
🌏 왜 WebGL은 Low-Level API일까?
✅ 모든 것을 직접 제어해야 한다
WebGL2는 셰이더 작성, 정점 설정, 버퍼 바인딩, 텍스처 관리 등 거의 모든 그래픽스 설정을 개발자가 직접 수동으로 지정해야 한다.
- 그림 하나 그리기 위해:
- 정점(vertex) 버퍼 생성
- 셰이더 컴파일
- draw 호출
자동으로 처리되는 로직은 거의 없기 때문에, low-level API로 분류된다.
✅ Viewport: 어디에 그릴 것인가?
WebGL에서 Viewport는 실제로 그림이 그려지는 캔버스 내부의 사각형 영역을 말한다. 기본적으로는 전체 캔버스를 사용하지만, 필요에 따라 나눌 수 있다.
gl.viewport(0, 0, canvas.width, canvas.height); // 전체 캔버스를 Viewport로 사용
- 파라미터:
(x, y, width, height) - 좌표 (0, 0)은 캔버스의 좌하단(bottom-left) 을 의미한다.
✅ 여러 Viewport로 나누기
하나의 canvas를 여러 뷰포트로 나눠서 다양한 시점을 동시에 그릴 수 있다. 예를 들어 4개의 시점을 다음처럼 나눌 수 있다:
// 전체 캔버스를 4분할한 예시
const w = canvas.width;
const h = canvas.height;
gl.viewport(0, h / 2, w / 2, h / 2); // 왼쪽 위 (Top view)
drawTopView();
gl.viewport(w / 2, h / 2, w / 2, h / 2); // 오른쪽 위 (Side view)
drawSideView();
gl.viewport(0, 0, w / 2, h / 2); // 왼쪽 아래 (Front view)
drawFrontView();
gl.viewport(w / 2, 0, w / 2, h / 2); // 오른쪽 아래 (Perspective view)
drawPerspectiveView();
하나의 canvas에서 다양한 시점을 표현하는 이 방식은 3D 모델링 프로그램에서도 흔히 사용된다.
✅ Canvas와 좌표계: (0, 0)은 어디인가?
| 환경 | (0, 0)의 위치 | Y 방향 |
|---|---|---|
| HTML Canvas 2D | 좌상단 (top-left) | 아래로 증가 |
| WebGL Viewport | 좌하단 (bottom-left) | 위로 증가 |
| WebGL NDC | 중심 (0,0) | 위로 증가 (-1~1 사이) |
이처럼 좌표계의 기준이 다르기 때문에 위치 계산 시 항상 문맥을 확인해야 한다.
🌏 Frame Buffer와 Raster: 화면에 보여주는 최종 이미지
✅ Frame Buffer란?
Frame Buffer는 GPU가 그리고 있는 픽셀 데이터를 담고 있는 메모리 상의 저장 공간이다.
Color buffer: 픽셀의 색상 정보Depth buffer: 깊이(z값)를 저장하여 겹치는 물체를 판단Stencil buffer: 마스킹 및 클리핑용
화면에 보이는 이미지는 결국 이 Frame Buffer에 저장된 내용을 디스플레이가 읽어서 보여주는 것이다.
✅ Raster란?
Raster는 화면을 격자 모양으로 나눈 픽셀들의 집합이다. 벡터 기반 도형을 raster 이미지로 바꾸는 과정을 Rasterization 또는 Scan Conversion이라고 부른다.
- Raster: 실제 픽셀 데이터 (2차원 배열)
- Pixel: 그 중 하나의 점 (색상 정보를 담고 있음)
✅ Scan Conversion: 도형을 픽셀로
Scan Conversion은 벡터로 정의된 삼각형, 선분 등을 픽셀 단위로 변환하는 과정이다.
벡터 도형 (정점 좌표) → 어떤 픽셀을 켜야 할까? → Raster 이미지
이 과정에서:
- 삼각형 내부인지 판단 (Coverage Test)
- 픽셀별 색상 보간, 깊이값 계산
- 최종 픽셀에 색상 출력
🌏 render() 함수는 어디에 그리고 있을까?
render() 함수는 GPU가 실제로 그림을 그리는 Back Buffer에 내용을 출력한다.
function render() {
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(...);
}
✅ Back Buffer → Front Buffer로
- WebGL은 더블 버퍼링을 사용한다:
- Back Buffer: 그림 그리는 중
- Front Buffer: 사용자에게 보여지는 화면
- 그리기 완료 후 자동으로 swap되어 부드러운 화면 전환이 가능해진다.
깜빡임(flickering)을 방지하기 위한 핵심 기술이 바로 이 더블 버퍼링이다.
✅ resize 이벤트와 다시 그리기
브라우저 창이 바뀔 때는 canvas 크기와 viewport도 같이 바꿔줘야 한다. 이를 위해 resize 이벤트 리스너를 설정한다:
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
gl.viewport(0, 0, canvas.width, canvas.height);
render(); // 다시 그림
});
캔버스 크기 = 실제 렌더링 해상도
viewport = 그 중 어디에 그릴지를 결정
'컴퓨터과학 > 컴퓨터그래픽스' 카테고리의 다른 글
| [컴퓨터그래픽스] 3D 그래픽스에서의 좌표 변환: Local → World → View → Clip → Screen (0) | 2025.10.23 |
|---|---|
| [컴퓨터그래픽스] 3D 조명: Local/Global Illumination, Phong 반사 모델 (0) | 2025.10.23 |
| [컴퓨터그래픽스] Three.js를 사용해 3D 게임을 만들어보자! (0) | 2025.10.23 |
| [컴퓨터그래픽스] Shader를 이해하는 가장 쉬운 방법: 개념, 예시, 사용법까지! (2) | 2025.05.01 |
🌏 WebGL: Canvas, Viewport, 그리고 렌더링까지
WebGL을 처음 접하면 가장 먼저 만나는 개념은 canvas, gl, 그리고 render() 함수다. 이 글에서는 처음으로 WebGL로 그래픽을 그릴 때 꼭 이해해야 하는 요소들을 하나하나 짚어보며, 실제로 어떻게 동작하는지도 함께 알아보자.
✅ HTML Canvas: 픽셀을 담는 공간
HTML5에서 제공하는 <canvas> 요소는 브라우저 안에서 그림을 그릴 수 있는 공간을 제공한다. 이 공간은 비트맵 형식의 2D 또는 3D 그래픽을 표현할 수 있다.
<canvas id="myCanvas"></canvas>
자바스크립트로 접근할 수 있으며, 이렇게 사용할 수 있다:
const canvas = document.getElementById('myCanvas');
canvas.width,canvas.height: 캔버스의 실제 픽셀 해상도를 의미한다.- 크기가 클수록 메모리를 더 많이 사용한다는 점도 염두에 두어야 한다.
✅ WebGL2 Context: 그래픽 API의 진입점
HTML <canvas>는 그 자체로 그림을 그릴 수 있는 기능을 가지고 있지는 않다. 대신, WebGL2와 같은 그래픽 API를 부여해야 한다.
const gl = canvas.getContext('webgl2');
여기서 gl은 WebGL2의 rendering context로, 이후 모든 WebGL 명령어들은 이 gl 객체를 통해 이루어진다. 예를 들어:
gl.clearColor(0.1, 0.2, 0.3, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
이처럼 WebGL2는 하드웨어 수준의 세밀한 설정이 필요한 low-level API다.
🌏 왜 WebGL은 Low-Level API일까?
✅ 모든 것을 직접 제어해야 한다
WebGL2는 셰이더 작성, 정점 설정, 버퍼 바인딩, 텍스처 관리 등 거의 모든 그래픽스 설정을 개발자가 직접 수동으로 지정해야 한다.
- 그림 하나 그리기 위해:
- 정점(vertex) 버퍼 생성
- 셰이더 컴파일
- draw 호출
자동으로 처리되는 로직은 거의 없기 때문에, low-level API로 분류된다.
✅ Viewport: 어디에 그릴 것인가?
WebGL에서 Viewport는 실제로 그림이 그려지는 캔버스 내부의 사각형 영역을 말한다. 기본적으로는 전체 캔버스를 사용하지만, 필요에 따라 나눌 수 있다.
gl.viewport(0, 0, canvas.width, canvas.height); // 전체 캔버스를 Viewport로 사용
- 파라미터:
(x, y, width, height) - 좌표 (0, 0)은 캔버스의 좌하단(bottom-left) 을 의미한다.
✅ 여러 Viewport로 나누기
하나의 canvas를 여러 뷰포트로 나눠서 다양한 시점을 동시에 그릴 수 있다. 예를 들어 4개의 시점을 다음처럼 나눌 수 있다:
// 전체 캔버스를 4분할한 예시
const w = canvas.width;
const h = canvas.height;
gl.viewport(0, h / 2, w / 2, h / 2); // 왼쪽 위 (Top view)
drawTopView();
gl.viewport(w / 2, h / 2, w / 2, h / 2); // 오른쪽 위 (Side view)
drawSideView();
gl.viewport(0, 0, w / 2, h / 2); // 왼쪽 아래 (Front view)
drawFrontView();
gl.viewport(w / 2, 0, w / 2, h / 2); // 오른쪽 아래 (Perspective view)
drawPerspectiveView();
하나의 canvas에서 다양한 시점을 표현하는 이 방식은 3D 모델링 프로그램에서도 흔히 사용된다.
✅ Canvas와 좌표계: (0, 0)은 어디인가?
| 환경 | (0, 0)의 위치 | Y 방향 |
|---|---|---|
| HTML Canvas 2D | 좌상단 (top-left) | 아래로 증가 |
| WebGL Viewport | 좌하단 (bottom-left) | 위로 증가 |
| WebGL NDC | 중심 (0,0) | 위로 증가 (-1~1 사이) |
이처럼 좌표계의 기준이 다르기 때문에 위치 계산 시 항상 문맥을 확인해야 한다.
🌏 Frame Buffer와 Raster: 화면에 보여주는 최종 이미지
✅ Frame Buffer란?
Frame Buffer는 GPU가 그리고 있는 픽셀 데이터를 담고 있는 메모리 상의 저장 공간이다.
Color buffer: 픽셀의 색상 정보Depth buffer: 깊이(z값)를 저장하여 겹치는 물체를 판단Stencil buffer: 마스킹 및 클리핑용
화면에 보이는 이미지는 결국 이 Frame Buffer에 저장된 내용을 디스플레이가 읽어서 보여주는 것이다.
✅ Raster란?
Raster는 화면을 격자 모양으로 나눈 픽셀들의 집합이다. 벡터 기반 도형을 raster 이미지로 바꾸는 과정을 Rasterization 또는 Scan Conversion이라고 부른다.
- Raster: 실제 픽셀 데이터 (2차원 배열)
- Pixel: 그 중 하나의 점 (색상 정보를 담고 있음)
✅ Scan Conversion: 도형을 픽셀로
Scan Conversion은 벡터로 정의된 삼각형, 선분 등을 픽셀 단위로 변환하는 과정이다.
벡터 도형 (정점 좌표) → 어떤 픽셀을 켜야 할까? → Raster 이미지
이 과정에서:
- 삼각형 내부인지 판단 (Coverage Test)
- 픽셀별 색상 보간, 깊이값 계산
- 최종 픽셀에 색상 출력
🌏 render() 함수는 어디에 그리고 있을까?
render() 함수는 GPU가 실제로 그림을 그리는 Back Buffer에 내용을 출력한다.
function render() {
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(...);
}
✅ Back Buffer → Front Buffer로
- WebGL은 더블 버퍼링을 사용한다:
- Back Buffer: 그림 그리는 중
- Front Buffer: 사용자에게 보여지는 화면
- 그리기 완료 후 자동으로 swap되어 부드러운 화면 전환이 가능해진다.
깜빡임(flickering)을 방지하기 위한 핵심 기술이 바로 이 더블 버퍼링이다.
✅ resize 이벤트와 다시 그리기
브라우저 창이 바뀔 때는 canvas 크기와 viewport도 같이 바꿔줘야 한다. 이를 위해 resize 이벤트 리스너를 설정한다:
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
gl.viewport(0, 0, canvas.width, canvas.height);
render(); // 다시 그림
});
캔버스 크기 = 실제 렌더링 해상도
viewport = 그 중 어디에 그릴지를 결정
'컴퓨터과학 > 컴퓨터그래픽스' 카테고리의 다른 글
| [컴퓨터그래픽스] 3D 그래픽스에서의 좌표 변환: Local → World → View → Clip → Screen (0) | 2025.10.23 |
|---|---|
| [컴퓨터그래픽스] 3D 조명: Local/Global Illumination, Phong 반사 모델 (0) | 2025.10.23 |
| [컴퓨터그래픽스] Three.js를 사용해 3D 게임을 만들어보자! (0) | 2025.10.23 |
| [컴퓨터그래픽스] Shader를 이해하는 가장 쉬운 방법: 개념, 예시, 사용법까지! (2) | 2025.05.01 |