OpenGL -> 3D 공간에 존재
화면/윈도우 창 -> 2차원 픽셀 배열
==> 모든 3D 좌표를 화면에 맞게 2D 픽셀로 변환하는 작업이 큰 부분 차지
"그래픽 파이프라인(graphics pipeline)" = 3D좌표를 2D 좌표로 변환하는 작업
1. 3D 좌표를 2D 좌표로 변환
2. 2D 좌표를 실제 색이 들어간 픽셀로 변환
- 2D 좌표 = 2D 공간에 있는 한 점의 위치를 매우 정확하게 나타냄
- 2D 픽셀 = 화면이나 윈도우 창의 해상도에 의해 제한되는 한 점의 근사치
< 그래픽 파이프라인 >
입력 = 3D 좌표
-> 입력을 화면에 색이 입혀진 2D 픽셀로 변환
여러 단계로 나뉘며 각 단계는 그 전 단게의 결과를 입력으로 받게 된다. 모든 단계는 특정한 기능을 갖고 있으며 쉽게 병렬로 실행될 수 있다.
gpu위에 작은 프로그램들을 실행시킴(작은 프로그램 = shaders)
shaders는 OpenGL Shading Language(GLSL)로 작성됨
vertex data[] -> vertex shader -> shape assembly -> geometry shader -> rasterization -> fragment shader -> tests and blending
vertex data -> 정점 데이터(정점들의 집합), 기본적으로 정점은 3D좌표에 대한 데이터의 집합, 이 정점의 데이터는 정점 속성(vertex attributes)을 사용하여 나타낸다,.
간단하게, 각 정점은 3D 위치와 컬러 값을 가진다고 가정
★vertex shader -> 하나의 정점을 입력으로 받음, 주 목적은 3D좌표를 다른 3D좌표로 변환하는 것, VERTEX 속성에 대한 기본적인 처리를 할 수 있음
primitive assembly -> primitive를 구성하고 primitive 도형의 모든 점들을 조립하는 vertex 쉐이더로부터 입력 값으로 모든 정점들을 받음, 결과값은 geometry shader로 전달됨.
geometry shader -> 입력값으로 정점들의 집합을 받는다, 이 정점들의 집합은 primitive를 구성하고 새로운 정점을 방출하여 새로운 primitive를 형성 , 다른 도형으로 변환될 수 있는 정점들
rasterization -> 결과 pirmitive를 최종화면의 적절한 픽셀과 mapping. 그 결과로 fragment shader에서 사용할 fragment가 나옴, fragment shader실행 전에 clipping이 수행 됨
clipping -> 성능 증가를 위해 사용, 뷰 밖에 있는 모든 fragment 버림
fragment -> 하나의 픽셀을 렌더링하기위해 필요한 모든 데이터
★fragment shader -> 주 목적은 픽셀의 최종 컬러를 결정, 일반적으로 OpenGL의 모든 고급효과들이 발생하느 단계. fragment shader는 3D scene에 대한 데이터를 갖고 있음(해당 데이터는 최종 칙셀 컬러(광원, 그림자, 빛의 색 등)를 계산하기 위해 사용될 수)
alpha test & blending -> fragment의 depth(stencil) value를 체크, 최종 fragment가 다른 obj보다 앞/뒤에 있는지 확인하고 다른 obj보다 뒤에 있는 fragment는 버린다. 이 단계에서 alpha값(obj의 투명도)을 확인하고 그에 맞추어 다른 obj와 blend한다.
-> 그래서 fragment shader에서 픽셀 컬러가 계산되었더라도 최종 픽셀 컬러는 여러 개의 삼각형을 렌더링할 때 완전다른 색이 될 수 있음
※ vertex shader와 fragment shader는 직접 작성해야함 (gpu에 디폴트가 존재x)
#입력
vertex data -> (x, y, z) 3D 좌표
* 3D 좌표가 모든 3개의 축(x, y, z)에서 값이 모두 -1.0 과 1.0 사이에 있어야 한다.
(normalized device coordinates, 위 범위 밖은 보이지 않음)
#vertex buffer objects(VBO)를 통해 메모리 관리
-> VBO - 많은 양의 정점들을 GPU 메모리 상에 저장할 수 잇음. 이러한 버퍼객체를 사용하면 한 번에 정점 데이터를 보내지 않아도 대량의 데이터를 한꺼번에 그래픽 카드로 전송할 수 ㅇ있음, gpu에 메모리가 할당되기만 하면 vertex shader는 빠르게 정점들에 접근할 수 있음
glGenBuffers = 버퍼 ID생성
glBindBuffer = (버퍼 유형, obj), 버퍼 유형이 다른 여러가지 버퍼를 바인딩
바인딩 시점부터 호출하는 모든 버퍼는 현재 바인딩 된 버퍼를 사용하게 됨
glBufferData = (복사하여 넣을 버퍼 유형, 버퍼에 저장할 데이터 크기(바이트 단위), 우리가 보낼 실제 데이터, 그래픽 카드가 주어진 데이터를 관리하는 방법), 미리 정의된 정점 데이터를 버퍼 메모리에 복사, 사용자가 정의한 데이터를 현재 바인딩 된 버퍼에 복사하는 기능
#정점 속성 연결(Linking Vertex Attributes)
vertex shader는 모든 입력들을 정점 속성의 형식으로 지정할 수 있도록 해준다. 어떤 정점 속성과 맞는지 직접 지정해야 한다. -> 렌더링 하기 전에 OpenGL이 정점 데이터를 어떻게 해석해야하는지를 우리가 지정해준다는 의미
glVertexAttributePointer = (vertex 속성, 속성의 크기, 데이터의 타입, 데이터를 정규화할 것인지 지정, stride(공백), 버퍼에서 시작하는 위치의 offset)
#Vertex Array Object (VAO)
VBO와 같이 바인딩 될 수 잇으며 그 이후의 vertex 속성 호출은 VAO내에 저장된다.
vertex 속성 포인터 구성할 때 오직 한 번만 호출하면되고, obj를 그릴때마다 해당 VAO를 바인당 하면 됨
-> 서로 다른 vertex 데이터와 속성들을 다른 VAO를 바인딩함으로써 손쉽게 교체할 수 있다.
설정한 모든 상태는 VAO 내부에 저장 된다.
#Element Buffer Objects(EBO)
VBO와 같은 버퍼
OpenGL이 어떠한 정점들을 그려야 할 지 결정할 수 있는 인덱스들을 저장(index drawing)
고유한 정점들 지정하고 사각형을 그릴 정점들의 인덱스 지정
삼각형 두 개를 합쳐 사각형을 만들 때 겹치는 정점 위치는 저장하지 않아도 된다.
'공부일지 > OpenGL' 카테고리의 다른 글
OpenGL - 3 (Shaders) (0) | 2020.03.07 |
---|---|
OpenGL -1 (window생성) (0) | 2020.03.05 |
openGL (0) | 2020.02.19 |