WebGL-9

WebGL ( 9 - Texture 2D )

이번장에선 WebGL Texture에 대해 설명하려고 합니다.
텍스처란 우리가 만든 프로그램내에서 평면이나 3D화면에 적용하는 이미지를 말합니다.
이미지를 적용할때 보통은 텍스처를 입힌다고 많이 표현합니다.

텍스처로 사용하는 이미지는 비트맵으로 존재할 수 있고, 절차적으로 생성하여 사용할 수 도 있습니다. ( 이미지 사용 or 그려서 사용 )

보통 텍스처를 입히는 과정에서 스케일 조정, 늘이기, 왜곡 및 반복등을 사용하여 더욱더 입체적인 표현을 할 수 있게해줍니다.
보통 텍스처의 너비와 높이는 같은값을 사용하며, 64, 128, 256, 512같은 2의 거듭제곱 크기 입니다.

텍스처에도 좌표를 사용하게되는데 정점의 위치와 달리 (x,y)좌표 대신 (s,t)좌표로 나타내고 이 좌표를 텍셀이라고 표현하는데,
텍셀은 텍스처 요소(texture element), 텍스처 픽셀(texture pixel)의 약어 입니다.

텍스처 좌표는 (0,0)에서 부터 (1,1)로 제한되는데, 위에서 말한 거듭제곱 크기를 예를 들어
128 x 128 픽셀 크기의 텍스처의 경우에는 이를 범위내에서 표현하기 위해 모든점은 128로 나누게 됩니다.

이로인하여 예를들어 (0.5, 0.25)좌표는 (64, 32) 텍셀을 나타낸다고 할 수 있습니다.

texture

이제부터는 본론으로 들어 텍스처 객체를 생선하고 바인딩을 해보도록 하겠습니다.
WebGL Texture를 생성하고 바인딩하는 코드는 아래와 같습니다.

1
2
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);

텍스처 타겟의 종류는 TEXTURE_2D 이외에도
TEXTURE_1D, TEXTURE_3D, 또는 TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_RECTANGLE, TEXTURE_CUBE_MAP, TEXTURE_BUFFER, TEXTURE_2D_MULTISAMPLE또는 TEXTURE_2D_MULTISAMPLE_ARRAY
등이 존재하지만 이번장에서는 TEXTURE_2D만 사용해보겠습니다.

특정 texture가 제대로 로드됐는지 확인할 때는 아래와 같이 isTexture 메서드를 사용하면 됩니다.

1
2
3
if(!gl.isTexture(this.texture)) {
console.error("텍스처가 잘못 로드되었습니다.");
}

텍스처 데이터를 채울 때 가장 많이 사용하는 방법은 이미지파일로부터 텍스처 데이터를 로드하는 것입니다.

우선 텍스터 이미지 데이터를 보관할 변수를 선언하여줍니다.
그리고 텍스처 이미지를 로드 하기 위해 Image 객체를 사용합니다.

1
2
3
4
5
6
7
8
9
var textureImage = null;
function loadTexture() {
textureImage = new Image();
textureImage.onload = function() {
setupTexture();
}

textureImage.src = './images/images.jpg'
}

loadTexture 메서드에서는 Image 객체를 생성하고 onload 이벤트를 설정하여 이미지가 textureImage.src에 대입될때
로드가되면 setupTexture 메서드를 호출하도록 작성합니다. 제일 중요한 텍스처 설정에 대한 내용은 setupTexture 메서드에 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
function setupTexture() {
texture = gl.createTexture(); // 텍스처 생성
gl.bindTexture(gl.TEXTURE_2D, texture); // 텍스처 바인드
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
// true 인 경우 수직 축을 따라 소스 데이터를 뒤집습니다.
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureImage);
// 텍스터 객체를 생성하고 TEXTURE_2D에 바인딩 한 후 이미지 데이터가 로딩된 이미지객체인
// textureImage를 texImage2D()에 전당하여 오출하면, 이미지 데이터가 텍스처에 쓰여집니다.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
// 텍스쳐를 위한 필터링을 준비합니다.
// 필터링은 이미지 크기가 변경될 때 이미지가 필터되는 방식을 제어합니다.
}
  • pixelStorei : 웹지엘에게 데이터를 저장하는법을 알려줌
  • texParameteri : 텍스처 필터링 및 래핑을 처리하는 옵션을 설정

