개발/OpenGL / / 2022. 3. 12. 13:48

OpenGL 공부일지 - OpenGL Super Bible 텍스처 - 2

반응형

Sampler Types

텍스처의 차원마다 텍스처 객체가 바인딩될 수 있는 타깃이 존재한다고 하였다. 그런데 타깃은 쉐이더에서 사용할 수 있는 해당 샘플러 타입도 있다.

위 표와 같은 종류들의 타깃들이 있는데, 예를들어 1D 텍스터를 생성하고 쉐이더에서 사용하려면 새 텍스처 이름을 GL_TEXTURE_1D 타깃에 바인딩하고 쉐이더의 smapler1D 변수를 사용해서 읽어야하는 식이다.

GLSL의 샘플러 타입은 정수형인지 부동소수점 데이터인지에 대해서 변수 표현방식도 u,i 가 붙는 등 다르다.

 

이전 포스팅에서 봤든 쉐이더에서 텍스처를 읽을 때 texelFetch 내장함수를 사용한다.

vec4 texelFetch(sampler1D s, int P, int lod);
vec4 texelFetch(sampler2D s, ivec2 P, int lod);
ivec4 texelFetch(isampler2D s, ivec2 P, int lod);
uvec4 texelFetch(usampler3D s, ivec3 P, int lod);

위와 같은 예시로 오버로딩이 많다.

모든 텍스처 함수는 4요소 RGBA를 반환한다. 만약 반환 값의 채널이 4보다 작으면 RGBA의 GB에는 default로 0이, A에는 1이 채워진다. 

Loading Textures from Files

이미지는 보통 디스크에 저장되거나 네트워크로부터 다운 받을 것이다. 텍스처를 하드코딩된 배열로 변환하거나 또는 파일로부터 애플리케이션에 로딩하거나 해야한다.

 이미지 파일 포맷은 많다. 압축의 여부도 다양하다. opengl의 모든 포멧을 지원하면서 밉맵이나 큐브 맵등의 기능을 지원하는 포멧은 .KTX라는 포멧이 있다.

KTX 포멧은 Khronos TeXure format이라고 하며, 텍스처 함수에 전달할 대부분의 인자를 포함하므로 파일의 텍스처를 직접 로딩가능하다.

struct header
{
    unsigned char identifier[12];
    unsigned int endianness;
    unsigned int gltype;
    unsigned int gltypesize;
    unsigned int glformat;
    unsigned int glinternalformat;
    unsigned int glbaseinternalformat;
    unsigned int pixelwidth;
    unsigned int pixelheight;
    unsigned int pixeldepth;
    unsigned int arrayelements;
    unsigned int faces;
    unsigned int miplevels;
    unsigned int keypairbytes;
};

 

 

참고로 위 코드는 .ktx 파일의 헤더이다.

각 요소에 대해서는 필요한 경우에 알아보도록 한다.

 

// Generate a name for the texture
glGenTextures(1, &texture);

// Load texture from file
sb7::ktx::file::load("media/textures/icemoon.ktx", texture);

.ktx 포멧은 opengl기반 애플리케이션을 위해 고안되어 직관적이다.

위 코드를 보자.

새로운 텍스처 이름을 예약하고 ktx파일 이름과 같이 로더에 전달하면 된다. 

로더는 텍스처를 해당 타깃에 바인딩하고 ktx파일로부터 데이터를 로딩한다.

 

현재 해당 경로의 ktx파일을 구할 수 없어 예제코드를 실행할 수 없다. 나중에 처리해보아야겠다.

Texture Coordinates

이전에는 프래그먼트의 윈도우 공간 좌표를 위치로 사용하고 이 위치의 텍스처를 읽었는데, 프래그먼트 쉐이더에서는 아무 값이나 사용가능하지만, 보통 OpenGL에 의해 각 프리미티브 사이에 부드럽게 보간된 입력값 중 하나를 사용한다. 이러한 것이 버텍스 쉐이더의 역할이다. 일반적으로 텍스처 좌표를 버텍스 입력에서 얻어와서 그대로 전달한다. 

 프래그먼트 쉐이더에서 여러 텍스처를 사용하면, 텍스처 별로 고유한 좌표를 사용할 수 있지만, 대부분의 경우 모든 텍스처에 대해 하나의 텍스처 좌표만 사용한다.

#version 450 core

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

layout (location = 0) in vec4 position;
layout (location = 4) in vec2 tc;

out VS_OUT
{
	vec2 tc;
} vs_out;

void main(void)
{
    // Calculate the position of each vertex
    vec4 pos_vs = mv_matrix * position;
    
    // Pass the texture coordinate through unmodified
    vs_out.tc = tc;
    
    gl_Position = proj_matrix * pos_vs;
}

위 코드는 하나의 텍스처 좌표를 받아 그대로 프래그먼트 쉐이더로 전달하는 버텍스 쉐이다.

#version 450 core
layout (binding = 0) uniform sampler2D tex_object;

// Input from vertex shader
in VS_OUT
{
	vec2 tc;
} fs_in;

// Output to framebuffer
out vec4 color;

void main(void)
{
    // Simply read from the texture at the (scaled) coordinates and
    // assign the result to the shader's output.
    color = texture(tex_object, fs_in.tc * vec2(3.0, 1.0));
}

위 쉐이더는 버텍스 쉐이더로 생성된 텍스처 좌표를 입력으로 받아 스케일한다. 

버텍스의 텍스처 좌표를 전달하는 것으로 객체 주위로 텍스처를 감쌀 수 있다. 

 

(github 소스코드에서 해당 예제는 simpletexcoords project이다)

...하지만 ktx 파일도, sbm 파일도 해당 경로에 리소스가 존재하지 않아 실행할 수 없다.

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유