Skip to content

Latest commit

 

History

History
221 lines (132 loc) · 9.69 KB

WebGL - 01 - Intro.md

File metadata and controls

221 lines (132 loc) · 9.69 KB

WebGL - 01 - Intro

프로그래밍 일반

레이어(Layer, 계층)

복잡함을 해결하기 위한 전략 중의 하나

A계층은 직접 접하고 있는 B계층에 대해서만 알면 되고, C계층에 대해서는 알지도 못하며 교류하지도 않는다.

Interface, Protocol

상호작용(interaction)을 하기 위한 무엇. 계층간 상호작용을 할 수 있게 해주는 규약.

상대주의적 관점

아래의 관계에서 B는 상황에 따라 상대적으로 정보의 소비자이기도 하고 정보의 제공자이기도 하다.

  • A는 정보 제공자, B는 A가 제공하는 정보의 소비자
  • B는 정보 제공자, C는 B가 제공하는 정보의 소비자

따라서 (가)는 언제나 (나)이다. 라는 절대주의적 관점을 버리고 항상 상황에 따라 상대주의적으로 파악하는 것이 프로그래밍의 이해에 도움이 된다.

용어는 고유명사

일반적으로 통용되는 의미에 너무 구속되면 내용 이해에 방해가 되므로 프로그래밍 관련 용어는 아예 별개의 고유명사로 인식하는 것이 좋다.

  • domain(앞 뜰 - 문제 영역), table(탁자, 표 - 데이터베이스 테이블), ...

컴퓨터의 그래픽 처리 흐름

물리적 흐름

WebGL은 왜 빠른가?

사용자의 눈높이는 점점 높아지고, 디바이스의 사양은 (역설적으로?) 계속 낮아지고 있다.

  • 하드웨어 자체는 점점 좋아지지만, 사용자가 실제로 자주 사용하는 디바이스의 사양은 점점 낮아지고 있다.
    • PC > 스마트폰 > 스마트워치 > IoT 기기 > ...

빠른 그래픽 처리가 점점 더 많이 필요하다는 것이 WebGL을 쓰게 되는 주요인

그렇다면 WebGL은 왜 빠른가?

그래픽 처리 흐름

WebGL 사용 시 OS계층을 타지 않고 브라우저가 바로 OpenGL을 거쳐 GPU에서 처리하므로 더 빠르다.

GPU 병렬 처리

  • CPU : 고성능 but 적은 core 수(1, 2, 4)

  • GPU : 저성능 but 엄청 많은 core 수(수백만~수천만)

  • 픽셀이 백만개라면

    • CPU는 백만개의 픽셀을 빨리 돌면서 픽셀에 점을 찍고
    • GPU는 백만개가 각각 하나의 픽셀에 점을 찍는다.
  • 그냥 한 판 그리는 거면 몰라도 애니메이션, 조명 처리 등이 들어가면 GPU의 승리

병렬 프로그래밍

GPU가 병렬적으로 처리할 수 있으려면 백만개의 점을 찍는 과정이 서로 격리되어 독립적이어야 한다.

독립적

1 + 3을 계산하여 4를 얻고 5 + 7을 계산해서 12를 얻는다고 하자.

이 두 번의 덧셈 계산은 서로 아무런 영향을 주지 않는 독립적인 계산이다. 따라서 1번 코어에는 1+3을 계산시키고, 2번 코어에는 5+7을 계산시켜서 병렬적으로 처리할 수 있다.

WebGL의 그래픽처리가 바로 이런 경우에 해당한다. 삼각형의 세 꼭지점을 모두 반시계 방향으로 30도 회전하는 계산은, 세 꼭지점 각각에서의 계산이 서로에게 아무런 영향을 주지 않는 독립적인 계산이다.

(1 + 2) + 5 를 계산한다고 하자.

이 두 번의 덧셈 계산을 하려면 (1 + 2)가 반드시 먼저 선행해야 한다는 제약이 있다. 이런 상황에서는 1번 코어에 (1 + 2)를 계산시키고, 2번 코어에 + 5을 계산시켜서 병렬적으로 처리할 수 없다.

무상태

  • 어떤 하나의 상태를 여럿이 공유하고, 여럿 중의 하나가 그 상태를 변경할 수 있다면 서로 독립적일 수 없다.
  • 따라서 병렬 프로그래밍을 하려면 상태를 사용하지 않는 순수한 수학적 함수가 필요하다.
  • 순수한 수학적 함수를 프로그래밍의 언어로 표현하면 지역 변수, 인자만을 사용하는 함수를 말한다.

절반만 빨간색 CPU vs GPU

화면의 우측 절반만 빨간색으로 칠하는 작업을 CPU 방식과 GPU 방식으로 비교해보자.

CPU 방식

function
	for (y ~~~)
    	for (x ~~~)
    	    if (x > 50%)
				paint RED

위와 같이 CPU가 루프를 돌면서 각 픽셀에 대해 처리

GPU 방식

function
    if (x > 50%)
        paint RED    

위의 함수를 각각의 GPU 코어가 병렬적으로 자기 픽셀에 대해 1회 처리

CPU와 GPU의 의사소통

  • GPU는 그리기만 할 뿐 사용자와의 인터랙션, 이벤트 처리 등에 대해서는 전혀 모름

  • 이런 정보는 CPU가 접수해서 버스를 통해 GPU에 전달해야함

  • 프로그래밍 적으로는 CPU가 관장하는 Canvas에서 gl 컨텍스트를 가져오고 gl 컨텍스트를 활용하여 GPU에 전달

  • 전달 비용이 비싸므로 버스 한 번 태울때마다 가능한 최적화해서 많이 담고 전달 회수를 줄여야 함

