Graphics Programming

OpenGL 4.5 정리 본문

Season 1/OpenGL

OpenGL 4.5 정리

minseoklee 2015. 8. 22. 21:22

클리핑 범위

-1 <= x <= 1

-1 <= y <= 1

0 <= z <= 1


좌표계: 오른손 좌표계(모니터의 오른쪽이 x축, 위쪽이 y축, 모니터에서 나에게 오는 방향이 z축)


필요한 라이브러리

glut, glfw, freeglut 등 - 윈도우(창) 관련 라이브러리

glew - OpenGL 최신 기능 사용시 필요 (비주얼 스튜디오만 설치하면 1.x ~ 2.x의 API만 이용 가능)

glLoadGen 쓸 것. glew를 쓰면 코어 프로필을 못 쓴다.

freeimage - 텍스처 이미지 로딩


텍스처 좌표



레퍼런스: https://www.opengl.org/sdk/docs/man4/



OpenGL 4.5 Core Profile(https://www.opengl.org/registry/doc/glspec45.core.pdf) 요약


표지: 렌더링 파이프라인


목차

1. 개요

2. OpenGL 기초

3. Dataflow 모델

4. Event 모델

5. Shared Object와 Multiple Context

6. Buffer Object

7. Program과 Shader

8. Texture와 Sampler

9. Framebuffer와 Framebuffer Object

10. Vertex Specification과 Drawing Command

11. Programmable Vertex Processing

12. ?
13. Fixed-Function Vertex Post-Processing

14. Fixed-Function Primitive Assembly와 Rasterization

15. Programmable Fragment Processing

16.

17. Writing Fragments and Samples to the Framebuffer

18. Reading and Copying Pixels

19. Compute Shaders

20. Debug Output

21. Special Functions

22. Context State Queries

23. State Tables

부록 A ~ I


1. 개요

마이크로소프트 윈도우즈의 OpenGL 바인딩은 WGL API이다. MSDN에 명세가 있지만 완전하지 않다.


2. OpenGL 기초

- OpenGL(이하 GL)은 GPU 메모리상 데이터 처리, 프레임버퍼에 렌더링하기, 프레임버퍼에 저장된 값 읽어오기만 담당. 다른 입출력 장치는 지원하지 않는다. 이에 대해서는 다른 라이브러리를 활용할 것.

 

- GL은 primitive를 그리며 이 primitive는 다양한 셰이더 프로그램과 고정 기능을 거쳐 처리된다. primitive는 point, line segement, patch, polygon을 뜻한다.

 

- primitive는 하나 이상의 정점(vertex) 모음이다. vertex는 point, line segement의 끝점, polygon의 모서리를 표현한다. vertex에는 위치 좌표, 색깔, 법선, 텍스처 좌표 등이 연관된다. 각각의 정점은 독립적으로, 또 순서대로 처리된다. 예외: primitive를 나타내는 정점 집합은 특정 영역에 들어맞도록 clip 되어야 한다. 이 경우 정점 데이터가 수정/추가될 수 있다.

 

- GL 명령은 순서대로 처리되며, 한 명령이 완전히 처리된 후에야 다음 명령을 시작한다. 따라서 두 그리기 명령을 연이어 실행할 경우 처음 primitive를 framebuffer에 완전히 그린 후에야 다음 primitive를 그리기 시작한다. 또한 query와 pixel read 명령을 실행할 경우 이전에 지시한 모든 GL 명령을 완료한 상태를 반환한다. 요약하면, GL 상태나 framebuffer에 관한 GL 명령은 그 후의 명령이 실행되기 전에 반드시 완료된다.

 

- 명령 호출시 데이터 바인딩이 일어난다. 즉 GL 명령에 넘겨진 데이터는 그 명령을 호출할 때 따로 저장되며, 따라서 해당 데이터가 포인터라 할 지라도 나중에 그 포인터가 가리키는 값을 수정하는 것은 GL에 영향을 주지 않는다.


- GL 명령을 클라이언트-서버 모델로 볼 수 있다. 프로그램(클라이언트)는 명령을 요청하고, GL(서버)는 그 명령을 해석해 처리한다. 서버는 많은 GL 컨텍스트(현재 GL 상태와 객체를 캡슐화한 것)들을 가질 수 있다. 클라이언트는 이 중 하나의 컨텍스트를 선택할 수 있다.


- framebuffer는 종류가 2개다. 윈도우 시스템이 제공하는 framebuffer는 한 컨텍스트가 활성화될 때 그 컨텍스트와 연관된다. default framebuffer라 칭한다. 애플리케이션에서 framebuffer를 자체 생성할 수도 있는데 이는 framebuffer object라 칭한다. 한 컨텍스트를 두 framebuffer와 연결하여 각각 읽기와 그리기 작업에 쓸 수도 있다. default framebuffer와 framebuffer object는 그 상태를 구성하고 관리하는 방법 자체에서 차이가 난다.


- default framebuffer에 대한 GL 명령의 결과는 전적으로 윈도우 시스템이 통제한다. 따라서 GL 컨텍스트를 초기화하거나 default framebuffer를 구성하는 GL 명령은 없다. 또한 framebuffer 내용을 물리적 장치에 출력하는 작업(감마 교정 등의 변환 포함)도 GL이 처리하지 않는다. default framebuffer의 할당과 구성은 [1. 개요]에서 언급한 WGL 같은 API의 몫이다.


- GL 컨텍스트의 할당과 초기화도 WGL 같은 API를 통해 이루어진다. GL 컨텍스트들은 서로 다른 default framebuffer에 연결될 수 있으며 몇 가지 컨텍스트 상태는 이 연결을 수행할 때 결정된다.


- default framebuffer 없이 GL 컨텍스트를 사용할 수 있다. 이 경우 framebuffer object가 모든 렌더링을 담당한다. offscreen rendering이 필요한 애플리케이션에 유용하다.


- 제공된 상태 값의 타입이 그 상태의 타입과 다를 때 변환 규약.

  - 진위값: 정수 0 또는 실수는 FALSE, 0이 아닌 정수는 TRUE로 변환

  - 정수 또는 열거형: FALSE와 TRUE는 각각 0과 1. 실수는 반올림. 결과값이 너무 커서 내부 상태 변수로 표현할 수 없을 경우, 결과를 알 수 없음.

  - 실수: FALSE와 TRUE는 각각 0.0과 1.0. 정수는 실수로. 정규화 여부는 명령마다 다름.

  - 배열: 위의 규칙들이 각각의 원소에 대해 적용됨.

  * 어떤 명령들은 추가적인 변환 규칙이 적용될 수 있음. 레퍼런스를 참고할 것.

  * 상태를 설정하는 명령들에서 값의 검정은 일반적으로 값 변환 후에 수행됨.


- query 명령들(Get으로 시작하는 것들)은 GL 상태값을 반환한다.


- GL은 수행능력 저하를 방지하기 위해 극히 일부의 오류만 감지한다. 오류 정보를 얻으려면 enum GetError( void ); 명령을 사용한다. 오류마다 숫자 부호가 부여되어 있다. 오류가 감지되면 플래그가 설정되고 그 부호는 기록된다. 플래그가 설정 상태인 한, 이후에 다른 오류가 발생해도 이 부호는 바뀌지 않는다. GetError을 호출하면 부호를 반환하고 플래그가 해제된다. GetError는 기록된 부호가 없으면 NO_ERROR를 반환한다.


- 오류를 발생시키는 명령은 무시되어 GL 상태나 framebuffer 내용에 아무 영향을 끼치지 않는다. 이 때 반환값이 있는 명령이면 일반적으로 0을 반환한다. 포인터 인자를 통해 값을 반환하는 명령인 경우, 해당 포인터는 수정되지 않는다.


- 그래픽스 리셋 복구. 이 경우 GL 컨텍스트가 리셋되어 lost context가 되고 거의 쓸 수 없게 된다. 이 때는 새 컨텍스트를 만들고 lost context로부터 상태를 가져와야 한다. 그래픽스 리셋 상태의 현재값은 enum GetGraphicsResetStatus( void ); 명령으로 얻어온다. 반환값은 이 명령을 마지막으로 호출한 이후에 GL 컨텍스트가 리셋 상태에 빠진 적이 있는 지를 나타낸다.

  - NO_ERROR: 마지막 호출 이후 리셋된 적이 없다.

  - GUILTY_CONTEXT_RESET: 현재 GL 컨텍스트 때문에 리셋이 일어난 적이 있다.

  - INNOCENT_CONTEXT_RESET: 리셋이 일어난 적은 있지만 현재 GL 컨텍스트 때문이 아니다.

  - UNKNOWN_CONTEXT_RESET: 리셋이 일어났는데 어떤 GL 컨텍스트에서 기인했는지 알 수 없다.


- Flush와 Finish. 구현에 따라 명령들은 GL 서버에 보내기 전에 명령 큐에 쌓이는데, void Flush( void ); 는 누적된 명령들은 유한 시간 안에 처리하도록 한다. Flush 반환할 때에도 여전히 명령을 처리하는 중일 수 있다. void Finish( void ); 는 모든 명령 실행이 끝나고 상태와 framebuffer 갱신이 끝난 후에야 반환한다.


- 컨텍스트 상태는 개별 개체가 아니라 GL 컨텍스트 자체에 속하는 상태다. 컨텍스트 상태는 클리핑, primitive rasterization, framebuffer clear 등 GPU의 고정 기능 단계들을 제어한다. 또한 명령 실행 중 어떤 개체를 사용할지, 즉 개체 바인딩을 결정한다.


- 컨텍스트 상태는 서버 상태와 클라이언트 상태로 나뉘는데 대부분의 상태가 서버에 속한다.


- 개체와 개체 모델. 각각의 개체 타입은 상응하는 이름공간을 갖는다.

  - 개체의 이름은 uint 타입의 부호 없는 정수로 표현된다. 0은 GL에 의해 예약되어있다.

  - 몇몇 개체 타입은 0이 그 타입의 default object를 나타내고, 그 외의 개체 타입의 경우 0은 그 개체 타입의 실제 인스턴스에 대응하지 않는다.

  - 대부분의 경우 Gen으로 시작하는 명령으로 이름을 생성함으로써 개체 이름이 만들어진다.

    가령 GenBuffers 명령은 이전에 쓰이지 않은 하나 이상의 버퍼 개체 이름을 반환한다.

 

- 여러 컨텍스트가 같은 서버 상태를 공유하는 것이 가능하며 WGL 같은 바인딩 API를 통해 이루어진다. 몇 예외를 제외하고 모든 컨텍스트 상태는 그 컨텍스트에 한정된다.

 

- GL이 사용하는 데이터 중 많은 것이 클라이언트에서 제공하는 것이다. 이중에 정점 배열이나 픽셀 데이터 같은 일부는 수행능력 이유상 서버 메모리에 저장해야 한다. 버퍼 개체는 data store라는 서버측 고정 길이 메모리를 포함한다.

 

- 셰이더 개체는 셰이더 프로그램의 소스 코드 또는 바이너리 코드, 혹은 둘 모두를 나타낸다. 셰이더 프로그램은 GL이 정의하는 프로그래밍 가능한 단계들 중 하나에서 실행되며 하나 이상의 셰이더 개체로 캡슐화된다.

 

- 셰이더 개체들은 함께 연결되어 프로그램 개체를 형성한다. 프로그래밍 가능 단계에서 실행될 셰이더 프로그램을 executable이라 부른다. 각각의 executable을 정의하는데 필요한 모든 정보는 프로그램 개체 안에 캡슐화된다.

 

- program pipeline 개체는 각각의 프로그래밍 가능 단계에 대해 별도의 프로그램 개체 바인딩 지점을 포함한다. 하나의 primitive가 각 단계에서 서로 다른 프로그램들에 의해 처리되는 것을 가능하게 한다. program pipeline 개체는 프로그램 개체들을 참조하는 컨테이너 개체다.

 

- 텍스처 개체 또는 텍스처는 텍스처 이미지의 모음이다. 이미지 요소들을 texel이라 한다. 셰이더는 텍스처 좌표가 나타내는 위치에서 텍스처를 샘플링한다. 샘플링 결과는 대개 fragment의 색상을 조정하는 데 쓰이지만, 어떤 목적으로도 쓸 수 있다.

 

- sampler 개체는 셰이더가 텍스처에 접근할 때 샘플링을 어떻게 수행할 지를 제어하는 상태의 부분집합을 포함한다.


- renderbuffer 개체는 무언가를 렌더링할 수 있는 단일 이미지를 포함한다. off-screen rendering을 수행할 때 renderbuffer 개체를 framebuffer 개체에 붙일 수 있다.

 

- framebuffer 개체는 색상 버퍼, 깊이 버퍼, 스텐실 버퍼 등 framebuffer의 상태를 캡슐화한다. 각각의 버퍼는 renderbuffer 객체에 의해 표현되거나 이 framebuffer에 부착된 텍스처 개체에 의해 표현된다. framebuffer 개체는 renderbuffer 또는 texture 개체를 참조하는 컨테이너 개체이며 공유되지 않는다.

 

- vertex array 개체는 정점 속성들의 모음을 나타낸다. 각각의 집합은 버퍼 개체 data store에 배열로 저장된다. 현재 바인딩된 vertex array 개체의 내용은 그리기 명령을 실행할 때 정점 셰이더의 입력이 된다. vertex array 개체는 버퍼 개체를 참조하는 컨테이너 개체이며 공유되지 않는다.

 

- transform feedback 개체는 transform feedback mode가 활성화 상태일 때, transform feedback 단계로 넘어온 primitive의 정점 속성들을 포착하기 위해 사용된다. 버퍼 개체를 참조하는 컨테이너 개체이며 공유되지 않는다.

 

- query 개체는 일련의 GL 명령 처리에 대한 정보를 반환한다. 가령 그리기 명령이 처리한 primitive 개수, transform feedback 버퍼에 기록된 primitive 개수, fragment 처리에서 깊이 테스트를 통과한 샘플 개수, 명령 실행에 필요한 시간 등. query 개체는 공유되지 않는다.

 

- sync 개체는 synchronization primitive로서 행동한다. GL 상태 기계나 그래픽스 파이프라인 내에서 발생하는 작업들의 동기화나 여러 그래픽스 컨텍스트 사이의 동기화에 쓸 수 있다. sync 개체는 공유될 수 있다.


3. Dataflow 모델

- 1단계: 정점들을 조립하여 점, 선분, 다각형 등 기하학적 primitive들을 형성한다.

- 2단계: 정점들을 변환한다.

- 3단계: tessellation과 기하 셰이더가 하나의 입력 primitive로부터 여러 primitive를 생성한다.

   이 때, 그 결과를 transform feedback을 통해 버퍼 개체에 넣을 수 있다.

- 4단계: primitive들은 clip volumne에 의해 잘려 rasterization을 준비한다.

- 5단계: rasterizer는 일련의 framebuffer 주소들과 값들을 생산한다.

- 6단계: 각각의 fragment는 framebuffer를 변경하기 전 최종 작업을 거친다.

   (깊이 값에 따른 조건부 갱신, 보관된 색상과 들어오는 색상의 혼합, 마스킹, 스텐실, 그 외 논리 연산)

- 7단계: 픽셀도 framebuffer로부터 읽어오거나 한 framebuffer에서 다른 것으로 복사하는 것이 가능하다.

- 8단계: 파이프라인과 무관하게, 내용을 버퍼 개체로부터 읽어오거나 버퍼 개체에 기록하는 compute 셰이더가 실행될 수 있다.

 

4. 이벤트 모델

- sync 개체는 synchronization primitive로서 작동하여, 어떤 이벤트를 나타내는데 그 완료 상태를 검사하거나 기다릴 수 있다.

 

- sync 개체는 signaled 또는 unsignaled 상태값을 가진다. 이벤트는 sync 개체와 연관된다. sync 개체가 생성될 때는 unsignaled 상태다. 연관 이벤트가 발생하면 sync 개체는 signaled 상태가 된다. sync 개체가 signaled 상태가 될 때까지 기다리도록 GL에 명령할 수 있다.

 

- 처음에는 한 sync 개체만이 정의되어 있다. fence sync 개체라는 것으로, GL 명령 스트림에 위치한 fence 커맨드에 의해 발동하는 이벤트와 연관된다. fence sync 개체는 GL 명령 스트림의 부분적 완료를 기다리는데 쓰이며, Finish의 좀 더 유연한 형태다. sync FenceSync( enum condition, bitfield flags ); 명령은 새로운 fence sync 개체를 생성하여, GL 명령 스트림에 fence 커맨드를 넣은 다음 이 fence sync 개체와 연관짓는다. 그리고 그 sync 개체에 상응하는 0이 아닌 이름을 반환한다. 명시된 condition이 fence 명령에 의해 만족될 때 그 sync 개체는 signaled 상태가 되고 ClientWaitSync 또는 WaitSync 명령이 sync에서 블로킹되도록 한다. 다른 상태들은 FenceSync나 연관된 fence 커맨드의 실행에 영향을 받지 않는다.

 

- FenceSync로 생성한 sync 개체의 초기 속성

  OBJECT_TYPE: SYNC_FENCE

  SYNC_CONDITION: condition(SYNC_GPU_COMMANDS_COMPLETE여야 함)

  SYNC_STATUS: UNSIGNALED

  SYNC_FLAGS: flags

 

- query 객체와 비동기 질의. 비동기 질의는 일련의 GL 명령 처리에 대한 정보를 반환하는 기제다. GL이 지원하는 질의 종류는 다음과 같다.

  - PRIMITIVES_GENERATED: GL이 처리한 primitive의 개수

  - TRANSFORM_FEEDBACK_PRIMITIVES: buffer 객체에 기록된 primitive의 개수

  - occlusion 질의: 깊이 테스트를 통과한 fragment의 개수

  - time elapsed 질의: 일련의 명령을 완전히 처리하는 데 필요한 시간

  - 타이머 질의: GL의 현재 시간

 

5. Shared Object와 Multiple Context

- shared object: 여러 컨텍스트가 공유할 수 있는 개체. buffer 개체, 프로그램 & 셰이더 개체, renderbuffer 개체, sampler 개체, sync 개체, 텍스처 개체 등(0번 텍스처 제외)

- 이들 중 어떤 개체는 다른 개체의 data store 일부 또는 전체에 대한 view를 포함한다.

  - 텍스처 버퍼 개체는 버퍼 개체의 data store에 대한 view를 포함한다.

  - view는 개체에 대한 참조 역할을 한다.

- 다른 개체를 참조하는 개체들: framebuffer, program pipeline, query, transform feedback, vertex array object

  - 이들은 컨테이너 개체라 부르며 공유되지 않는다

 

6. buffer 개체

- buffer 개체는 서버 메모리에서 고정 크기 할당량을 담는 data store이다.

- void GenBuffers( sizei n, uint *buffers ); 명령은 buffers 안에 n개의 미사용 버퍼 이름을 담아 반환한다.

- void CreateBuffers( sizei n, uint *buffers ); 명령은 buffers 안에 n개의 미사용 버퍼 이름을 담아 반환한다.

   각각의 버퍼가 어떤 대상에 바운딩된 것처럼 초기화된다.

- GenBuffers와 CreateBuffers의 차이

- 버퍼 삭제는 void DeleteBuffers( sizei n, const uint *buffers ); 명령

 

7. 프로그램과 셰이더

- 셰이더는 데이터가 OpenGL 프로세싱 파이프라인을 거치며 적용될 연산을 기술한다. (애플리케이션이 제공한 정점에서 시작하여 프레임버퍼에 기록하기 직전 fragment에 이르기까지)

 

- 셰이더에 사용하는 프로그래밍 언어는 OpenGL Shading Language Specification 참조.

 

- 셰이더 사용 절차: shader 개체에 소스 코드 로드 -> 컴파일. 또는 미리 컴파일된 바이너리 코드를 shader 개체에 직접 로드.

- GL 구현자는 컴파일 기능을 반드시 넣어야 한다.

- NUM_SHADER_BINARY_FORMATS가 0보다 크면 바이너리 로딩이 지원되는 것.

 

- 하나 이상의 shader 개체들은 program 개체에 부착된다. 그 다음 program 개체는 링크 과정을 거쳐, 모든 관련 shader 개체들로부터 실행 가능한 코드를 생산한다. 또는 미리 컴파일된 프로그램 바이너리 코드를 program 개체에 직접 로드할 수 있다.

 

- program 개체가 셰이더 스테이지에 바인딩되면 그 스테이지의 current program object라고 부른다.

- 각 단계의 current program object는 하나의 program 개체를 가지고 모두 설정할 수도 있고, separable program object를 이용하여 개별 설정할 수도 있다.

 

- 셰이더 스테이지의 종류: vertex shader, tessellation control shader, tessellation evaluation shader, geometry shader, fragment shader, compute shader

  - vertex shader: vertex attribute에 대한 연산을 기술

  - tessellation control/evaluation shader: tessellator의 작업을 제어

  - geometry shader: 정점들로부터 조립되는 primitive의 처리에 영향을 줌

  - fragment shader: rasterization 중 fragment의 처리에 영향을 줌

  * 하나의 program 개체가 이 셰이더들을 모두 포함할 수도, 일부만 포함할 수도 있다.

- computer shader는 셰이더 실행 시 전달된 배열에 대해 범용 계산을 수행하지만 다른 셰이더들이 처리하는 primitive와는 연관이 없다.

 

- 셰이더는 실행 시 여러 종류의 변수를 참조할 수 있다.

  - uniform은 프로그램별 변수로서 프로그램 실행 동안 상수로 존재한다.

  - buffer variable은 uniform과 비슷하지만 buffer object memory에 저장되며, 여러 셰이더에 기록될 수 있고 일정한 값을 가진다.

  - subroutine uniform variable은 uniform과 비슷하지만 program object state가 아니라 context state다.

  - sampler는 텍스처링에 사용되는 특수한 형태의 uniform이다.

  - image는 내장 셰이더 함수를 이용해 접근하는 텍스처의 레벨을 식별하는 특수 형태의 uniform이다.

  - output varaible은 셰이더 실행 결과를 담으며 파이프라인의 이후 단계에서 사용된다.

 

- shader 개체의 이름공간은 부호 없는 정수로서 0은 GL에 의해 예약되어 있다. 이 이름공간은 프로그램 개체들 사이에서 공유된다.

 

- shader 개체를 생성하려면 uint CreateShader( enum type ); 명령을 사용한다.

- 생성 시에 shader 개체는 비어 있다.

- type 인자는 생성될 shader 개체의 종류를 기술하며 다음 중 하나여야 한다: VERTEX_SHADER, TESS_CONTROL_SHADER, TESS_EVALUATION_SHADER, GEOMETRY_SHADER, FRAGMENT_SHADER, COMPUTE_SHADER.

- type이 이 중 하나가 아니면 INVALID_ENUM 에러 발생, 0 반환

 

- shader 개체에 소스 코드 로드: void ShaderSource( uint shader, sizei count, const char * const *string, const int *length );

- 기존에 소스 코드가 있었다면 완전히 교체됨

 

- 소스 코드 로드 후 컴파일: void CompileShader( uint shader );

- 각 shader 개체는 COMPILE_STATUS라는 진위값 상태를 가지며 컴파일 후 수정된다. GetShaderiv로 확인 가능.

- ShaderSource로 shader 개체의 소스 코드를 변경해도 컴파일 상태나 컴파일된 셰이더 코드에 영향을 주지 않는다.

- 각 shader 개체는 정보 로그를 가진다. GetShaderInfoLog로 확인 가능.

 

- 셰이더 컴파일러가 할당한 리소스는 void ReleaseShaderCompiler( void ); 로 해제 가능

- 이는 애플리케이션이 제공하는 힌트이며, 정상적인 셰이더 소스를 로드하고, ReleaseShaderCompiler를 호출하고, 컴파일을 시도해도 에러가 생기지 않는다.

 

- 셰이더 삭제는 void DeleteShader( uint shader );

- shader가 아무 program 개체에도 부착되지 않았다면 즉시 삭제. 아니면 삭제 딱지가 붙고 모든 program 개체로부터 떨어졌을 때 삭제됨.

- 어떤 개체에 삭제 딱지가 붙으면 그것의 불리언 상태 비트 DELETE_STATUS가 true로 설정된다. GetShaderiv로 확인 가능.

- shader에 0을 넣으면 아무 일도 일어나지 않는다.

 

- 셰이더 여부 확인: boolean IsShader( uint shader );

- shader가 존재하는 shader 개체의 이름인지 확인.

 

- 셰이더 바이너리를 로드하려면 void ShaderBinary( sizei count, const uint *shaders, enum binaryformat, const void *binary, sizei length );

 

- program 개체 생성: uint CreateProgram( void );

- program 개체에 shader 개체 부착: void AttachShader( uint program, uint shader );

- 셰이더에 소스 코드 로드 전/후 어느 때나 부착 가능

- 링크 수행: void LinkProgram( uint program );

 

- program 사용: void UseProgram( uint program );

- 0 기입시 사용 중인 program object가 없는 것이 된다.

 

- program 개체 사용 도중에 shader 개체를 부착/탈착하거나 컴파일하는 것은 program 개체의 링크 상태나 실행 코드에 영향을 주지 않는다.

- LinkProgram 또는 ProgramBinary를 실행해서 program 개체를 재링크한 후에야 반영된다.

 

- uint CreateShaderProgramv( enum type, sizei count, const char * const *strings ); 명령은 다음과 동일하다.

const uint shader = CreateShader(type);
if (shader) {
  ShaderSource(shader, count, strings, NULL);
  CompileShader(shader);
  const uint program = CreateProgram();
  if (program) {
    int compiled = FALSE;
    GetShaderiv(shader, COMPILE_STATUS, &compiled);
    ProgramParameteri(program, PROGRAM_SEPARABLE, TRUE);
    if (compiled) {
      AttachShader(program, shader);
      LinkProgram(program);
      DetachShader(program, shader);
    }
    append-shader-info-log-to-program-info-log
  }
  DeleteShader(shader);
  return program;
} else {
  return 0;
}

 

- program 개체가 current rendering state의 일부가 되면, 그 실행 코드가 여러 인터페이스를 통해 다른 GL 파이프라인 스테이지나 애플리케이션 코드와 통신할 수 있다.

- 프로그램이 링크되면 GL은 그 인터페이스에 대한 active resource들의 목록을 생성한다.

- active resource: variable, interface block, 셰이더 코드가 사용하는 subroutine 등

- 셰이더 코드 안에서 참조되는 리소스들은 active한 것으로 간주된다. (컴파일러와 링커가 그 리소스는 셰이더 실행 결과에 영향을 주지 않는다고 간주하지 않는 한. 선언만 하고 쓰지 않는다던가 절대 실행되지 않을 if절 안에서만 사용된다던가. active인지 아닌지의 판단은 구현에 따라 다르다)

- GL은 program 개체의 인터페이스의 속성들을 질의하는 명령들을 제공한다. 각 명령은 programInterface 토큰을 넘겨받아 특정 인터페이스를 식별한다.

 

- 지원되는 programInterface들

  - UNIFORM, UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER, PROGRAM_INPUT, PROGRAM_OUTPUT

  - VERTEX_SUBROUTINE, TESS_CONTROL_SUBROUTINE, TESS_- EVALUATION_SUBROUTINE, GEOMETRY_SUBROUTINE, FRAGMENT_- SUBROUTINE, COMPUTE_SUBROUTINE

  - VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_SUBROUTINE_- UNIFORM, TESS_EVALUATION_SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_UNIFORM, FRAGMENT_SUBROUTINE_UNIFORM, COMPUTE_SUBROUTINE_UNIFORM

  - TRANFORM_FEEDBACK_VARYING

  - TRANFORM_FEEDBACK_BUFFER

  - BUFFER_VARIABLE

  - SHADER_STORAGE_BLOCK

 

- 모든 셰이더 단계를 하나의 program 개체로 묶는 대신, 여러 program 개체에 파이프라인의 일부를 나눠 담을 수 있다.

- void GenProgramPipelines( sizei n, uint *pipelines ); 는 이전에 쓰이지 않은 n개 program pipeline 개체들의 이름을 반환한다.

- void DeleteProgramPipelines( sizei n, const uint *pipelines ); 삭제

- void BindProgramPipeline( uint pipeline ); 바인딩. UseProgram에 의해 current program object가 정해진 상태에서는 효과가 없다.

- void UseProgramStages( uint pipeline, bitfield stages, uint program );

- void ActiveShaderProgram( uint pipeline, uint program ); 은 이름이 program인, 링크된 프로그램을 active program으로 설정한다.

 

- sampler는 텍스처 조회를 위한 특별한 uniform이다. 값 i인 sampler는 i번 텍스처 이미지에 대응된다. i의 값은 0 ~ (최대로 지원되는 텍스처 개수 - 1)이다.

 

8. 텍스처와 샘플러

- texturing은 하나 이상의 특정 이미지(들)의 일부를 fragment 또는 vertex에 매핑한다. 이 매핑은 이미지에서 텍스처 좌표 (s, t, r)이 나타내는 위치의 색상을 sampling함으로서 이루어진다. 텍스처 조회는 주로 fragment의 RGBA 색상을 조절하는 데 쓰이지만 셰이더에서 어떤 목적으로든 쓸 수 있다.

- 내부 자료형이 정수인 텍스처와 실수인 텍스처가 있다.

 

- void ActiveTexture( enum texture ); 는 active texture unit selector를 지정한다.

- active texture unit selector는 TexParameter, TexImage, BindTexture 등의 명령이 접근할 텍스처 이미지 유닛을 지정한다.

 

- GL에서 텍스처는 이름 있는 개체로 표현된다. 텍스처 개체들의 이름공간은 부호 없는 정수로 0은 GL이 기본 텍스처 개체를 나타내기 위해 예약되어 있다.

 

- 새 텍스처 개체 생성: void GenTextures( sizei n, uint *textures );

- 바인딩: void BindTexture( enum target, uint texture );

- 여러 텍스처 바인딩: void BindTextures( uint first, sizei count, const uint *textures );

  - first에서 first + count - 1까지의 유닛을 순서대로 active하고 BindTexture 호출하는 것과 동일

 

- 텍스처링을 위해 필요한 상태는 두 부류로 나눌 수 있고, GL 텍스처 개체는 둘 모두를 포함한다.

  - dimensionality와 다른 이미지 매개변수들

  - 샘플링 레이트

- 텍스처 개체의 샘플링 상태만을 캡슐화하기 위해 부가적인 샘플러 개체를 만들 수 있다

- 생성: void GenSamplers( sizei count, uint *samplers );

- 생성된 이름은 BindSampler, SamplerParameter*, GetSamplerParameter*, IsSampler 등에 사용

- 바인딩: void BindSampler( uint unit, uint sampler );

- 여러 개 바인딩: void BindSamplers( uint first, sizei count, const uint *samplers );

 

- 샘플러 개체의 매개변수들의 현재 값 질의

  - void GetSamplerParameter{if}v( uint sampler, enum pname, T *params );

  - void GetSamplerParameterI{i ui}v( uint sampler, enum pname, T *params );

 

- pixel rectangle의 전송. pixel rectangle을 받아들이거나 반환하는 명령들은 다음 인자를 취한다.

  - format: 메모리상 값이 무엇을 나타내는지를 지시하는 심볼 상수.

  - width, height: 전송될 pixel rectangle의 가로 세로 길이

  - data: 그려질 데이터

 

- unpacking. 데이터는 현재 바운딩된 pixel unpack buffer 또는 클라이언트 메모리로부터 일련의 값으로서 뽑아온다. 그 형태는 바이트, 정수, 실수 등이 될 수 있다. 이 값들은 format에 따라 1~4개씩 그룹을 형성한다.

- pixel unpack buffer가 바운딩되면 data는 그 버퍼 내에서의 offset이 되고 픽셀들은 이 offset을 기준으로 unpack된다.

- 아니면 data는 클라이언트 메모리에 대한 포인터이고 픽셀들은 그 포인터를 기준으로 unpack된다.

 

- 기본적으로 각각의 GL 자료형의 값은 클라이언트의 GL 바인딩의 언어에 명시된 대로 해석된다.

- 하지만 UNPACK_SWAP_BYTES가 활성화되었다면 비트 순서가 수정되어 해석된다.

- 비트 순서 수정은 오직 GL 자료형인 ubyte가 8비트일 때 8, 16, 32비트인 자료형들에 대해서만 정의된다.

  - 8비트: [7..0] -> [7..0]

  - 16비트: [15..0] -> [7..0][15..8]

  - 32비트: [31..0] -> [7..0][15..8][23..16][31..24]

 

- 메모리 내 그룹들은 직사각형 안에 배열된 것으로 간주된다. 이 직사각형은 일련의 row로 이루어지는데 data는 첫 row의 첫 group의 첫 원소를 가리킨다. UNPACK_ROW_LENGTH가 0이라면 한 row 내에 그룹의 개수는 width와 같다. 아니면 그룹의 개수가 UNPACK_ROW_LENGTH의 값이다.

 

- 텍스처 이미지 구조. 텍스처 이미지 자체는 값의 그룹을 나열한 것이다. 첫번째 그룹은 텍스처 이미지의 왼쪽 아래 모서리다. 이어지는 그룹들은 왼쪽에서 오른쪽으로 width 길이의 행을 채운다. height개 행이 아래에서 위로 쌓여 하나의 이차원 이미지를 형성한다. depth개 조각들이 뒤에서 앞으로 쌓인다. 한 그룹에 대한 최종 RGBA 성분이 계산되면 텍셀의 성분에 할당된다. 0부터 세서 최종적인 n번째 텍셀은 내부적으로 정수 좌표 (i, j, k)가 할당된다.

  - i = n mod width

  - j = floor(n/width) mod height

  - k = floor(n/(width*height)) mod depth

- 따라서 삼차원 이미지의 최종적인 이차원 이미지 조각은 가장 높은 k값에 의해 참조된다.

- target이 TEXTURE_CUBE_MAP_ARRAY이면 k는 layer-face를 가리킨다. 이 layer는 floor(k/6)이며 face는 k mod 6이다.

 

- 텍스처 이미지의 내부 자료형이 정규화된 고정소수점이라면, 부호 유무에 따라 각 색상 성분이 다음의 식 중 하나를 통해 변환된다.

$$ f' = \text{convert_float_uint} (f \times (2^b - 1) , b) $$

$$ f' = \text{convert_float_int} (f \times (2^b - 1) , b) $$

- 내부 자료형이 부동소수점 또는 정수라면 대응하는 내부 구성요소의 표현 가능 범위에 맞춰 잘리지만 변환되지는 않는다.

 

- TexImage3D의 level 인자는 level-of-detail을 나타내는 정수다. 메인 텍스처 이미지의 level은 0이다. level은 0 이상이어야 한다.

 

- TexImage2D는 2D 텍스처 이미지를 기술하는 데 쓰인다. target은 2D 텍스처의 경우 TEXTURE_2D, 1D 배열 텍스처는 TEXTURE_1D_ARRAY, rectangle 텍스처는 TEXTURE_RECTANGLE, 큐브 맵 텍스처의 경우 큐브 맵 face target들 중 하나다. 추가적으로, target은 2D 프록시 텍스처의 경우 PROXY_TEXTURE2D, 1D 프록시 배열 텍스처는 PROXY_TEXTURE_1D_ARRAY, rectangle 프록시 텍스처는 PROXY_TEXTURE_RECTANGLE, 큐브 맵 프록시 텍스처는 PROXY_TEXTURE_CUBE_MAP이 될 수 있다. 다른 인자들은 TexImage3D의 경우와 같다.

void TexImage2D( enum target, int level, int internalformat, sizei width, sizei height, int border, enum format, enum type, const void *data );

 

- 텍스처 이미지 디코딩의 경우 TexImage2D는 TexImage3D에서 depth를 1로 주고 UNPACK_SKIP_IMAGES를 무시하는 것과 동등하다.

- 2D 또는 rectangle 텍스처는 하나의 2D 텍스처 이미지로 이루어진다. 큐브 맵 텍스처는 2D 텍스처 이미지 6개로 구성된다.

- 큐브 맵 face target들은 큐브 맵의 2D 이미지 6개를 기술하고, 갱신하고, 질의하는 데 쓰이지만 큐브 맵 텍스처 개체에 바인딩할 때는 target이 TEXTURE_CUBE_MAP임을 주의하라.

 

- TexImage1D는 1D 텍스처 이미지를 기술하는 데 쓰인다. target은 TEXTURE_1D 또는 PROXY_TEXTURE_1D여야 한다.

void TexImage1D( enum target, int level, int internalformat, sizei width, int border, enum format, enum type, const void *data );

 

- 텍스처 이미지 디코딩의 경우 TexImage1D는 TexImage2D에서 height에 1을 준 것과 동등하다.

- 이미지 포인터가 가리키는 이미지는 디코딩되어 GL의 내부 메모리에 복사된다. 이 디코딩된 이미지를 texture image라 부른다. 텍스처 이미지의 원소 (i, j, k)를 텍셀(texel)이라 부른다. (2D 또는 1D 텍스처의 경우 k는 무관하다. 1D 텍스처의 경우 j, k는 무관하다.)

- 셰이더에서 텍스처를 샘플링하여 fragment를 텍스처링할 때 쓰이는 텍스처 값은 실제로 어느 텍셀과도 일치하지 않을 수 있다. (interpolation 때문)

- target이 TEXTURE_CUBE_MAP_ARRAY라면 텍스처 값은 좌표 (s,t,r,q)에 의해 결정된다. s,t,r은 TEXTURE_CUBE_MAP의 경우와 같고 q는 인덱스다.

- TexImage1D, TexImage2D, TexImage3D의 data 인자가 NULL이고 pixel unpack buffer 개체가 0이면, 명시된 target, level, internalformat, border, width, height, depth에 맞는 텍스처 이미지가 생성되지만 그 내용물은 채워지지 않는다. 이 경우 픽셀 처리를 수행하지 않는다. 하지만 오류는 data 포인터가 올바른 경우와 마찬가지로 발생한다. pixel unpack buffer object가 0이 아니라면 data 인자는 pixel unpack buffer object의 데이터 시작 지점을 참조하는 것으로 다뤄진다.

 

8.6 Alternate Texture Image Specification Commands

- 2D, 1D 텍스처 이미지는 프레임버퍼에서 직접 이미지 데이터를 가져와서 기입할 수도 있다.

- void CopyTexImage2D( enum target, int level, enum internalformat, int x, int y, sizei width, sizei height, int border );

- 이 명령은 TexImage2D와 정확히 같은 방식으로 2D 텍스처 이미지를 정의하는데, 이미지 데이터를 클라이언트 메모리가 아니라 프레임버퍼에서 바로 가져온다는 점이 다르다. target은 반드시 TEXTURE_2D, TEXTURE_1D_ARRAY, TEXTURE_RECTANGLE, 또는 큐브 맵 타겟 중 하나여야 한다. x, y, width, height는 ReadPixels의 인자와 동일하다. 이것들은 프레임버퍼 영역에서 복사할 영역의 왼쪽 아래 (x, y) 좌표, 가로 길이, 세로 길이를 명시한다.

- 에러 목록

  - INVALID_ENUM

    - target이 TEXTURE_2D, TEXTURE_1D_ARRAY, TEXTURE_RECTANGLE, 큐브 맵 페이스 타겟 중 하나가 아닐 경우

    - internalformat에 잘못된 값을 기입한 경우

  - INVALID_VALUE

    - target이 여섯 개의 큐브 맵 2D 이미지 타겟 중 하나인데, width와 height가 다를 경우

    - width 또는 height가 음수일 경우

  - INVALID_OPERATION

    - 깊이 성분 데이터가 필요한데 깊이 버퍼가 없을 경우

    - 스텐실 색인 데이터가 필요한데 스텐실 버퍼가 없을 경우

    - 정수 RGBA 데이터가 필요한데 현재 색상 버퍼의 포맷이 정수가 아닐 경우

    - 부동 또는 고정소수점 RGBA 데이터가 필요한데 현재 색상 버퍼의 포맷이 정수일 경우

    - read buffer에 해당하는 프레임버퍼 attachment의 FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 값이 LINEAR이고 internalformat이 표 8.24의 sRGB 포맷 중 하나일 때

    - read buffer에 해당하는 프레임버퍼 attachment의 FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 값이 SRGB이고 internalformat이 표 8.24의 sRGB 포맷 중 하나가 아닐 때

    - READ_FRAMEBUFFER_BINDING에 바인딩된 개체가 무결 프레임버퍼이고 그것의 SAMPLE_BUFFERS의 effective value가 1일 때(9.2.3.1절 참조)

  - INVALID_FRAMEBUFFER_OPERATION

    - READ_FRAMEBUFFER_BINDING에 바인딩된 개체가 무결 프레임버퍼(framebuffer complete)가 아닐 경우

 

- void CopyTexImage1D( enum target, int level, enum internalformat, int x, int y, sizei width, int border );

- TexImage1D와 같은 방식으로 1D 텍스처 이미지를 정의하지만 이미지 데이터를 클라이언트 메모리가 아니라 프레임버퍼에서 가져온다.

- target은 반드시 TEXTURE_1D 이어야 한다.

- 텍스처 이미지를 디코딩할 때, CopyTexImage1D는 CopyTexImage2D의 height에 1을 준 것과 동등하다. 단 border의 값과 무관하게 height는 항상 1이다.

- level, internalformat, border는 TexImage1D의 것들과 동일하다.

 

- 텍스처 개체의 텍스처 이미지에서 일부 영역만 다시 기입하려면 다음 명령들을 이용하라.

void TexSubImage3D( enum target, int level, int xoffset, int yoffset, int zoffset, sizei width, sizei height, sizei depth, enum format, enum type, const void *data );

void TexSubImage2D( enum target, int level, int xoffset, int yoffset, sizei width, sizei height, enum format, enum type, const void *data );

void TexSubImage1D( enum target, int level, int xoffset, sizei width, enum format, enum type, const void *data );

void CopyTexSubImage3D( enum target, int level, int xoffset, int yoffset, int zoffset, int x, int y, sizei width, sizei height );

void CopyTexSubImage2D( enum target, int level, int xoffset, int yoffset, int x, int y, sizei width, sizei height );

void CopyTexSubImage1D( enum target, int level, int xoffset, int x, int y, sizei width );void TextureSubImage3D( uint texture, int level, int xoffset, int yoffset, int zoffset, sizei width, sizei height, sizei depth, enum format, enum type, const void *pixels );

void TextureSubImage3D( uint texture, int level, int xoffset, int yoffset, int zoffset, sizei width, sizei height, sizei depth, enum format, enum type, const void *pixels );

void TextureSubImage2D( uint texture, int level, int xoffset, int yoffset, sizei width, sizei height, enum format, enum type, const void *pixels );

void TextureSubImage1D( uint texture, int level, int xoffset, sizei width, enum format, enum type, const void *pixels );

void CopyTextureSubImage3D( uint texture, int level, int xoffset, int yoffset, int zoffset, int x, int y, sizei width, sizei height );

void CopyTextureSubImage2D( uint texture, int level, int xoffset, int yoffset, int x, int y, sizei width, sizei height );

void CopyTextureSubImage1D( uint texture, int level, int xoffset, int x, int y, sizei width );


표 8.15: 텍스처 부분이미지 명령을 위한 올바른 텍스처 target 또는 유효한 texture 타겟

명령 

올바른 target 또는 유효한 texture 타겟 

TexSubImage1D

CopyTexSubImage1D

TextureSubImage1D

CopyTextureSubImage1D

TEXTURE_1D

TexSubImage2D

CopyTexSubImage2D

TEXTURE_2D

TEXTURE_1D_ARRAY

TEXTURE_RECTANGLE

표 8.19의 큐브 맵 페이스 타겟 중 하나 

TextureSubImage2D

CopyTextureSubImage2D

TEXTURE_2D

TEXTURE_1D_ARRAY

TEXTURE_RECTANGLE

TexSubImage3D

CopyTexSubImage3D

TEXTURE_3D

TEXTURE_2D_ARRAY

TEXTURE_CUBE_MAP_ARRAY

TextureSubImage3D

CopyTextureSubImage3D

TEXTURE_3D

TEXTURE_2D_ARRAY

TEXTURE_CUBE_MAP_ARRAY

TEXTURE_CUBE_MAP


- *TexSubImage*의 경우, 텍스처 개체는 target에 바운딩되는 것이고, *TextureSubImage*의 경우, texture는 텍스처 개체의 이름이다.

- 텍스처 이미지에서 명시된 부분 영역 이외의 internalformat, width, height, depth, border, 텍셀 값은 변하지 않는다.

- 각 명령의 level 매개변수는 수정될 텍스처 이미지 레벨을 명시한다.


- 압축된 내부 포맷을 사용하는 텍스처 이미지의 경우, 압축을 풀고 다시 압축하지 않는 한 일부 영역만을 수정하는 것이 불가능할 수 있다. GL은 이런 포맷에 대한 부분 변경을 지원하지 않는다. 이런 포맷에 대해 Tex*SubImage*나 CopyTex*SubImage* 명령을 호출하면 INVALID_OPERATION 오류가 발생할 것이다. (xooffset, yoffset, zoffset이 모두 0인 경우 제외)


8.6.1 텍스처 복사 피드백 루프(Texture Copying Feedback Loops)

목적 텍스처 이미지 레벨이 read framebuffer의 한 선택된 읽기 버퍼에도 바인딩된 상태라면, 이 레벨에 대해 CopyTex*SubImage* 또는 CopyTexImage* 명령을 호출하는 것은 정의되지 않은 행동이다. 피드백 루프에 대한 자세한 설명은 9.3.2절을 참조.


8.7 압축된 텍스처 이미지

이미 알려진 압축 이미지 포맷으로 저장된 이미지 데이터를 이용하여 텍스처 이미지를 기입하거나 수정할 수 있다. 부록 C와 GL 확장에 정의된 추가 포맷들이 그러하다.


void CompressedTexImage1D( enum target, int level,
    enum internalformat, sizei width, int border,
    sizei imageSize, const void *data );


void CompressedTexImage2D( enum target, int level,
    enum internalformat, sizei width, sizei height,
    int border, sizei imageSize, const void *data );


void CompressedTexImage3D( enum target, int level,
    enum internalformat, sizei width, sizei height,
    sizei depth, int border, sizei imageSize, const
    void *data );


- target, level, internalformat, width, height, depth, border 매개변수는 TexImage1/2/3D와 같은 뜻이다.

- pixel unpack buffer가 바인딩된 경우(PIXEL_UNPACK_BUFFER_BINDING의 0이 아닌 값이 지시), data는 그 버퍼 내에서의 오프셋이고, 압축 데이터는 버퍼의 이 오프셋부터 읽기 시작한다. 그렇지 않으면 data는 클라이언트 메모리에 대한 포인터다.

- 압축 이미지는 internalformat이 정의하는 명세에 따라 디코딩된다. 압축 텍스처 이미지는 imageSize개의 ubyte 배열로 취급된다.

- 압축 이미지가 internalformat이 정의하는 명세에 따라 인코딩된 상태가 아니라면, 결과는 알 수 없다.

- 압축 데이터가 고정 크기의 텍셀 블록들로 배열되어 있다면, pixel storage mdoe를 사용하여 부분 사각형 영역을 선택하는 것이 가능하다.


8.7절 미완성

관심 없어서 일단 패스..


8.8 멀티샘플 텍스처

- 2D 텍스처 또는 2D 배열 텍스처와 비슷하지만 텍셀마다 여러 샘플을 포함한다.

- 이미지 레벨을 여러 개 가지지 않는다.


void TexImage2DMultisample( enum target, sizei samples,
    enum internalformat, sizei width, sizei height,
    boolean fixedsamplelocations );
void TexImage3DMultisample( enum target, sizei samples,
    enum internalformat, sizei width, sizei height,
    sizei depth, boolean fixedsamplelocations );


- TexImage2DMultisample의 경우 target은 TEXTURE_2D_MULTISAMPLE 또는 PROXY_TEXTURE_2D_MULTISAMPLE이어야 한다.

- TexImage3DMultisample의 경우 target은 TEXTURE_2D_MULTISAMPLE_ARRAY 또는 PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY이어야 한다.

- samples는 요구되는 최소 샘플 개수다. 텍스처 이미지에 실제로 할당되는 샘플 개수는 구현에 따라 다르다. 하지만 TEXTURE_SAMPLES의 결과 값은 samples 이상이며, 구현이 지원하는 다음으로 큰 샘플 카운트보다 크지 않음이 보장된다.

- fixedsamplelocation이 TRUE면 이미지의 모든 텍셀에 대해 같은 위치와 같은 개수의 샘플을 사용하고, 샘플 위치는 이미지의 내부 포맷이나 크기에 의존하지 않는다.

- TexImage*Multisample이 성공하면 target에 대한 기존 이미지가 삭제되고 텍셀 내용은 정의되지 않는다. TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_SAMPLES, TEXTURE_INTERNAL_FORMAT, TEXTURE_FIXED_SAMPLE_LOCATIONS는 width, height, 할당된 실제 샘플 수, internalformat, fixedsamplelocations로 설정된다.

- 셰이더에서 멀티샘플 텍스처에 접근할 때, 정수들의 벡터 하나(어떤 텍셀을 취할 지를 나타냄)와 정수 하나(샘플 개수. 텍셀에서 어떤 샘플을 취할 지를 결정. 14.3.1절 참조)를 취한다. 일반적인 샘플링 명령은 멀티샘플 텍스처 타겟에 대해 허용되지 않는다. fetch할 때 필터링도 수행되지 않는다.

- 0보다 작거나 텍스처 내 샘플 개수 이상의 샘플 넘버를 fetch하면 정의되지 않은 결과를 초래한다.

- 에러 목록

  - INVALID_ENUM

    - target이 위에서 서술한, 허용되는 멀티샘플 타겟이 아닌 경우

    - internalformat이 color-renderable, depth-renderable, stencil-renderable이 아닌 경우 (9.4절에 정의됨)

  - INVALID_VALUE

    - width, height, depth가 음수인 경우

    - samples가 0인 경우

    - width 또는 height가 MAX_TEXTURE_SIZE보다 큰 경우

    - TexImage3DMultisample에서 depth가 MAX_ARRAY_TEXTURE_LAYERS의 값보다 큰 경우

  - INVALID_OPERATION

    - samples가 이 target과 internalformat에 대해 지원되는 최대 샘플 개수보다 클 경우

      * 지원되는 최대 개수는 GetInternalformativ에 pname을 SAMPLES로 줘서 알 수 있다 (22.3절 참조)

    - active texture unit의 target에 현재 바인딩된 텍스처의 TEXTURE_IMMUTABLE_FORMAT이 TRUE일 경우


8.9 버퍼 텍스처

- 1D, 2D, 3D, 2D 배열, 큐브맵 텍스처 외에 버퍼 텍스처라는 타입이 있다

- 1D 텍스처와 비슷하지만 버퍼 텍스처에서는 텍스처 이미지가 텍스처의 일부로 저장되지 않는다

- 버퍼 개체가 버퍼 텍스처에 부착되고, 텍스처 이미지는 버퍼 개체의 데이터 저장소에서 가져온다

- 버퍼 개체의 데이터 저장소가 변경되면 이 개체가 바인딩된 모든 버퍼 텍스처의 내용물에 그 변경이 반영된다

- 여러 이미지 레벨을 가지지 않는다. 하나의 데이터 저장소만 가용하다


void TexBufferRange( enum target, enum internalformat,
    uint buffer, intptr offset, sizeiptr size );
void TextureBufferRange( uint texture, enum internalformat,
    uint buffer, intptr offset, sizeiptr size );


- 이름이 buffer인 버퍼 개체의 저장소의 일정 범위를 버퍼 텍스처에 부착한다. 그 범위는 offset에서 시작하여 size만큼 나아간다. (offset과 size는 basic machine unit)

- TexBufferRange의 경우 버퍼 텍스처는 target에 현재 바인딩된 것이다

- TextureBufferRange의 경우 texture는 버퍼 텍스처의 이름이다. target 또는 texture의 실타겟은 TEXTURE_BUFFER여야 한다.

- buffer가 0이면 버퍼 텍스처에 부착된 버퍼 개체가 떨어져 나간다. offset과 size의 값은 무시된다. 이 버퍼 텍스처의 offset과 size 상태는 0으로 설정된다. internalformat은 버퍼 개체에서 찾은 텍스처 이미지의 저장 포맷을 나타내며, 표 8.16의 sized internal format 중 하나여야 한다.

- 오류 목록

  - INVALID_OPERATION

    - TextureBufferRange에서 texture가 존재하는 텍스처 개체의 이름이 아닌 경우

    - buffer가 0이 아니면서 존재하는 버퍼 개체의 이름이 아닌 경우

  - INVALID_ENUM

    - 실 target이 TEXTURE_BUFFER가 아닌 경우

    - internalformat이 표 8.16의 sized internal format 중 하나가 아닌 경우

  - INVALID_VALUE

    - offset이 음수거나 size가 0 이하거나 offset + size가 target에 바인딩된 버퍼의 BUFFER_SIZE의 값보다 큰 경우

    - offset이 TEXTURE_BUFFER_OFFSET_ALIGNMENT의 정배수가 아닌 경우


- 다음의 함수들은

void TexBuffer( enum target, enum internalformat, uint buffer );
void TextureBuffer( uint texture, enum internalformat, uint buffer );


- 이것들과 동등하다. (size는 buffer의 BUFFER_SIZE 값)

TexBufferRange(target, internalformat, buffer, 0, size);
TextureBufferRange(texture, internalformat, buffer, 0, size);


- 버퍼 개체를 텍스처에 붙이는 것 외에, 버퍼 개체를 TEXTURE_BUFFER라는 버퍼 개체 타겟에 바인딩하여 버퍼 개체의 데이터 저장소를 기입, 수정, 읽을 수 있다. 버퍼 개체를 TEXTURE_BUFFER에 바인딩하려면 BindBuffer를 호출할 때 target을 TEXTURE_BUFFER로 설정한다. (6절 참조)

 

8.10 텍스처 인자(parameter)
- 텍스처 인자는 텍스처 개체의 이미지를 기입하거나 변경할 때, 프래그먼트에 적용할 때 취급되는 방법을 제어한다.

- 각 인자는 다음의 명령들로 설정한다.

  - void TexParameter{if}( enum target, enum pname, T param );

  - void TexParameter{if}v( enum target, enum pname, const T *params );

  - void TexParameterI{i ui}v( enum target, enum pname, const T *params );

  - void TextureParameter{if}( uint texture, enum pname, T param );

  - void TextureParameter{if}v( uint texture, enum pname, const T *params );

  - void TextureParameterI{i ui}v( uint texture, enum pname const T *params );

- TexParameter*의 경우 텍스처 개체는 target에 바인딩된 것이다. TextureParameter*의 경우 texture는 텍스처 개체의 이름이다. target 또는 texture의 실 타겟은 TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY. TEXTURE_RECTANGLE, TEXTURE_CUBE_MAP, TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_MULTISAMPLE, TEXTURE_2D_MULTISAMPLE_ARRAY 중 하나여야 한다.

- pname은 설정할 인자를 가리키는 기호 상수다. 가능한 인자들이 표 8.17에 요약되었다.

- 스칼라 형태의 명령에서 param은 단일 값이다.

- 벡터 형태의 명령에서 params는 인자들의 배열이다. 그 타입은 설정하려는 인자에 따라 다르다.

- 형변환은 2.2.1절에 명시된 대로 수행한다.

  - 예외: TEXTURE_BORDER_COLOR의 값을 TexParamterIiv 또는 TexParameterIuiv로 기입하면 수정되지 않고 정수의 내부 데이터타입으로 저장된다. TexParameteriv로 기입하면 식 2.2를 이용해 부동소수점 형태로 변환된다. 그 외의 경우 값은 수정되지 않고 부동소수점 형태로 저장된다.

- pname이 TEXTURE_SWIZZLE_RGBA이면 params는 네 enum의 배열이다. (TEXTURE_SWIZZLE_[R/G/B/A])

 

 

 이름

타입 

유효한 값

 DEPTH_STENCIL_TEXTURE_MODE

 enum

 DEPTH_COMPONENT

 STENCIL_INDEX

 TEXTURE_BASE_LEVEL

 int

 음이 아닌 정수

 TEXTURE_BORDER_COLOR

 4개의 float, int, 또는 uint

 값 4개

 TEXTURE_COMPARE_MODE

 enum

 NONE

 COMPARE_REF_TO_TEXTURE

 TEXTURE_COMPARE_FUNC

enum

 LEQUAL, GEQUAL

 LESS, GREATER

 EQUAL, NOTEQUAL

 ALWAYS, NEVER

 TEXTURE_LOD_BIAS

 float

 임의 값

 TEXTURE_MAG_FILTER

 enum

 NEAREST, LINEAR

 TEXTURE_MAX_LEVEL

 int

 음이 아닌 정수

 TEXTURE_MAX_LOD

 float

 임의 값

 TEXTURE_MIN_FILTER

 enum

 NEAREST, LINEAR

 NEAREST_MIPMAP_NEAREST

 NEAREST_MIPMAP_LINEAR

 LINEAR_MIPMAP_NEAREST

 LINEAR_MIPMAP_LINEAR

 TEXTURE_MIN_LOD

 float

 임의 값

 TEXTURE_SWIZZLE_R  enum

 RED, GREEN, BLUE, ALPHA, ZERO, ONE

 TEXTURE_SWIZZLE_G

 enum

 RED, GREEN, BLUE, ALPHA, ZERO, ONE

 TEXTURE_SWIZZLE_B

 enum

 RED, GREEN, BLUE, ALPHA, ZERO, ONE

 TEXTURE_SWIZZLE_A

 enum

 RED, GREEN, BLUE, ALPHA, ZERO, ONE

 TEXTURE_SWIZZLE_RGBA

 enum 4개

 RED, GREEN, BLUE, ALPHA, ZERO, ONE

 TEXTURE_WRAP_S

 enum

 CLAMP_TO_EDGE, REPEAT

 CLAMP_TO_BORDER

 MIRRORED_REPEAT

 MIRROR_CLAMP_TO_EDGE

 TEXTURE_WRAP_T

 enum

 위와 동일
 TEXTURE_WRAP_R

 enum

 위와 동일

 

- TextureView를 통해 생성된 텍스처의 경우, TEXTURE_BASE_LEVEL과 TEXTURE_MAX_LEVEL 인자는 원래 데이터 저장소가 아니라 뷰에 상대적으로 해석된다.

- 큐브 맵 텍스처의 텍스처 인자들은 큐브 맵 전체에 적용된다. 여섯 개의 2D 텍스처 이미지들은 이 인자들을 공유한다.

- 오류

  - INVALID_ENUM

    - 실 target이 위에 나열한 유효 타겟 중 하나가 아닐 경우

    - pname이 표 8.17의 인자 이름들 중 하나가 아닐 경우

    - pname이 가리키는 인자가 enum 타입이지만 param(s)에 기입한 값이 표 8.17의 유효한 값들 중 하나가 아닐 경우

  - INVALID_OPERATION

    - TextureParameter*에서 texture가 존재하는 텍스처 개체의 이름이 아닐 경우

  - INVALID_VALUE

    - pname이 TEXTURE_

 

이걸 굳이 번역해야 하나

 

8.11 텍스처 질의

8.11.1 활성 텍스처(Active Texture)

- 대부분의 텍스처 상태 변수에 관한 질의는 ACTIVE_TEXTURE의 값에 의해 한정되어 어떤 서버 텍스처 상태 벡터를 질의할 지를 결정한다.

- 표 23.12에 요약

 

8.11.2 텍스처 인자 질의

- 텍스처 개체의 인자들은 다음 명령으로 질의한다

  - void GetTexParameter{if}v(enum target, enum pname, T *params);

  - void GetTexParameterI{i ui}v( enum target, enum pname, T *params );

  - void GetTextureParameter{if}v( uint texture, enum pname, T *data );

  - void GetTextureParameterI{i ui}v( uint texture, enum pname, T *data );

- Tex와 Texture의 차이는 앞에서 많이 나와서 생략.

 

Comments