[OpenGL] LearnOpenGL 정리본 6~7

2022. 7. 30. 16:16opengl

728x90

shader

GPU에서 동작하는 프로그램 이 프로그램은 그래픽 파이프라인의 특정 부분을 각자 맡아서 실행한다. shader는 입력값을 출력값으로 변환시키는 프로그램 그 자체이다. 또한 shader은 아주 독립적이기 때문에 서로 의사소통이 안된다. 유일한 의사 소통은 입력값과 출력값을 통해서 하는 것 뿐이다.

 

GLSL 

shader은 c언어와 비슷하게 생긴 GLSL로 작성됨.

그래픽과 함께 쓰일 수 있도록 만들어 졌고,  특히  vector와 matrix를 조작하는데에 유용한 기능들을 가지고 있다. 

 

shader은 항상 버전 선언으로부터 시작합니다. 그 다음으로는 입력 변수와 출력 변수들이 나오게 됩니다. 그리고 uniform이 나오고 그 후에는 main함수로 감싸져 있다.  shader의 시작하는 지점은 main함수부터이다. 

Vertex shader에 대해서 이야기할 때 각각의 입력 변수는 vertex attribute라고 부른다. 

vertex attribute를 선언할 수 있는 갯수는 최대 갯수가 정해져 있다. 

OpenGL은 4가지 요소를 가진 vertex attribute를 최소 16개까지는 보장하고 있다. 

vertex attribute에 대한 정보는  GL_MAX_VERTEX_ATTRIBS를 통해 알 수 있다.

 

 

Types

GLSL의 Vector는 1 ~ 4가지의 요소를 가진 컨테이너 이다. 다음과 같은 형식을 취한다.

 

  • vecn: n개의 float 타입 요소를 가지는 기본적인 vector
  • bvecn: n개의 boolean 타입 요소를 가지는 vector
  • ivecn: n개의 integer 타입 요소를 가지는 vector.
  • uvecn: n개의 unsigned integer 타입 요소를 가지는 vector
  • dvecn: n개의 double 타입 요소를 가지는 vector

우리가 하는 작업은 거의 float 타입에서 작업이 충분하기 때문에 우리는 대부분 기본적인 vecn을 사용할 것이다. 

 

Vector의 요소 들은 vec.x  를 통해 접근이 가능하다.  x는 vector의 첫 번째 요소이다. 1,2,3,4번째 요소들에 접근하기위해 접근자를 사용해서 접근 할 수 있다. (.x .y .z .w.) 또한,  GLSL에서는 컬러는 RGBA를 사용하여 나타낼 수 있고 텍스쳐 좌표는 stq를 사용하여 나타낼 수 있다. 

 

swizzling

Vector데이터 타입으로 swizzling이라고 불리는 흥미롭고 유연한 요소를 선택 할 수 있다. 

vec2같은 경우에는 z를 엑세스 할 수 없다. 근데 z축을 표현하고 싶다면? vector를 다른 vector의 생산자의 파라미터로 넘길 수 있다. 그렇게하면 필요한 파라미터 수가 적어진다. 

 

vector은 모든 유형의 입출력에서 사용할 수 있는 유연한 데이터타입이다. 

 

 

Vertex shader

 

Fragment shader

 

 

 

 

 

적용! 속성 추가하기

 

위치가  location 0이고 컬러가 location 1인거 같다.

 

fragment의 컬러를 위해 uniform을 사용할 필요는 없지만, 이제 출력변수를 사용해야하기 때문에 fragment shader를 다음과 같이 수정해야한다. 

 

현재 layout을 알고 있다면 glVertexAttribPointer 함수를 사용하여 vertex 형식을 수정할 수 있다. 

 

  glVertexAttribPointer 파라미터는 간단하다. 이번에는 attribute location 1vertex attribute를 구성합니다. 컬러 값은 float 타입 3개의 크기를 가지고 정규화 하지 않는다.

  우리는 이제 2개의 vertex attribute를 가지고 있기 때문에 stride 값을 다시 계산해야 한다. 데이터 배열의 다음 attribute 값(다음 위치 vector의 x 요소)을 받기위해 float 타입 크기를 6 번 오른쪽으로 이동해야 하고 그 6개 중의 3개는 위치 값이고 나머지 3개는 컬러 값이다. 이로인해 stride 값은 float 크기의 6배다(= 24 바이트).
  또한 이번에는 offset를 지정해야 한다. 각각의 vertex에 대하여 위치 vertex attribute는 첫 번째이므로 offset을 0으로 설정한다. color attribute는 위치 데이터 다음부터 시작하므로 offset은 3 * sizeof(float) 입니다(= 12 바이트).

 