용어 정리

파이프라인(Pipeline)

한 절차의 결과가 다른 절차의 입력이 되도록 미리 흐름이 정해져 있는 처리 방식

  • 파이프라인의 흐름 전체는 변경이 불가능하다.
    • 이에 반해 플로우(flow)는 정해진 절차를 변경할 수도 있는 경우를 의미한다.
  • 파이프라인의 흐름 자체는 변경할 수 없지만, 파이프라인을 형성하는 일부 절차에 대해서는 처리 방식에 개입할 수는 있다.
    • 디자인 패턴의 템플릿 메서드 패턴을 떠올려보자.

훅(Hook)

파이프라인을 형성하는 일부 절차의 처리 방식에 개입할 수 있는 지점 또는 수단

  • 템플릿 메서드 패턴에서 템플릿 클래스를 상속받는 쪽에서 구현하도록 abstract로 표시되어 있는 메서드가 hook에 해당한다.
  • GPU 파이프라인에서는 버텍스 셰이더(Vertex Shader)와 프래그먼트 셰이더(Fragment Shader)가 hook이다.
    • 프로그래머 입장에서는 버텍스 셰이더와 프래그먼트 셰이더만 마음대로 구성 가능하며, 나머지는 프로그래머가 손댈 수 없으며 그저 파이프라인을 따라 흘러갈 뿐

GPU 렌더링 파이프라인

  • 전체 흐름은 CPU -> BUS -> GPU -> 디스플레이
  • GPU 내의 렌더링 파이프라인
    • 버텍스 셰이더와 프래그먼트 셰이더만 프로그래머가 핸들링 가능(Hook)
    • 나머지 요소는 CPU에서 전달받은 데이터에 따라 주어진 고정적인 흐름에 따라 처리됨(Fixed)

버텍스(Vertex)

정점, 꼭지점, 모서리

래스터화(Rasterization)

실세계에서는 무한한 연속체로 되어 있는 기하학적 요소(직선, 곡선, 면, ...)에 대한 데이터를 유한한 픽셀에 쪼개서 담는 처리를 말하며, 래스터화 과정을 거치면 프래그먼트가 생성된다.

실세계의 수직선에서 0과 1을 잇는 선분을 생각해보자. 0과 1사이에는 0과 무한대 사이에 있는 것과 같은 개수의 무한한 점이 있다. 하지만 이 선분을 디스플레이 화면에 뿌릴 떄는 결국 디스플레이의 해상도에 따른 유한한 픽셀 갯수만큼의 데이터만 필요하다.

양자화(Quantization)

실세계에서는 연속적인 무한한 데이터를 쳐내서 불연속적인 유한한 데이터로 만드는 것

  • 소리를 mp3로 만들 때 가청 주파수 정도의 데이터만 취한다.

  • 움직이는 화면을 만들 때 가시 주파수 정도의 데이터만 취한다.

프래그먼트(Fragment)

래스터화의 결과로 나오는 픽셀 쪼가리(fragment) 단위의 정보

넓은 의미에서는 픽셀이라고 봐도 크게 틀리지는 않으나, 컬러 버퍼에 저장된 픽셀을 수정하는데 필요한 데이터를 총칭한다고 보는 것이 더 정확하다.

그래픽 처리 전략

대부분의 그래픽 처리에서 공통적으로 사용되는 기본 전략은 선 영역계산 - 후 색채우기

선 영역 계산 - Reflow - Vertex Shader

  • 색을 칠할 영역 또는 공간 계산
  • 기하 정보(Geometry)에 대한 연산이 필요하므로 CPU에 많은 부담
    • DOM 최적화의 주된 방법 중의 하나도 Reflow 최소화
  • WebGL에서는 버텍스 셰이더가 Reflow 역할을 담당하며, CPU가 아닌 GPU에서 계산하므로 CPU 부담을 줄일 수 있고 결국 성능 향상으로 이어진다.

후 색채우기 - Repaint - Fragment Shader

  • 계산된 영역 또는 공간 내에 색 채우기
  • 단순히 색을 채우는 것으로 Reflow에 비해 연산 부담이 덜하다.
  • 화면 요소 자체에는 아무런 변화가 없더라도 마우스 이동 만으로도 Repaint가 발생
  • 따라서 Repaint는 최소화 할 여지도 많지 않으며, Repaint 최소화를 통한 성능 향상 효과도 크지 않다.
  • WebGL에서는 프래그먼트 셰이더가 Repaint 역할 담당

영역 계산 방식

상대값 기준

  • 어떤 기준 요소에 대한 상대적인 값으로 영역 계산
    • width=50%로 하면 어떤 디바이스에서도 폭 50%로 일관되게 표현 가능
  • adaptive, reactive 하지만 계산 성능이 좀 낮음

절대값 기준

  • 절대적인 값으로 영역 계산
    • x=600 y=400로 하면 디바이스에 따라 화면에 보일 수도 안 보일 수도 있음
  • 이론 상으로는 계산 성능이 좋지만, 실무적으로는 절대값 기준으로만 계산하는 경우는 거의 없고 상대값 기준 계산과 함께 사용되므로 계산 성능 상의 장점이 많이 희석된다.

용어 짝짓기

CPU 프로그래밍 GPU 프로그래밍
프로그램 셰이더(Shader)
이미지 텍스쳐(Texture)
배열 버퍼(buffer)