텍스처 설정은 먼저
createTexture 메서드를 통하여 텍스처를 생성하고 TEXTURE_2D에 바인드합니다.
그리고 pixelStorei 메서드를 호출하여 웹지엘에서 텍스처 데이터를 저장하는 방식을 조절합니다.

pixelStorei 옵션으로 UNPACK_FLIP_Y_WEBGL을 true로 설정하면 수직 Y축으로 소스데이터를 뒤집어줍니다.
이렇게 하면 데이터의 마지막행이 첫번째로 전송되는 행이되는데 이 옵션을 true로 하여 뒤집는 이유는 HTML 이미지에서
로드한 데이터가 웹지엘의 방향과 Y축점이 반대로 되어있기 때문에 해당 옵션을 사용하지 않으거나 false값을 설정한다면 이미지가 뒤집어져 보이게 됩니다.
(웹지엘에서 텍스처를 입힐때 왼쪽 하단부터 0,0이기 때문에 Y축이 반대입니다.)
texture

texParameteri는 2번째 인자에 따라 텍스처 필터링과 밉래핑으로 나뉩니다.

텍스처 필터링은 크게 두 종류가 있고 종류에는 확대와 축소가 있습니다.

필터링

TEXTURE_MIN_FILTER (축소)

1
2
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
// 기본 값 - NEAREST_MIPMAP_LINEAR

축소의 경우 하나의 픽셀이 많은 영역의 텍셀에 대응할 경우 생기는 계단 현상을 유발하게되고,
3번쨰 인자가 LINEAR를 사용하여도 동일한 계단 현상이 나타나게 됩니다.
블록화 계단현상

texture

TEXTURE_MAG_FILTER (확대)

1
2
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
// 기본 값 - LINEAR 이기때문에 아무것도 입력안하면 이미지가 번저보입니다.

확대의 경우 텍스처 좌표에서 가장 가까운 텍셀값을 가져오기때문에 너무 많이 확대되면 블록화 현상이 생깁니다.
그러나 3번쨰 인자가 LINEAR라면 텍스처 좌표 주변의 4개 텍셀의 평균값으로 필터링하기 문에 이미지가 번저보이는 현상이 생깁니다.

texture

랩핑(매핑)

텍스처가 정사각형이던 아니던, 텍스처의 좌하단은 (0,0), 우상단은 (1,1)입니다.
그러나 사용자가 이 범위를 벗어나는 좌표를 사용할 때가 있는데, 웹지엘은 이를 텍스처 랩 모드에 따라서 처리합니다.

texParameteri 메소드에 2번째 인자로 TEXTURE_WRAP_S 혹은 TEXTURE_WRAP_T를 사용하여 S방향과 T방향에
각각 독립적으로 텍스처 랩모드를 설정할 수 있고 texParameteri 메서드의 3번째 인자로 설정하게 됩니다.

Default으로 아무것도 명시하지 않는다면 gl.REPEAT값이 적용됩니다.

  • REPEAT 랩 모드 예시
    (바둑판식으로 이미지를 반복합니다.)
1
2
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);

texture

  • MIRRORED_REPEAT 랩 모드 예시
    ( S or T 축을 기준으로 거울처럼 반전하면서 같은 이미지를 반복합니다.)
    1
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);

texture

1
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);

texture

  • CLAMP_TO_EDGE 랩 모드 예시
    (모서리 픽셀을 늘려서 확장시킵니다.)
1
2
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

texture

1
2
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

texture

이외에도 다른 옵션들이 존재하고, 다른 옵션들의 내용은
https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texParameter
아래의 링크에서 확인하시길 바랍니다.

그리고 텍스처 이미지는 아래의 주소에서 편하게 이용할 수 있습니다.


다음장에선 3D입체 오브젝트에 텍스처를 입혀보는 내용을 다루도록 하겠습니다.


Comments: