Table of Contents
기초: 3차원 공간의 대표
단일 픽셀이 그려지기 전에, 3D 엔진은 공간에 개체를 설명하는 수학 언어가 있어야합니다. 코어는 vectors] (위치, 방향, 또는 색상을 나타내는 세 가지 구성 요소 튜플) 및 matrices (4×4 배열을 인코딩 변환). C에서, 이것은 일반적으로 간단한 구조로 정의됩니다.
- 포인트와 벡터에 대한.
- 열매 순서에 저장 된 변환 매트릭스에 대한.
모든 객체는 triangles로 구성되어 있습니다. 삼각형은 위치와 선택적으로 정상과 색상으로 세 가지 vertices에 의해 정의되며, 연속 배열(예: ]로 계산하여 구조별 수천의 얼굴을 처리할 때 캐시 효율을 향상시킵니다.
그래픽 파이프 : Vertices에서 Pixels로
그래픽 파이프라인은 3D 장면 데이터를 2D 이미지로 변환하는 단계의 순서입니다. 기본 소프트웨어 렌더링 엔진에서 수동으로 각 단계를 실행합니다. 주요 단계는 다음과 같습니다.
- Vertex Processing - 모델, 전망 및 투영 변환을 적용한다.
- Rasterization – 변환 변환된 삼각형으로 조각 (주파 픽셀).
- Shading - 조명과 재료에 따라 각 조각의 색상을 계산합니다.
- Output Merging – 심도 테스트를 포함한 프레임 버퍼와 블렌딩 조각.
하드웨어 가속 엔진 (OpenGL, Vulkan 또는 DirectX 사용)은 GPU에서 이러한 단계를 수행하지만 소프트웨어 경로에 대한 이해는 GPU가 후드에서 작동하는 방법을 깊이 통찰력을 제공합니다.
Vertex 처리 및 변환
모든 vertex는 model space (현지 좌표는 객체와 관계)에서 시작합니다. 세상에서 위치를 위해, 당신은 ]model matrix를 적용하여 번역, 회전 및 스케일링을 인코딩합니다. 그런 다음 view matrix는 카메라-relativeLT(FLT:3)으로 세계 좌표를 변환합니다. ]:7FLT:7]:7FLT:7FLT:7]
C에서, 변환 기능은 다음과 같습니다:
- – 정체성 매트릭스를 반환합니다.
- – 번역 매트릭스 구축.
- – X 축의 회전.
- - 4개의 원적 벡터(인화 좌표)에 의해 4×4 매트릭스를 다룹니다.
모든 vertices를 통해 소프트웨어에 해당되는 베텍스 쉐더는 각각 매트릭스를 결합하여 변형된 베텍스 버퍼에 결과를 저장합니다.
투상: 관점 versus Orthographic
투사 제어는 화면에 표시되는 방법. Perspective projection]는 디턴 객체가 더 작을 수 있으며 현실주의를 창출합니다. 그것의 모체는 볼, 측면 비율, 가까이 및 멀리 클립 비행기에서 내장됩니다. 고전적인 수식은 z (매트릭스 멀티 복제 후) x 및 y 구성 요소를 디바이딩합니다. C에서 투사 매트릭스를 한 번 컴파일하고 재사용하십시오.
- – 표준 관점 매트릭스를 반환합니다.
Orthographic projection은 병렬한 선을 보존하고 UI 또는 CAD 도구에 사용되는 단순하다. 그것은 시각 배당을 포함하지 않습니다.
Rasterization: 채우는 삼각형
투상 후, 2D 스크린 좌표 (픽셀 위치와 같은) 및 깊이 값 (z)가 있습니다. Rasterization는 정수 픽셀 좌표를 포함하는 파편으로 각 삼각형을 깰. 고전적인 알고리즘은 ]scanline 변환:
- 삼각형의 세 가지 vertices를 y 좌표로 정렬하십시오.
- 왼쪽과 오른쪽 가장자리를 걷고, 각 스캔에 대한 X 경계를 계산합니다.
- 수평선의 각 화소를 위해, 삼각형의 가로를 가로로 옮기는 조각의 깊이를 산출하십시오.
- depth test: 심도 버퍼에서 값이 이미 있는 파편의 z를 비교합니다. 더 가까이에, 깊이 버퍼를 업데이트하고 파편의 색상을 계산하면 됩니다.
C에서 효율적으로 가장자리 산책 알고리즘을 구현하는 것은 고정 포인트 라이터의 고정 지점을 방지하기 위해 고정 지점의 주의적 인 사용을 요구합니다. 많은 취미 엔진은 brute-force 접근 (지하 상자에서 모든 픽셀 검사)과 나중에 가장자리 방정식으로 최적화합니다.
, 빛
간단한 평면 쉐이드 엔진은 얼굴 정상과 단일 광원에서 계산 된 삼각형 당 단일 색상을 사용합니다. [FLT : 0] Lambertian 모델[FLT : 1]은 디퓨즈 강도를 제공합니다 : [FLT : 9]]. C에서 두 삼각형 가장자리의 교차 제품으로 정상을 계산합니다 (세계 공간에 vertices를 변형 한 후), 다음 삼각형의 기본 색상으로 가벼운 강도를 곱합니다.
깊이를 추가하려면 Gouraud shading (vertex 정상, 파편에 걸쳐 인터폴화) 또는 Phong shading] (per-pixel normal). 후자는 세계 위치와 정상을 가로 질러 파편 당 점화를 계산해야하지만 극적으로 더 나은 결과를 얻을 수 있습니다.
C에서 엔진 구축: 실제 단계
최소 소프트웨어 3D 엔진을 스크래치에서 건설하는 것을 해보자. 목표는 640×480 픽셀 창에 주위와 확산 조명과 회전 큐브를 렌더링하는 것입니다.
단계 1 – 픽셀 버퍼 설정
프레임과 깊이에 대한 메모리 버퍼 정의: 과 ]. 프레임 버퍼를 검은 색으로 지우고 깊이 버퍼 1.0 (far plane) 각 프레임.
단계 2 – 정의 장면 데이터
큐브의 경우, 6 개의 얼굴 (12 삼각형)은 12 × 3 = 36 vertices가 필요합니다. 위치 (3 플로트) 및 색상 (3 플로트 RGB 용)로 구조의 배열에 저장하십시오. 8 개의 독특한 큐브 코너와 6 개의 얼굴 색상을 미리 정의하십시오. 도포 vertices를 피하기 위해 인덱스 버퍼를 사용합니다.
단계 3 – 변환 파이프라인
각 프레임은 각 (예 : 회전 (시간))에서 모델 매트릭스를 계산합니다. 이 점에서 원하는 고정 카메라에서 볼 매트릭스, 투영 매트릭스. 단일 MVP 매트릭스에 결합하십시오. . ]로 곱하여 모든 버텍스를 변환합니다. 그런 다음 원근법 배당 (divide x,y,z by w)을 실행하여 정상화 장치 (LT1)를 갖는 (NUMXF)를 설정합니다. [FLT : 1F] : 14F]의 심도 측정을 위해 (NUF)를 설정합니다.
단계 4 – Rasterize 및 Shade
각 삼각형의 경우, 스캔 방법을 사용합니다. 걷기 픽셀 동안 깊이를 가로질러 세계 공간 위치 (Phong) 또는 버텍스 정상 (Gouraud)와 같은 per-vertex 속성을 인터포레이트합니다. Lambertian diffuse 방정식을 적용합니다. 심도 테스트 패스가 전달되면 프레임 버퍼에 최종 색상을 작성하십시오.
단계 5 – 디스플레이
SDL (Simple DirectMedia Layer) 또는 유사한 라이브러리를 사용하여 창을 만들고 프레임 버퍼를 밝히십시오. 예를 들어 SDL2 : , , ] ]]], ]] 및 각 프레임.
이 소프트웨어 경로는 CPU에서 실행, 그래서 성능은 프레임 당 수천 삼각형에 제한됩니다. 일단 편안하면, 당신은 OpenGL을 가진 래스터화 층을 교체 할 수 있습니다, GPU에 무거운 작업을 오프로드하면서 C의 변환과 장면 논리를 유지하면서.
당신의 엔진 최적화
기본 엔진은 느립니다. 여러 가지 최적화는 실시간 성능에 필수적입니다.
- Back-face culling: 카메라에서 정상적인 지점을 건너 삼각형을 건너. 프로젝트 삼각형의 서명 영역을 계산 (2D에서) 또는 보기 방향과 얼굴 정상의 도트 제품을 확인.
- Frustum culling: 보기 frustum의 6개의 비행기에 대한 객체의 경계 상자를 테스트합니다. 완전히 외부가 전체 객체를 건너면 됩니다.
- Fixed-point arithmetic: 꽉 래스터화 루프에서 정수 수학과 플로팅 포인트 작업을 대체합니다. 많은 엔진 빌더는 스캔 인터폴레이션에 대한 16.16 고정 지점을 사용합니다.
- Pre-transform cache: 한 번 메쉬의 모든 vertices를 변환하여 동일한 vertex를 여러 번 변환하지 않고 인덱스를 사용합니다.
- 블록 프레임 버퍼 쓰기: 메모리-주문에 있는 픽셀 쓰기 (왼쪽 오른쪽, 상단-bottom) 캐쉬를 최대화하기 위해.
이 기술은 온건한 복잡성의 장면을 위해 3~5fps에서 60fps로 소프트웨어 렌더링기를 밀어 줄 수 있습니다 (예를들면, 약간 백 삼각형).
엔진을 확장
단단한 기초가 존재하는 경우, 당신은 incrementally 특징을 추가할 수 있습니다:
- Texture 매핑: 저장 2D 이미지와 삼각형의 UV 좌표를 인터포레이트. 부드러운 결과를 위해 bilinear 필터링을 구현합니다.
- Advanced shading: specular Highlightss (Blinn-Phong), 주변의 망각, 또는 그림자지도를 추가합니다.
- Scene 관리: 는 물체가 눈에 보이는 것을 결정하기 위해 옥세 또는 BSP 트리를 사용합니다.
- 사용자 상호 작용: 카메라 또는 물건 개체를 궤도에 키보드와 마우스 입력을 핸들.
- Pipeline 요약:] 은 그늘 시스템을 설계: 기능 포인터로서 vertex 및 파편 기능을 정의하고, 재 컴파일 없이 유연한 렌더링을 가능하게 합니다.
자원 및 더 읽기
이해를 깊게하려면이 엔진을 영감을 얻은 고전적인 텍스트 및 온라인 자습서를 살펴보십시오.
- Scratchapixel – 레이 트랩, 래스터화, 수학의 심층적인 설명.
- LearnOpenGL – 현대 OpenGL 튜토리얼; “Hello Triangle” 챕터로 시작.
- Wikipedia: 3D Projection – 원근법과 정형적 매트릭스 뒤에 공식 수학.
C의 3D 엔진을 구축하는 것은 그래픽 프로그래머를위한 통행의 rite입니다. 그것은 당신이 효율적인 코드를 작성하는 방법뿐만 아니라 성능 크리티컬 시스템을 구성하는 세 가지 차원에서 생각하는 방법을 가르칩니다. 단일 회전 큐브로 시작하면 더 삼각형, 질감, 그리고 마지막으로 GPU로 떨어져 손을 추가합니다. Raw C에서 완전히 기능적인 엔진으로 여행은 화면의 모든 픽셀 뒤에 마법을 나타냅니다.