Graphics Programming

텍스처(Texture) 본문

Season 1/OpenGL

텍스처(Texture)

minseoklee 2015. 10. 3. 01:48

텍스처

- 셰이더가 읽고 쓸 수 있는 구조화된 저장 형태

- 주로 이미지 데이터를 저장하는 데 쓰임

 

사용법

1. 이름을 생성한다

2. 텍스처 타겟에 그 이름을 바인딩한다

3. 원하는 이미지 크기를 명시한다

 

종류 - 1D, 2D, 3D, rectangle

 

텍스처 읽기

- 텍스처는 샘플러 변수(sampler variable)로 표현된다

- 2D 텍스처 => sampler2D

 

uniform sampler2D s;

out vec4 color;

void main() {

  color = texelFetch(s, ivec2(gl_FragCoord.xy), 0);

}

 

sampler1D, sampler2D, ... => floating-point

prefix i => integer(signed)

prefix u => unsigned integer

 

텍스처 읽기 제어 - 래핑wrapping, 필터링filtering 모드

 

매개변수들은 sampler 개체에 저장된다

glGenSamplers(GLsizei n, GLuint *samplers)

glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)

glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)

sampler 개체를 타겟에 바인딩하지 않아도 직접 수정할 수 있다

 

샘플러 개체를 텍스처 유닛에 바인딩하기

glBindSampler(GLuint uint, GLuint sampler)

 

각 텍스처는 샘플러 개체를 내장한다

void glTexParameterf(GLenum target, GLenum pname, GLfloat param)

void glTexParameteri(GLenum target, GLenum pname, GLint param)

 

여러 텍스처 사용

- 샘플러 유니폼을 여러 개 생성한다

- 각각 다른 텍스처 유닛을 참조하도록 설정한다

- 몇 개까지 지원하는가?

  GLint maxUnits;

  glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxUnits);

  => 셰이더 스테이지들 중 임의의 한 시점에서 접근 가능한 텍스처 유닛 최대 개수

- 텍스처를 텍스처 유닛에 바인딩하기: active texture unit selector를 변경해야 한다

  glActiveTexture(GL_TEXTURE0 + offset)

- GL_TEXTURE1 ~ 31까지는 정의되어 있음

- 샘플러 유니폼들이 다른 유닛들을 참조하게 하는 방법

  1. glUniform1i() with glGetUniformLocation()

  2. layout(binding = 0) uniform sampler2D foo // 추천

 

텍스처 필터링: 실제로는 텍셀과 픽셀이 일대일로 매칭될 일이 거의 없다

- texelFetch(): 특정 정수 텍스처 좌표에서 단일 텍셀을 가져온다

- 더 유연한 함수로 texture()가 있다

- 텍스처 늘이기 = maginifcation -> GL_TEXTURE_MAG_FILTER

- 텍스처 줄이기 = minification -> GL_TEXTURE_MIN_FILTER

- 기본 필터: GL_NEAREST, GL_LINEAR

  * 기본 필터링은 밉맵 없이는 작동하지 않는다

- glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

 

밉매핑

- 일반적인 텍스처 매핑의 흔한 문제점

  1. scintillation (계단현상)

  2. performance (띄엄띄엄 하는 추출)

  물체는 작을 때 텍스처는 클 때

- 밉매핑 수준 결정

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0)

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4)

 

밉맵 필터링

- minification의 경우

  - GL_NEAREST_MIPMAP_NEAREST - nearest mipmap, nearest neighbor sampling

  - GL_NEAREST_MIPMAP_LINEAR - 밉맵간 보간, 최단 이웃 샘플링

  - GL_LINEAR_MIPMAP_NEAREST

  - GL_LINEAR_MIPMAP_LINEAR

- magnification의 경우 GL_NEAREST와 GL_LINEAR만 가능

- GL_LINEAR_MIPMAP_LINEAR를 trilinear 밉매핑이라고 부르기도 한다

 

밉맵 얻는 방법

- 모든 밉맵 수준을 직접 그린다

- OpenGL이 생성하도록 한다: glGenerateMipmap(GLenum target)

 

텍스터 wrap

- glSamplerParameteri(param, value)

  - param: GL_TEXTURE_WRAP_S,T,R

  - value: GL_REPEAT, MIRRORED_REPEAT, CLAMP_TO_EDGE, CLAMP_TO_BORDER

  - S는 1D,2D,3D에, T는 2D,3D에, R은 3D에 영향을 준다

  - clamp to border의 경우 색상 설정은 glSamplerParameterfv()에 GL_TEXTURE_BORDER_COLOR를 인자로

 

array texture: 여러 개의 1D, 2D, 큐브맵 이미지를 하나의 텍스처 개체에 적재

- 둘 이상의 이미지를 하나의 텍스처에 담기는 새로운 개념이 아니다

  - 밉매핑: 각 밉 수준은 별개의 이미지

  - 큐브매핑: 각 면이 고유의 이미지와 밉 수준을 가진다

- 그럼 텍스처 배열은 무엇인가?

  - 텍스처 이미지의 배열이 하나의 텍스처 개체에 바인딩되고 셰이더는 인덱스를 통해 접근한다

  - 종류: 1D, 2D, 큐브맵 배열 텍스처. 단 3D 배열 텍스처는 없음

- 2D 배열 텍스처와 3D 텍스처의 차이점

  - 배열 텍스처의 레이어 사이에는 필터링이 적용되지 않는다

 

- 2D 배열 텍스처 불러오기

GLuint tex;

glGenTextures(1, &tex);

glBindTexture(GL_TEXTURE_2D_ARRAY, tex);

glTexStorage3D(GL_TEXTURE_2D_ARRAY, 8, GL_RGBA8, 256, 256, 100);

for(int i=0; i<100; i++){

  glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, 256, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, image_data[i]);

}

Comments