이 그림에 대한 출력을 생각해보자 fragment inerpolation

 

Textures

텍스처는 오브젝트에 세부 정보를 추가하는 데에 사용되는 2D Image이다.

vertex에 대한 세부내용을 넣지 않아도 오브젝트가 세밀하게 묘사되어 있다는 착각을 줄 수 있다.

 

 

Texture Wrapping

  텍스처 좌표는 일반적으로 (0,0)에서 (1,1)까지이지만 만약 범위 밖의 좌표를 지정하면 어떻게 될까요? 정답은

 OpenGL의 기본 동작은 텍스처 이미지를 반복하는 것이다(기본적으로 텍스처 좌표의 정수 부분을 무시합니다). 

 

  • GL_REPEAT: 텍스처의 기본 동작입니다. 이미지를 반복한다.
  • GL_MIRRORED_REPEAT: GL_REPEAT와 같지만 반복할때마다 이미지를 반대로 뒤집는다.
  • GL_CLAMP_TO_EDGE: 0과 1 사이의 좌표를 고정합니다. 결과적으로 큰 좌표가 가장자리에 고정되어 가장자리의 패턴이 늘어나게 된다다.

GL_CLAMP_TO_BORDER: 범위 밖의 좌표에 사용자가 지정한 테두리 색이 지정된다.

Texture Filtering

 

 GL_NEAREST (nearest neighbor filtering라고도 불림)는 OpenGL의 기본적인 텍스처 필터링 방법입니다. GL_NEAREST로 설정하면 OpenGL은 가운데가 텍스처 좌표에 가장 가까운 픽셀을 선택한다. 

 

GL_LINEAR ((bi)linear filtering이라고도 불림) 은 텍스처 좌표의 이웃한 텍셀에서 보간된 값을 가져와 텍셀 사이의 색상근사치를 가져온다. 텍스처 좌표에서 텍셀의 중심까지의 거리가 가까울수록 해당 텍셀의 색상이 샘플링 된 색상에 더많이 혼합됩니다. 

 

Mipmaps

오브젝트가 멀리 떨어져 있어서 몇개의 fragment만 생성하기 때문에 OpenGL은 텍스처의 대부분을 차지하는 fragment를 위한 텍스처 색상을 선택해야하므로 고해상도 텍스처에서 해당 fragment의 올바른 색상 값을 가져오는 데에 어려움을 겪는 것을 해결해준다. 

 

mipmap (texture 매핑할때 렌더링 속도를 향상시키기 위한 목적)

시점에서 특정 거리의 임계 값을 넘으면 OpenGL은 오브젝트까지의 거리에 가장 적합한 mipmap 텍스처를 사용하게 된다.각 텍스처 이미지에 대한 mipmap 텍스처 모음을 생성하는 것은 직접하기에는 번거롭지만, OpenGL은 텍스처를 생성한 후 glGenerateMipmaps 함수를 호출하면 모든 작업을 수행할 수 있다. 

 

OpenGL은 두 mipmap 레이어 사이에 가장자리가 선명하게 나타나는 것과 같은 일부 결함을 나타낼 수도 있습니다. 일반적인 텍스처 필터링과 마찬가지로 mipmap 레벨을 전환하기 위해 NEAREST  LINEAR 필터링을 사용하여 mipmap 레벨 사이를 필터링 할 수도 있습니다. mipmap 레벨 사이의 필터링 방법을 지정하기 위해 원래의 필터링 방법을 다음 네 가지 옵션 중 하나로 대체할 수 있다.

 

  • GL_NEAREST_MIPMAP_NEAREST: nearest neighbor 보간법으로 mipmap을 필터링하고 텍스처 샘플링도 nearest neghbor 보간법을 사용합니다.
  • GL_LINEAR_MIPMAP_NEAREST: nearest neighbor 보간법으로 mipmap을 필터링하고 텍스처 샘플링은 linear 보간법을 사용합니다.
  • GL_NEAREST_MIPMAP_LINEAR: linear 보간법으로 mipmap을 필터링하고 텍스처 샘플링은 nearest neighbor 보간법을 사용합니다.
  • GL_LINEAR_MIPMAP_LINEAR: linear 보간법으로 mipmap을 필터링하고 텍스처 샘플링도 linear 보간법을 사용합니다.

 

텍스처 로드 및 생성

stb_image.h는 가장 많이 쓰이는 파일 형식을 로드할 수 있고 프로젝트에 쉽게 통합할 수 있는싱글 헤더 이미지로드 라이브러리이다.

 

 

텍스처 생성

OpenGL의 객체들과 마찬가지로 텍스처는 ID로 참조한다.

  glGenTextures 함수는 먼저 우리가 생성하고자 하는 텍스처의 갯수를 첫 번째 파라미터로 받고 두 번째 파라미터로 주어진 unsigned int 배열에 텍스처들을 저장한다(이 경우에는 하나의 unsigned int). 다른 객체들과 마찬가지로 바인딩 해야합니다.

 

바인딩 후 -> 이미지 데이터를 사용하여 텍스처를 생성한다.  glTextImage2D 함수를 사용함

  • 첫 번째 파라미터는 텍스처 타겟을 지정한다. 이를 GL_TEXTURE_2D로 설정한다는 것은 현재 GL_TEXTURE_2D로 바인딩된 텍스처 객체에 텍스처를 생성하겠다는 뜻이다(그래서 GL_TEXTURE_1D나 GL_TEXTURE_3D로 바인딩된 객체에는 아무런 영향을 끼치지 않는다).
  • 두 번째 파라미터는 우리가 생성하는 텍스처의 mipmap 레벨을 수동으로 지정하고 싶을 때 지정합니다. 하지만 우리는 베이스 레벨일 0로 남겨두겠다. ++ 1로하면 오류가 발생함 
  • 세 번째 파라미터는 OpenGL에게 우리가 저장하고 싶은 텍스처가 어떤 포멧을 가져야 할지 알려줍니다. 우리의 이미지는 오직 RGB 값만 가지고 있으므로 텍스처를 RGB 값과 함께 저장한다.
  • 네 번째, 다섯 번째 파라미터는 결과 텍스처의 너비와 높이를 설정합니다. 우리는 이미지를 로딩할 때 이미 저장해두었으므로 해당 변수들을 사용한다.
  • 그 다음 파라미터는 항상 0을 지정해야한다.
  • 일곱 번째, 여덟 번째 파라미터는 원본 이미지의 포멧과 데이터타입을 지정한다. 우리는 RGB 값이 있는 이미지를 로드했고 chars(bytes)로 저장하였으므로 해당하는 값으로 설정한다.
  • 마지막 파라미터는 실제 이미지 데이터다.

 

glTexImage2D 함수를 한번 호출하면 현재 바인딩된 텍스처 객체가 첨부된 텍스처 이미지를 가진다. 

현재는 베이스 레벨의 텍스처 이미지만 로드되었고, 만약 우리가 mipmap을 사용하고 싶으면 모든 여러가지 이미지들을 직접 지정 하거나, 텍스처를 생성한 후 glGenerateMipmap함수를 사용해야한다. -> 현재 바인딩된 텍스처에 대해 필요한 모든 mipmap들을 자동으로 생성해준다. 

 

생성한후 이미지의 메모리는 반환해준다.

텍스처의 생성과정

 

 

 

728x90

'opengl' 카테고리의 다른 글

<자료구조> 큐(queue),덱(deque)  (0) 2023.06.01
[OpenGL] LearnOpenGL 정리본 4~5  (0) 2022.07.23
[OpenGL] LearnOpenGL 정리 본 (1~4)  (0) 2022.07.18
그래픽스 스터디  (0) 2022.07.12