티스토리 뷰
이 장에서는 Rendering Pipeline(RP)의 개요와 RP에서 Shader의 활용을 알아본다.
개요 단계의 내용이고 매우매우 자세한 내용은 없다.
RP의 하나 하나 단계는 그 자체만으로도 매우 깊은 단계이기 때문에 너무 자세한 이야기는 생략하도록 한다.
1. RP의 개념
1.1. RP의 정의
렌더링 파이프라인은 3D 모델을 스크린에 render 하기 위한 stage들의 모음이다.
이 중 4개의 단계는 ‘Shader’를 통해 프로그래밍 할 수 있다.
이 Shader는 보통 GLSL/HLSL 등의 언어를 통해 작성된다.
그렇다면 이 RP가 어떤 stage들로 구성되어 있는지 알아보자.
1.2. RP의 Stage
RP는 다음과 같이 9개의 stage로 구성되어있다.
정리해보면 다음 순서로 각각의 역할을 수행한다. 앞에 [Programmable]을 붙인 부분은 사용자가 제어 가능한 부분이다.
- Vertex Specification: render할 이미지의 vertex 정보를 작성하고 저장.
- [Programmable]Vertex Shader: vertex에 대한 정보를 수정할 수 있는 부분.
- [Programmable]Tessellation Shader: vertex data들이 작은 primitive들로 세분화되는 단계.
- [Programmable]Geometry Shader: primitive를 processing 하는 단계. 0개 이상의 primitive들을 생성할 수 있다.
- Vertex Post-Processing: clip space 좌표를 기반으로 vertex의 좌표계를 변환.
- Primitive Assembly: 각 vertex들을 연결하여 primitive를 만드는 단계.
- Rasterization: primitive를 2차원의 각 픽셀에 대응시키는 단계.
- [Programmable]Fragment Shader: 프래그먼트의 정보를 바탕으로 색상을 조작하는 단계.
- Per-Sample Operations: 유저가 지정한 여러 Test들을 수행하는 단계.
각 단계에 대해서는 아래에서 조금씩 더 자세하게 알아보자.
1.2.1. Vertex Specification
Vertex를 정의하고 저장하는 과정이다.
기술적으로는 Vertex stream을 만들어 vertex shader에 넘기는 과정이다.
이 과정에서 VAO/VBO라는 OpenGL Object를 이용하여 정보를 넘기게 된다.
깊은 글은 아니지만 VAO와 VBO는 해당 개념을 잘 이해해야 한다.
그러므로 간단하게나마 짚고 넘어가겠다.
VBO
이 specification 과정은 vertex를 정의하고 저장하는 과정이라 했다.
그렇다면 이 과정에서 필요할 정보들을 생각해보면 다음과 같다.
- vertex data 그 자체: 각 vertex 별 position, uv(텍스쳐매핑), tangent 등의 정보.
- vertex data를 어떻게 해석할 것인지에 대한 정보.
우선 VBO는 Vertex Buffer Object로서 vertex data 그 자체에 대한 정보를 저장한다.
예를 들어 다음과 같이 우리가 정의해볼 수도 있다.(xyzxyzxyz 순서)
float vertices1[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
혹은 uv를 포함하여 다음과 같이 정의할 수도 있다.(xyzuvxyzuvxyzuv 순서)
float vertices2[] = {
-0.5f, -0.5f, 0.0f, 0.2f, 0.5f,
0.5f, -0.5f, 0.0f, 0.1f, 0.4f,
0.0f, 0.5f, 0.0f 0.3f, 0.7f,
};
이런 VBO는 그 해석 방법이 없으므로 이것으로는 아무 것도 그릴 수 없다.
몇 번째가 x고 몇 번째가 uv인가? uv 정보가 있긴 한가?
즉 배열만 보고서는 어떤 속성이 어디 있는지 알 수 없다. 단순한 raw data의 나열일 뿐이다.
따라서 Vertex의 속성 정보를 제공하는 ‘Vertex Attribute’ 의 선언이 필요하다.
Vertex Attribute
vertex attribute는 vertex의 속성으로서 xyz, uv, normal과 같은 vertex의 정보들을 나타낸다.
이 정보를 따로 선언해주면 opengl은 vbo를 해석할 수 있는 방법을 알게 된다.
예를 들어 아까의 vertex를 생각해보자.
float vertices2[] = {
-0.5f, -0.5f, 0.0f, 0.2f, 0.5f,
0.5f, -0.5f, 0.0f, 0.1f, 0.4f,
0.0f, 0.5f, 0.0f 0.3f, 0.7f,
};
이 정보는 생각해보면 아래와 같이 해석해야 할 것이다.
이 때 attribute는 다음과 같다.
- xyz attribute
- uv attribute
또한, 각 attribute 별로 필요한 정보는 다음과 같다.
- attribute id(location)
- attribute의 element 개수
- attribute의 type
- attribute의 stride: 얼만큼의 size 뒤에 동일한 attribute가 나오는가의 보폭
위와 같은 경우 다음과 같이 코드를 작성하여 Attribute를 선언할 수 있다.
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
0번 id로 크기가 3인 xyz attribute를, 1번 id로 크기가 2인 uv attribute를 만들고 각각을 활성화했다.
이렇게 되면 이제 opengl이 위의 VBO를 해석할 방법을 알게 될 것이고, 이후의 RP 단계에서 이를 사용할 수 있을 것이다.
API에 대한 설명은 이번 문서의 내용을 다소 벗어나므로 아래 문서를 참고해주면 고마울 것 같습니다..
https://registry.khronos.org/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml
VAO
우선 위와 같이 VBO와 attribute만 있어도 렌더링은 할 수 있다.
하지만 조금 raw한 면이 있다.
매 번 VBO와 attribute를 각각 설정해줘야 하고 상태로서 관리하는 것이 불가능하다.
따라서 이것을 상태로서 이용할 수 있도록 VAO가 존재한다.
VAO는 Vertex Array Object로서 Vertex Attribute와 여러 VBO들을 담을 수 있는 Object다.
다음과 같이 Attribute에 대한 정보와 여러 VBO들을 Binding하는 정보들을 들고 있다.
직접적인 사용법은 다음 글에서 다루기로 하며 우선은 VAO에 대한 설명은 이 정도에서 마친다.
1.2.2. Vertex Shader(Programmable)
Vertex들을 조작하는 부분.
주로 world 변환, view 변환, projection 변환 처리 등을 진행한다.
유니티 shader에서 사용했을 때는 스케일을 키워 외곽선을 만드는 패스를 그릴 때 사용한 적도 있었다.
1.2.3. Tesselation[Programmable]
data를 small primitives로 나누는 과정이다.
opengl 4.0 이상에서 등장한 최신 shader type.
상당히 higher level의 detail을 다룬다.
정확한 정의 자체는 ‘patch로 제공된 primitive를 더 작은 primitive로 쪼개는 것’을 의미한다.
(여기서 patch는 고차 primitive를 의미한다.)
여러 detail이 있지만 우선은 이 역할 정도로만 알아두고 넘어가자.
1.2.4. Geometry Shader[Programmable]
primitive를 processing할 수 있는 shader.
새로운 primitive 형태로 변환하는 등의 작업을 수행할 수 있다.
1.2.5. Vertex Post-Processing
Transform Feedback
- 이전 stage들의 결과가 buffer에 저장된다.
Clipping
- 보이지 않는 Primitive들을 삭제해버림.(볼 필요 없는 애들은 필요 없으니까)
- vertex의 좌표계가 clipspace에서 window space로 변환됨.
1.2.6. Primitive-Assembly
vertex stream을 받아서 primitive들의 sequence로 조직하는 과정.
1.2.7. Rasterization
- Primitive들을 Fragment들로 전환한다.
- pixel에 맞는 형태로 변경.
- 보간을 사용.
1.2.8. Fragment Shader
- 각 fragment들을 다루는 shader 영역
- 필수는 아니지만 보통 사용한다.
- depth나 stencil 데이터 등이 필요할 때는 예외
- 가장 중요한 결과는 픽셀의 색깔이다.
- OpenGL에서 가장 간단한 형태는 Vertex Shader와 Fragment Shader만을 가진 형태.
1.2.9. Per-Sample Operation
각종 test들의 모음으로서 scissor test / stencil test / depth test 등이 이 단계에서 수행된다.
Refs
매우 많이 참고한 매우 좋은 글: https://kyoungwhankim.github.io/ko/blog/opengl_triangle1/
https://www.khronos.org/opengl/wiki/vertex_Specification
https://github.com/rlatkddn212/opengl-graphics-pipeline?tab=readme-ov-file
https://velog.io/@aqusta/OpenGL-파이프라인
https://learn.microsoft.com/en-us/windows/uwp/graphics-concepts/geometry-shader-stage--gs-
'그래픽스' 카테고리의 다른 글
[그래픽스] OpenGL Uniform Variables 선언과 이용 (0) | 2025.02.15 |
---|---|
[그래픽스]Hello Triangle - OpenGL에서 삼각형 띄워보기 (0) | 2025.02.12 |
[그래픽스] Hello Window - GLEW/GLFW 이용하여 창 띄우기 (0) | 2025.02.06 |
[그래픽스] OpenGL과 GLEW/GLFW (0) | 2025.02.03 |
[그래픽스] C++에서 OpenGL(GLEW/GLFW) 개발 환경 구축 (0) | 2025.02.01 |
- Total
- Today
- Yesterday
- CS
- NLP
- 순환 신경망
- Neural Network
- CNN
- 컴퓨터과학
- 연속 신호
- 매트랩 함수
- 컴퓨터 과학
- 머신러닝
- 영상구조
- Logistic Regression
- 영상처리
- 사진구조
- Andrew ng
- 이미지처리
- 신경망
- gradient descent
- RGB이미지
- 매트랩
- 밑바닥부터 시작하는 딥러닝
- 자연어 처리
- 인덱스 이미지
- 딥러닝
- rnn
- ML
- 이미지
- 신호 및 시스템
- 이산 신호
- 머신 러닝
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |