1 Getting started 6 Textures - JJhuk/LearnOpenGL GitHub Wiki

LearnOpenGL - Textures

url: https://learnopengl.com/Getting-started/Textures 생성일: 2021λ…„ 1μ›” 2일 μ˜€ν›„ 3:16

μš°λ¦¬λŠ” μ˜€λΈŒμ νŠΈμ— 더 λ§Žμ€ λ””ν…ŒμΌμ„ μΆ”κ°€ν•˜κΈ° μœ„ν•΄ 각 λ²„ν…μŠ€μ— 색상을 μ‚¬μš©ν•˜μ—¬ ν₯미둜운 이미지λ₯Ό λ§Œλ“€ 수 μžˆλ‹€λŠ” 것을 λ°°μ› μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 사싀감을 더 μ–»κΈ° μœ„ν•΄μ„  더 λ§Žμ€ 색상을 지정할 수 μžˆλ”λ‘ λ§Žμ€ λ²„ν…μŠ€κ°€ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. 각 λͺ¨λΈμ—λŠ” 훨씬 더 λ§Žμ€ λ²„ν…μŠ€λ“€μ΄ ν•„μš”ν•˜κ³  각 λ²„ν…μŠ€μ— λŒ€ν•΄ 삭상 속성도 ν•„μš”ν•˜κΈ° λ•Œλ¬Έμ— 이것은 μƒλ‹Ήν•œ μ–‘μ˜ μΆ”κ°€ μ˜€λ²„ν—€λ“œλ₯Ό μ°¨μ§€ν•©λ‹ˆλ‹€.

μ•„ν‹°μŠ€νŠΈμ™€ ν”„λ‘œκ·Έλž˜λ¨Έκ°€ 일반적으둜 μ„ ν˜Έν•˜λŠ” 것은 ν…μŠ€μ³λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. ν…μŠ€μ³λŠ” κ°œμ²΄μ— μ„ΈλΆ€ 정보λ₯Ό μΆ”κ°€ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” 2D이미지 (1D및 3D도 μ‘΄μž¬ν•¨)μž…λ‹ˆλ‹€. (예λ₯Όλ“€μ–΄) ν…μŠ€μ³λ₯Ό 멋진 벽돌 이미지가 μžˆλŠ” 쒅이 ν•œμž₯으둜 μƒκ°ν•˜λ©΄ 3D 집 μœ„μ— κΉ”λ”ν•˜κ²Œ μ ‘ν˜€μ„œ 집에 벽돌 외관이 μžˆλŠ” 것 처럼 λ³΄μž…λ‹ˆλ‹€. 단일 이미지에 λ§Žμ€ λ””ν…ŒμΌμ„ μ‚½μž… ν•  수 있기 λ•Œλ¬Έμ— μΆ”κ°€ λ²„ν…μŠ€λ₯Ό μ§€μ •ν•˜μ§€ μ•Šκ³ λ„ μ˜€λΈŒμ νŠΈκ°€ 맀우 μ„Έλ°€ν•œ λŠλ‚Œμ„ 쀄 수 μžˆμŠ΅λ‹ˆλ‹€.

이미지 μ˜†μ— μžˆλŠ” ν…μŠ€μ³λ₯Ό μ‚¬μš©ν•˜μ—¬ μ…°μ΄λ”λ‘œ 보낼 λŒ€λŸ‰μ˜ μž„μ˜ 데이터 μ»¬λ ‰μ…˜μ„ μ €μž₯ν•˜λŠ” 데도 μ‚¬μš©ν•  수 μžˆμ§€λ§Œ λ‹€λ₯Έ 주제둜 λ„˜μ–΄κ°€κ² μŠ΅λ‹ˆλ‹€.

μ•„λž˜μ—μ„œ 이전 μž₯μ—μ„œ μ‚Όκ°ν˜•μ΄ 맀핑 된 벽돌벽 의 ν…μŠ€μ³ 이미지λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

textures

ν…μŠ€μ³λ₯Ό μ‚Όκ°ν˜•μ— λ§€ν•‘ν•˜λ €λ©΄ μ‚Όκ°ν˜•μ˜ 각 꼭지점에 ν•΄λ‹Ήν•˜λŠ” ν…μŠ€μ³ 뢀뢄을 μ•Œλ €μ•Ό ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 각 λ²„ν…μŠ€μ—λŠ” ν…μŠ€μ³ μ΄λ―Έμ§€μ—μ„œ μƒ˜ν”Œλ§ν•  뢀뢄을 μ§€μ •ν•˜λŠ” ν…μŠ€μ³ μ’Œν‘œκ°€ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. ν”„λ ˆκ·Έλ¨ΌνŠΈ 보간은 λ‚˜λ¨Έμ§€ ν”„λ ˆκ·Έλ¨ΌνŠΈμ— λŒ€ν•΄ λ‚˜λ¨Έμ§€λ₯Ό μˆ˜ν–‰ν•©λ‹ˆλ‹€.

ν…μŠ€μ³ μ’Œν‘œλŠ” x 및 y μΆ•μ˜ 0 μ—μ„œ 1 κΉŒμ§€ μž…λ‹ˆλ‹€. (2D ν…μŠ€μ³ 이미지λ₯Ό μ‚¬μš©ν•œλ‹€λŠ” 점을 κΈ°μ–΅ν•˜μ„Έμš”.) ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό μ‚¬μš©ν•˜μ—¬ ν…μŠ€μ²˜ 색상을 κ²€μƒ‰ν•˜λŠ” 것을 μƒ˜ν”Œλ§μ΄λΌκ³  ν•©λ‹ˆλ‹€. ν…μŠ€μ²˜ μ’Œν‘œλŠ” ν…μŠ€μ²˜ μ΄λ―Έμ§€μ˜ μ™Όμͺ½ ν•˜λ‹¨μ— λŒ€ν•œ (0,0) μ—μ„œ μ‹œμž‘ν•˜μ—¬ ν…μŠ€μ²˜ μ΄λ―Έμ§€μ˜ 였λ₯Έμͺ½ 상단에 λŒ€ν•œ (1,1) κΉŒμ§€μž…λ‹ˆλ‹€. λ‹€μŒ μ΄λ―Έμ§€λŠ” ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό μ‚Όκ°ν˜•μ— λ§€ν•‘ν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€. λ‹€μŒ μ΄λ―Έμ§€λŠ” ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό μ‚Όκ°ν˜•μ— λ§€ν•‘ν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€.

tex_coords

μ‚Όκ°ν˜•μ— λŒ€ν•΄ 3개의 ν…μŠ€μ²˜ μ’Œν‘œ 점을 μ§€μ •ν•©λ‹ˆλ‹€. μ‚Όκ°ν˜•μ˜ μ™Όμͺ½ ν•˜λ‹¨μ΄ ν…μŠ€μ²˜μ˜ μ™Όμͺ½ ν•˜λ‹¨κ³Ό μΌμΉ˜ν•˜κΈ°λ₯Ό μ›ν•˜λ―€λ‘œ μ‚Όκ°ν˜•μ˜ μ™Όμͺ½ ν•˜λ‹¨ λ²„ν…μŠ€μ— (0.0) ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. (1,0) ν…μŠ€μ²˜ μ’Œν‘œκ°€ μžˆλŠ” 였λ₯Έμͺ½ ν•˜λ‹¨μ—λ„ λ™μΌν•˜κ²Œ μ μš©λ©λ‹ˆλ‹€. μ‚Όκ°ν˜•μ˜ 상단은 ν…μŠ€μ²˜ μ΄λ―Έμ§€μ˜ 상단 쀑앙과 μΌμΉ˜ν•΄μ•Ό ν•˜λ―€λ‘œ (0.5, 1.0) 을 ν…μŠ€μ²˜ μ’Œν‘œλ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€. λ²„ν…μŠ€ 셰이더에 3개의 ν…μŠ€μ²˜ μ’Œν‘œλ§Œ μ „λ‹¬ν•˜λ©΄ λ©λ‹ˆλ‹€. 그러면 각 ν”„λ ˆκ·Έλ¨ΌνŠΈμ˜ λͺ¨λ“  ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό κΉ”λ”ν•˜κ²Œ λ³΄κ°„ν•˜λŠ” ν”„λ ˆκ·Έλ¨ΌνŠΈ μ…°μ΄λ”λ‘œ μ „λ‹¬λ©λ‹ˆλ‹€.

κ²°κ³Ό ν…μŠ€μ²˜ μ’Œν‘œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

float texCoords[] = {
    0.0f, 0.0f,  // μ™Όμͺ½ μ•„λž˜ 꼭지점  
    1.0f, 0.0f,  // 였λ₯Έμͺ½ μ•„λž˜ 꼭지점
    0.5f, 1.0f   // 쀑앙 상단 꼭지점
};

νƒμŠ€μ²˜ μƒ˜ν”Œλ§μ€ 해석이 λŠμŠ¨ν•˜μ—¬ λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ OpenGLμ—κ²Œ ν…μŠ€μ²˜λ₯Ό μƒ˜ν”Œλ§ ν•˜λŠ” 방법을 μ•Œλ €μ£ΌλŠ” 것이 우리의 μž„λ¬΄μž…λ‹ˆλ‹€.

Texture Wrapping

ν…μŠ€μ²˜ μ’Œν‘œλŠ” 일반적으둜 (0, 0) μ—μ„œ (1,1) κΉŒμ§€ μ΄μ§€λ§Œ λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ μ’Œν‘œλ₯Ό μ§€μ •ν•˜λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”? OpenGL의 κΈ°λ³Έ λ™μž‘μ€ ν…μŠ€μ²˜ 이미지λ₯Ό λ°˜λ³΅ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. (기본적으둜 뢀동 μ†Œμˆ˜μ  ν…μŠ€μ²˜ μ’Œν‘œμ˜ μ •μˆ˜ 뢀뢄을 λ¬΄μ‹œν•¨.) OpenGL이 μ œκ³΅ν•˜λŠ” 더 λ§Žμ€ μ˜΅μ…˜μ΄ μžˆμŠ΅λ‹ˆλ‹€.

  • GL_REPEAT : ν…μŠ€μ³μ˜ κΈ°λ³Έ λ™μž‘μž…λ‹ˆλ‹€. ν…μŠ€μ²˜ 이미지λ₯Ό λ°˜λ³΅ν•©λ‹ˆλ‹€.
  • GL_MIRRORED_REPEAT : GL_REPEAT와 κ°™μ§€λ§Œ 반볡 ν•  λ•Œλ§ˆλ‹€ 이미지λ₯Ό λ―ΈλŸ¬λ§ν•©λ‹ˆλ‹€.
  • GL_CLAMP_TO_EDGE : 0 κ³Ό 1 사이 μ’Œν‘œλ₯Ό κ³ μ •ν•©λ‹ˆλ‹€. κ·Έ κ²°κ³Ό 더 높은 μ’Œν‘œκ°€ κ°€μž₯μžλ¦¬μ— κ³ μ •λ˜μ–΄ κ°€μž₯자리 νŒ¨ν„΄μ΄ λŠ˜μ–΄λ‚©λ‹ˆλ‹€.
  • GL_CLAMP_TO_BORDER : 이제 λ²”μœ„ λ°–μ˜ μ’Œν‘œμ— μ‚¬μš©μž 지정 ν…Œλ‘λ¦¬ 색상이 μ§€μ •λ©λ‹ˆλ‹€.

각 μ˜΅μ…˜μ€ κΈ°λ³Έ λ²”μœ„λ₯Ό λ²—μ–΄λ‚œ ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό μ‚¬μš©ν•  λ•Œ λ‹€λ₯Έ μ‹œκ°μ  좜λ ₯을 κ°€μ§‘λ‹ˆλ‹€. μƒ˜ν”Œ μƒ‰μŠ€μ²˜ 이미지 (HΓ³lger Rezende의 원본 이미지)μ—μ„œ 이것이 μ–΄λ–»κ²Œ λ³΄μ΄λŠ”μ§€ λ³΄κ² μŠ΅λ‹ˆλ‹€.

texture_wrapping

μ•žμ„œ μ–ΈκΈ‰ν•œ 각 μ˜΅μ…˜μ€ glTexParameter* ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μ’Œν‘œ μΆ• (s , t (3D ν…μŠ€μ³λ₯Ό μ‚¬μš©ν•˜λŠ” 경우 r) λ‹Ή x , y , z 에 ν•΄λ‹Ή)λ³„λ‘œ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

첫 번째 μΈμˆ˜λŠ” ν…μŠ€μ²˜ λŒ€μƒμ„ μ§€μ •ν•©λ‹ˆλ‹€. 2D ν…μŠ€μ²˜λ‘œ μž‘μ—…ν•˜κ³  μžˆμœΌλ―€λ‘œ ν…μŠ€μ²˜ λŒ€μƒμ€ GL_TEXTURE_2D μž…λ‹ˆλ‹€. λ‘λ²ˆμ§Έ μΈμˆ˜λŠ” μ„€μ •ν•˜λ €λŠ” μ˜΅μ…˜κ³Ό ν…μŠ€μ²˜ 좕을 지정해야 ν•©λ‹ˆλ‹€. S 와 T μΆ• λͺ¨λ‘μ— λŒ€ν•΄ κ΅¬μ„±ν•˜λ €κ³  ν•©λ‹ˆλ‹€. λ§ˆμ§€λ§‰ μΈμˆ˜λŠ” μš°λ¦¬κ°€ μ›ν•˜λŠ” ν…μŠ€μ²˜ λž˜ν•‘ λͺ¨λ“œλ₯Ό μ „λ‹¬ν•˜λ„λ‘ μš”κ΅¬ν•˜λ©°, 이 경우 OpenGL은 GL_MIRRORED_REPEAT둜 ν˜„μž¬ ν™œμ„±ν™” 된 ν…μŠ€μ²˜μ— ν…μŠ€μ²˜ λž˜ν•‘ μ˜΅μ…˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.

GL_CLAMP_TO_BORDER μ˜΅μ…˜μ„ μ„ νƒν•˜λ©΄ ν…Œλ‘λ¦¬ 색상도 지정해야 ν•©λ‹ˆλ‹€. 이것은 GL_TEXTURE_BORDER_COLOR λ₯Ό μ˜΅μ…˜μœΌλ‘œ μ‚¬μš©ν•˜λŠ” glTexParameter ν•¨μˆ˜μ— ν•΄λ‹Ήν•˜λŠ” fv λ₯Ό μ‚¬μš©ν•˜μ—¬ μˆ˜ν–‰λ˜λ©°, μ—¬κΈ°μ—μ„œ ν…Œλ‘λ¦¬μ˜ 색상 κ°’μ˜ 뢀동 배열을 μ „λ‹¬ν•©λ‹ˆλ‹€.


float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);  

Texture Filtering

ν…μŠ€μ³ μ’Œν‘œλŠ” 해상도에 μ˜μ‘΄ν•˜μ§€ μ•Šμ§€λ§Œ 뢀동 μ†Œμˆ˜μ  값이 될 수 μžˆμœΌλ―€λ‘œ OpenGL은 ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό 맀핑 ν•  ν…μŠ€μ²˜ ν”½μ…€ (텍셀이라고도 함)을 νŒŒμ•…ν•΄μ•Ό ν•©λ‹ˆλ‹€. 이것은 맀우 큰 물체와 저해상도 ν…μŠ€μ²˜κ°€ μžˆμ„ 경우 특히 μ€‘μš”ν•©λ‹ˆλ‹€. OpenGL에도 μ΄λŸ¬ν•œ ν…μŠ€μ²˜ 필터링 μ˜΅μ…˜λ„ ν¬ν•¨λ˜μ–΄ μžˆλ‹€κ³  μΆ”μΈ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ—¬λŸ¬ 가지 μ˜΅μ…˜μ„ μ‚¬μš©ν•  수 μžˆμ§€λ§Œ, ν˜„μž¬ κ°€μž₯ μ€‘μš”ν•œ μ˜΅μ…˜μΈ GL_NEAREST 및 GL_LINEAR 에 λŒ€ν•΄ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

GL_NEAREST (κ°€μž₯ κ°€κΉŒμš΄ 이웃 λ˜λŠ” 포인트 필터링이라고도 함)λŠ” OpenGL의 κΈ°λ³Έ ν…μŠ€μ²˜ 필터링 λ°©λ²•μž…λ‹ˆλ‹€. GL_NEAREST 둜 μ„€μ •ν•˜λ©΄ OpenGL은 쀑심이 ν…μŠ€μ²˜ μ’Œν‘œμ— κ°€κΉŒμš΄ 텍셀을 μ„ νƒν•©λ‹ˆλ‹€. μ•„λž˜μ—μ„œ μ‹­μžκ°€κ°€ μ •ν™•ν•œ ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό λ‚˜νƒ€λ‚΄λŠ” 4픽셀을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. μ™Όμͺ½ 상단 텍셀은 ν…μŠ€μ²˜ μ’Œν‘œμ— κ°€μž₯ κ°€κΉŒμš΄ 쀑심을 κ°€μ§€λ―€λ‘œ μƒ˜ν”Œλ§ 된 μƒ‰μƒμœΌλ‘œ μ„ νƒλ©λ‹ˆλ‹€.

Untitled

GL_LINEAR ((이쀑) μ„ ν˜• 필터링이라고도 함)은 ν…μŠ€μ²˜ μ’Œν‘œμ˜ 인접 ν…μ…€μ—μ„œ 보간 된 값을 가져와 텍셀 μ‚¬μ΄μ˜ 색상을 κ·Όμ‚¬ν•©λ‹ˆλ‹€. ν…μŠ€μ²˜ μ’Œν‘œμ—μ„œ 텍셀 μ€‘μ‹¬κΉŒμ§€μ˜ 거리가 μž‘μ„μˆ˜λ‘ ν•΄λ‹Ή ν…μ…€μ˜ 색상이 μƒ˜ν”Œλ§ 된 색상에 더 많이 κΈ°μ—¬ν•©λ‹ˆλ‹€. μ•„λž˜μ—μ„œ 이웃 ν”½μ…€μ˜ ν˜Όν•© 색상이 λ°˜ν™˜λ˜λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

Untitled 1

κ·ΈλŸ¬λ‚˜ μ΄λŸ¬ν•œ ν…μŠ€μ²˜ 필터링 λ°©λ²•μ˜ μ‹œκ°μ  νš¨κ³ΌλŠ” λ¬΄μ—‡μΌκΉŒμš”? 큰 κ°œμ²΄μ— μ €ν•΄μƒλ„μ˜ ν…μŠ€μ²˜λ₯Ό μ‚¬μš©ν•  λ•Œ μ΄λŸ¬ν•œ 방법이 μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€. (λ”°λΌμ„œ ν…μŠ€μ²˜κ°€ μœ„μͺ½μœΌλ‘œ ν™•μž₯되고 κ°œλ³„ 텍셀이 λˆˆμ— λœλ‹ˆλ‹€

texture_filtering

GL_NEAREST λŠ” ν…μŠ€μ²˜λ₯Ό ν˜•μ„±ν•˜λŠ” 픽셀을 λͺ…ν™•ν•˜κ²Œ λ³Ό 수 μžˆλŠ” 블둝 νŒ¨ν„΄μ„ μƒμ„±ν•˜λŠ” 반면 GL_LINEAR 은 κ°œλ³„ 픽셀이 덜 λ³΄μ΄λŠ” λΆ€λ“œλŸ¬μš΄ νŒ¨ν„΄μ„ μƒμ„±ν•©λ‹ˆλ‹€. GL_LINER 은 보닀 사싀적인 좜λ ₯을 μƒμ„±ν•˜μ§€λ§Œ 일뢀 κ°œλ°œμžλŠ” 그것보닀 8λΉ„νŠΈ λͺ¨μ–‘을 μ„ ν˜Έν•˜λ―€λ‘œ GL_NEAREST μ˜΅μ…˜μ„ μ„ νƒν•©λ‹ˆλ‹€.

ν™•λŒ€ 및 μΆ•μ†Œμž‘μ—…μ„ μœ„ν•΄ ν…μŠ€μ²˜ 필터링을 μ„€μ • ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ ν…μŠ€μ²˜κ°€ μΆ•μ†Œλ  λ•Œ κ°€μž₯ κ°€κΉŒμš΄ 이웃 필터링을 μ‚¬μš©ν•˜κ³  μ—…μŠ€μΌ€μΌ 된 ν…μŠ€μ²˜μ— λŒ€ν•΄μ„  μ„ ν˜• 필터링을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ glTexParameter*λ₯Ό 톡해 두 μ˜΅μ…˜μ— λŒ€ν•œ 필터링 방법을 지정해야 ν•©λ‹ˆλ‹€. μ½”λ“œλŠ” λž˜ν•‘ 방법 μ„€μ •κ³Ό μœ μ‚¬ν•΄μ•Ό ν•©λ‹ˆλ‹€.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

Mipmaps

수천개의 물체가 μžˆλŠ” 큰 방이 있고 각각 ν…μŠ€μ²˜κ°€ λΆ™μ–΄μžˆλ‹€κ³  μƒμƒν•΄λ³΄μ„Έμš”. 뷰어에 κ°€κΉŒμš΄ κ°œμ²΄μ™€ λ™μΌν•œ 고해상도 ν…μŠ€μ²˜κ°€ μ—°κ²°λœ λ©€λ¦¬μžˆλŠ” κ°œμ²΄κ°€ μžˆμŠ΅λ‹ˆλ‹€. μ˜€λΈŒμ νŠΈκ°€ 멀리 λ–¨μ–΄μ Έ 있고 μ•„λ§ˆλ„ λͺ‡ 개의 ν”„λ ˆκ·Έλ¨ΌνŠΈλ§Œ μƒμ„±ν•˜κΈ° λ•Œλ¬Έμ— OpenGL은 ν…μŠ€μ²˜μ˜ λ§Žμ€ 뢀뢄에 κ±Έμ³μžˆλŠ” ν”„λ ˆκ·Έλ¨ΌνŠΈμ— λŒ€ν•΄ ν…μŠ€μ²˜ 색상을 μ„ νƒν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— 고해상도 ν…μŠ€μ²˜μ—μ„œ ν”„λ ˆκ·Έλ¨ΌνŠΈμ— λŒ€ν•œ μ˜¬λ°”λ₯Έ 색상 값을 κ²€μƒ‰ν•˜λŠ” 데 어렀움을 κ²ͺμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μž‘μ€ 물체에 고해상도 ν…μŠ€μ²˜λ₯Ό μ‚¬μš©ν•˜λŠ” λ©”λͺ¨λ¦¬ λŒ€μ—­ν­ λ‚­λΉ„λŠ” 말할 것도 μ—†κ³ , μž‘μ€ 물체에 κ°€μ‹œμ μΈ μ΄νŒ©νŠΈκ°€ μƒμ„±λ©λ‹ˆλ‹€.

이 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ OpenGL은 기본적으둜 각 후속 ν…μŠ€μ²˜κ°€ 이전 ν…μŠ€μ²˜μ— λΉ„ν•΄ 2λ°° μž‘μ€ νƒμŠ€μ²˜ 이미지 λͺ¨μŒμΈ λ°‰λ§΅μ΄λΌλŠ” κ°œλ…μ„ μ‚¬μš©ν•©λ‹ˆλ‹€. λ°‰λ§΅μ˜ κ°œλ…μ€ μ΄ν•΄ν•˜κΈ° μ‰½μŠ΅λ‹ˆλ‹€. λ·°μ–΄μ—μ„œ νŠΉμ • 거리 μž„κ³„ 값이 μ§€λ‚˜λ©΄ OpenGL은 κ°œμ²΄κΉŒμ§€μ˜ 거리에 κ°€μž₯ μ ν•©ν•œ λ‹€λ₯Έ 밉맡 ν…μŠ€μ²˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. 물체가 멀리 λ–¨μ–΄μ Έ 있기 λ•Œλ¬Έμ— 더 μž‘μ€ 해상도λ₯Ό μ‚¬μš©ν•˜λ”λΌλ„ μ‚¬μš©μžμ—κ²Œ λˆˆμ— 띄지 μ•ŠμŠ΅λ‹ˆλ‹€. 그러면 OpenGL은 μ˜¬λ°”λ₯Έ 텍셀을 μƒ˜ν”Œλ§ ν•  수 있으며 λ°‰λ§΅μ˜ ν•΄λ‹Ή 뢀뢄을 μƒ˜ν”Œλ§ ν•  λ•Œ κ΄€λ ¨λœ μΊμ‹œ 맀λͺ¨λ¦¬κ°€ μ€„μ–΄λ“­λ‹ˆλ‹€. λ°‰ λ§€ν•‘λœ ν…μŠ€μ²˜κ°€ μ–΄λ–»κ²Œ μƒκ²ΌλŠ”μ§€ μžμ„Ένžˆ λ³΄κ² μŠ΅λ‹ˆλ‹€.

mipmaps

각 ν…μŠ€μ²˜ 이미지에 λŒ€ν•΄ λ°‰ λ§€ν•‘λœ ν…μŠ€μ²˜ λͺ¨μŒμ„ λ§Œλ“œλŠ” 것은 μˆ˜λ™μœΌλ‘œ μˆ˜ν–‰ν•˜κΈ°κ°€ λ²ˆκ±°λ‘­μ§€λ§Œ λ‹€ν–‰μŠ€λŸ½κ²Œλ„ OpenGL은 ν…μŠ€μ²˜λ₯Ό λ§Œλ“  ν›„ glGenerateMipmapsλ₯Ό ν•œ 번만 ν˜ΈμΆœν•˜μ—¬ λͺ¨λ“  μž‘μ—…μ„ μˆ˜ν–‰ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ Œλ”λ§ 쀑에 밉맡 레벨 사이λ₯Ό μ „ν™˜ ν•  λ•Œ OpenGL은 두 밉맡 λ ˆμ΄μ–΄ 사이에 λ³΄μ΄λŠ” λ‚ μΉ΄λ‘œμš΄ κ°€μž₯μžλ¦¬μ™€ 같은 일뢀 μ•„ν‹°νŒ©νŠΈλ₯Ό ν‘œμ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€. 일반 ν…μŠ€μ²˜ 필터링과 λ§ˆμ°¬κ°€μ§€λ‘œ 밉맡 μˆ˜μ€€ κ°„ μ „ν™˜μ„ μœ„ν•΄ NEAREST 및 LINEAR 필터링을 μ‚¬μš©ν•˜μ—¬ 밉맡 μˆ˜μ€€κ°„μ— 필터링 ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 밉맡 레벨 μ‚¬μ΄μ˜ 필터링 방법을 μ§€μ •ν•˜κΈ° μœ„ν•΄ μ›λž˜ 필터링 방법을 λ‹€μŒ λ„€ 가지 μ˜΅μ…˜ 쀑 ν•˜λ‚˜λ‘œ λŒ€μ²΄ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • GL_NEAREST_MIPMAP_NEAREST : ν”½μ…€ 크기와 μΌμΉ˜μ‹œν‚€κΈ° μœ„ν•΄ κ°€μž₯ κ°€κΉŒμš΄ 밉맡을 μ·¨ν•˜κ³  ν…μŠ€μ²˜ μƒ˜ν”Œλ§μ— κ°€μž₯ κ°€κΉŒμš΄ 이웃 보간을 μ‚¬μš©ν•©λ‹ˆλ‹€.
  • GL_LINEAR_MIPMAP_NEAREST : κ°€μž₯ κ°€κΉŒμš΄ 밉맡 λ ˆλ²¨μ„ μ·¨ν•˜κ³  μ„ ν˜• 보간을 μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή λ ˆλ²¨μ„ μƒ˜ν”Œλ§ν•©λ‹ˆλ‹€.
  • GL_NEAREST_MIPMAP_LINEAR : ν”½μ…€ 크기에 κ°€μž₯ κ·Όμ ‘ν•œ 두 밉맡 사이λ₯Ό μ„ ν˜• λ³΄κ°„ν•˜κ³  κ°€μž₯ κ°€κΉŒμš΄ 이웃 보간을 톡해 보간 된 λ ˆλ²¨μ„ μƒ˜ν”Œλ§ν•©λ‹ˆλ‹€.
  • GL_LINEAR_MIPMAP_LINEAR : κ°€μž₯ κ°€κΉŒμš΄ 두 밉맡 사이λ₯Ό μ„ ν˜•μœΌλ‘œ λ³΄κ°„ν•˜κ³  μ„ ν˜• 보간을 톡해 λ³΄κ°„λœ λ ˆλ²¨μ„ μƒ˜ν”Œλ§ν•©λ‹ˆλ‹€.

ν…μŠ€μ²˜ 필터링과 λ§ˆμ°¬κ°€μ§€λ‘œ 필터링 방법을 glTexParameteriλ₯Ό μ‚¬μš©ν•˜μ—¬ μ•žμ„œ μ–ΈκΈ‰ν•œ 4가지 방법 쀑 ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

일반적인 μ‹€μˆ˜λŠ” 밉맡 필터링 μ˜΅μ…˜ 쀑 ν•˜λ‚˜λ₯Ό ν™•λŒ€ ν•„ν„°λ‘œ μ„€μ •ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 밉맡은 주둜 ν…μŠ€μ²˜κ°€ μΆ•μ†Œ 될 λ•Œ μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— νš¨κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€. ν…μŠ€μ²˜ ν™•λŒ€λŠ” 밉맡을 μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©° 밉맡 필터링 μ˜΅μ…˜μ„ μ œκ³΅ν•˜λ©΄ OpenGL GL_INVALID_ENUM μ—λŸ¬ μ½”λ“œκ°€ μƒμ„±λ©λ‹ˆλ‹€.

Loading and Creating textures

μ‹€μ œλ‘œ ν…μŠ€μ²˜λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ ν•΄μ•Όν•  첫 번째 일은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λ‘œλ“œν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. ν…μŠ€μ²˜ μ΄λ―Έμ§€λŠ” 각각 고유 ν•œ ꡬ쑰와 데이터 μˆœμ„œκ°€ μžˆλŠ” μˆ˜μ‹­κ°œμ˜ 파일 ν˜•μ‹μœΌλ‘œ μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ ‡λ‹€λ©΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ΄λŸ¬ν•œ 이미지λ₯Ό μ–΄λ–»κ²Œ κ°€μ Έμ˜¬ 수 μžˆμ„κΉŒμš”? ν•œ 가지 해결책은 .png 와 같이 μ‚¬μš©ν•  파일 ν˜•μ‹μ„ μ„ νƒν•˜κ³  자체 이미지 λ‘œλ”λ₯Ό μž‘μ„±ν•˜μ—¬ 이미지 ν˜•μ‹μ„ 큰 λ°”μ΄νŠΈ λ°°μ—΄λ‘œ λ³€ν™˜ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 자체 이미지 λ‘œλ”λ₯Ό μž‘μ„±ν•˜λŠ” 것은 그리 μ–΄λ ΅μ§€λŠ” μ•Šμ§€λ§Œ μ—¬μ „νžˆ 번거둭고 더 λ§Žμ€ ν˜•μ‹μ„ μ§€μ›ν•˜λ €λ©΄ 각 ν˜•μ‹μ— λŒ€ν•΄ 이미지 λ‘œλ”λ₯Ό μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€.

또 λ‹€λ₯Έ ν•΄κ²°μ±…μ΄μž μ’‹μ•„ λ³΄μ΄λŠ” 해결책은 자주 μ‚¬μš©ν•˜λŠ” μ—¬λŸ¬κ°€μ§€ ν˜•μ‹μ„ μ§€μ›ν•˜κ³  우리λ₯Ό μœ„ν•΄ λͺ¨λ“  λ…Έλ ₯을 λ‹€ν•˜λŠ” 이미지 λ‘œλ”© 라이브러리λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. std_image.h 와 같은거 말이죠

stb_image.h

stb_image.h λŠ” Sean Barrett 의 맀우 μΈκΈ°μžˆλŠ” 단일 헀더 이미지 λ‘œλ”© 라이브러리둜, κ°€μž₯ 많이 μ‚¬μš©λ˜λŠ” 파일 ν˜•μ‹μ„ λ‘œλ“œν•  수 있으며, ν”„λ‘œμ νŠΈμ— μ‰½κ²Œ 톡합할 수 μžˆμŠ΅λ‹ˆλ‹€. stb_image.h λŠ” μ—¬κΈ°μ—μ„œ λ‹€μš΄λ‘œλ“œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 단일 ν—€λ”νŒŒμΌμ„ λ‹€μš΄λ‘œλ“œν•˜κ³  stb_image.h 둜 ν”„λ‘œμ νŠΈμ— μΆ”κ°€ν•œ ν›„ λ‹€μŒ μ½”λ“œλ‘œ μΆ”κ°€ C++ νŒŒμΌμ„ λ§Œλ“­λ‹ˆλ‹€.

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h

STB_IMAGE_IMPLEMENTATION 을 μ •μ˜ν•¨μœΌλ‘œμ¨ μ „μ²˜λ¦¬κΈ°λŠ” κ΄€λ ¨ μ •μ˜ μ†ŒμŠ€ μ½”λ“œλ§Œ ν¬ν•¨ν•˜λ„λ‘ 헀더 νŒŒμΌμ„ μˆ˜μ •ν•˜μ—¬ 효과적으둜 헀더 νŒŒμΌμ„ .cpp 파일둜 λ³€ν™˜ν•©λ‹ˆλ‹€. 이제 ν”„λ‘œκ·Έλž¨ μ–΄λ”˜κ°€μ— std_image.h λ₯Ό ν¬ν•¨ν•˜κ³  μ»΄νŒŒμΌν•˜μ‹­μ‹œμ˜€.

λ‹€μŒ ν…μŠ€μ²˜ μ„Ήμ…˜μ—λŠ” λ‚˜λ¬΄ μ»¨ν…Œμ΄λ„ˆμ˜ 이미지λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. stb_image.h λ₯Ό μ‚¬μš©ν•˜μ—¬ 이미지λ₯Ό λ‘œλ“œν•˜λ €λ©΄ stbi_load ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0); 

이 ν•¨μˆ˜λŠ” λ¨Όμ € 이미지 파일의 μœ„μΉ˜λ₯Ό μž…λ ₯으둜 λ°›μŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ stb_image.h κ°€ κ²°κ³Ό μ΄λ―Έμ§€μ˜ λ„ˆλΉ„, 높이 및 색상 μ²΄λ„λ‘œ μ±„μšΈ **두 번째, μ„Έ 번째, λ„€ 번째 인수둜 μ„Έ 개의 ints λ₯Ό 제곡 ν•  κ²ƒμœΌλ‘œ μ˜ˆμƒν•©λ‹ˆλ‹€. λ‚˜μ€‘μ— ν…μŠ€μ²˜λ₯Ό μƒμ„±ν•˜λ €λ©΄ μ΄λ―Έμ§€μ˜ λ„ˆλΉ„μ™€ 높이가 ν•„μš”ν•©λ‹ˆλ‹€.

Generating a texture

OpenGL의 이전 κ°œμ²΄μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ ν…μŠ€μ²˜λŠ” ID둜 μ°Έμ‘°λ©λ‹ˆλ‹€. ν•˜λ‚˜ λ§Œλ“€μ–΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

unsigned int texture;
glGenTextures(1, &texture);  

glGenTextures ν•¨μˆ˜λŠ” λ¨Όμ € μš°λ¦¬κ°€ μƒμ„±ν•˜λ €λŠ” ν…μŠ€μ²˜μ˜ 수λ₯Ό μž…λ ₯으둜 μ·¨ν•˜κ³  두 번째 인수둜 μ§€μ •λœ unsigned int λ°°μ—΄λ‘œ μ €μž₯ν•©λ‹ˆλ‹€ (이 κ²½μš°μ—λŠ” 단일 unsigned int). λ‹€λ₯Έ μ˜€λΈŒμ νŠΈμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ 바인딩 ν•΄μ•Ό 후속 ν…μŠ€μ²˜ λͺ…령이 ν˜„μž¬ 바인딩 된 ν…μŠ€μ²˜λ₯Ό κ΅¬μ„±ν•©λ‹ˆ

glBindTexture(GL_TEXTURE_2D, texture);

이제 ν…μŠ€μ²˜κ°€ λ°”μΈλ”©λ˜μ—ˆμœΌλ―€λ‘œ 이전에 λ‘œλ“œ 된 이미지 데이터λ₯Ό μ‚¬μš©ν•˜μ—¬ ν…μŠ€μ³ 생성을 μ‹œμž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν…μŠ€μ²˜λŠ” glTexImage2D둜 μƒμ„±λ©λ‹ˆλ‹€.


glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);

이것은 맀개 λ³€μˆ˜κ°€ μƒλ‹Ήνžˆ λ§Žμ€ 큰 ν•¨μˆ˜μ΄λ―€λ‘œ λ‹¨κ³„λ³„λ‘œ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

  • 첫 번째 μΈμˆ˜λŠ” ν…μŠ€μ²˜ λŒ€μƒμ„ μ§€μ •ν•©λ‹ˆλ‹€. 이것을 GL_TEXTURE_2D 둜 μ„€μ •ν•˜λ©΄ 이 μž‘μ—…μ΄ λ™μΌν•œ λŒ€μƒμ—μ„œ ν˜„μž¬ 바인딩 된 κ°œμ²΄μ— ν…μŠ€μ²˜λ₯Ό μƒμ„±ν•œλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€. (λ”°λΌμ„œ λŒ€μƒ GL_TEXTURE_ID λ˜λŠ” GL_TEXTURE_3D에 바인딩 된 ν…μŠ€μ²˜λŠ” 영ν–₯을 받지 μ•ŠμŠ΅λ‹ˆλ‹€.)
  • 두 번째 μΈμˆ˜λŠ” 각 밉맡 λ ˆλ²¨μ„ μˆ˜λ™μœΌλ‘œ μ„€μ •ν•˜λ €λŠ” 경우 ν…μŠ€μ²˜λ₯Ό μƒμ„±ν•˜λ €λŠ” 밉맡 λ ˆλ²¨μ„ μ§€μ •ν•˜μ§€λ§Œ κΈ°λ³Έ 레벨인 0 으둜 λ‘κ² μŠ΅λ‹ˆλ‹€.
  • μ„Έ 번째 μΈμˆ˜λŠ” OpenGL μ—κ²Œ ν…μŠ€μ²˜λ₯Ό μ €μž₯ν•  ν˜•μ‹μ„ μ•Œλ €μ€λ‹ˆλ‹€. μ΄λ―Έμ§€μ—λŠ” RGB κ°’λ§Œ μžˆμœΌλ―€λ‘œ RGB κ°’μœΌλ‘œ ν…μŠ€μ²˜λ„ μ €μž₯ν•©λ‹ˆλ‹€.
  • λ„€ λ²ˆμ§Έμ™€ λ‹€μ„― 번째 μΈμˆ˜λŠ” κ²°κ³Ό ν…μŠ€μ²˜μ˜ λ„ˆλΉ„μ™€ 높이λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€. 이미지λ₯Ό λ‘œλ“œ ν•  λ•Œ 이전에 μ €μž₯ν–ˆμœΌλ―€λ‘œ ν•΄λ‹Ή λ³€μˆ˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.
  • λ‹€μŒ μΈμˆ˜λŠ” 항상 0 이어야 ν•©λ‹ˆλ‹€. (λ ˆκ±°μ‹œ ν•­λͺ©)
  • 7λ²ˆμ§Έμ™€ 8번째 μΈμˆ˜λŠ” μ†ŒμŠ€ μ΄λ―Έμ§€μ˜ ν˜•μ‹κ³Ό 데이터 μœ ν˜•μ„ μ§€μ •ν•©λ‹ˆλ‹€. 이미지에 RGB 값을 λ‘œλ“œν•˜κ³  char (λ°”μ΄νŠΈ)둜 μ €μž₯ν–ˆμœΌλ―€λ‘œ ν•΄λ‹Ή 값을 μ „λ‹¬ν•©λ‹ˆλ‹€.
  • λ§ˆμ§€λ§‰ μΈμˆ˜λŠ” μ‹€μ œ 이미지 λ°μ΄ν„°μž…λ‹ˆλ‹€.

glTexture2Dκ°€ 호좜되면 ν˜„μž¬ 바인딩 된 ν…μŠ€μ²˜ κ°œμ²΄μ— ν…μŠ€μ²˜ 이미지가 λΆ™ν˜€μ§‘λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ ν˜„μž¬ ν…μŠ€μ²˜ μ΄λ―Έμ§€μ˜ κΈ°λ³Έ μˆ˜μ€€λ§Œ λ‘œλ“œλ˜μ–΄ 있으며 밉맡을 μ‚¬μš©ν•˜λ €λ©΄ λͺ¨λ“  λ‹€λ₯Έ 이미지λ₯Ό μˆ˜μ •μœΌλ‘œ 지정해야 ν•©λ‹ˆλ‹€. (두 번째 인수λ₯Ό 계속 μ¦κ°€μ‹œν‚€λ©΄μ„œ) λ˜λŠ” ν…μŠ€μ²˜λ₯Ό 생성 ν•œ ν›„ glGenerateMipmap을 호좜 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 그러면 ν˜„μž¬ 바인딩 된 ν…μŠ€μ²˜μ— ν•„μš”ν•œ λͺ¨λ“  밉맡이 μžλ™μœΌλ‘œ μƒμ„±λ©λ‹ˆλ‹€.

ν…μŠ€μ²˜ 및 ν•΄λ‹Ή 밉맡 생성을 μ™„λ£Œ ν•œ ν›„ 이미지 λ©”λͺ¨λ¦¬λ₯Ό ν•΄μ œν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

stbi_image_free(data);

λ”°λΌμ„œ ν…μŠ€μ²˜λ₯Ό μƒμ„±ν•˜λŠ” 전체 ν”„λ‘œμ„ΈμŠ€λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€,

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// ν…μŠ€μ³ λž˜ν•‘ / 필터링 μ˜΅μ…˜ μ„€μ • (ν˜„μž¬ 바인딩 된 ν…μŠ€μ³ κ°œμ²΄μ—μ„œ)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// ν…μŠ€μ²˜λ₯Ό λ‘œλ”©ν•˜κ³  생성
int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
    std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);

Applying textures

λ‹€μŒ μ„Ήμ…˜μ—μ„œλŠ” Hello Triangle μž₯의 λ§ˆμ§€λ§‰ λΆ€λΆ„μ—μ„œ glDrawElements둜 κ·Έλ¦° μ‚¬κ°ν˜• λͺ¨μ–‘을 μ‚¬μš©ν•©λ‹ˆλ‹€. ν…μŠ€μ²˜λ₯Ό μƒ˜ν”Œλ§ν•˜λŠ” 방법을 OpenGL에 μ•Œλ €μ•Ό ν•˜λ―€λ‘œ ν…μŠ€μ²˜ μ’Œν‘œλ‘œ λ²„ν…μŠ€ 데이터λ₯Ό μ—…λ°μ΄νŠΈ ν•΄μ•Ό ν•©λ‹ˆλ‹€.

float vertices[] = {
    // positions          // colors           // texture coords
     0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // top right
     0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // bottom right
    -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // bottom left
    -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // top left 
};

μΆ”κ°€ λ²„ν…μŠ€ 속성을 μΆ”κ°€ ν–ˆμœΌλ―€λ‘œ λ‹€μ‹œ OpenGLμ—κ²Œ μƒˆλ‘œμš΄ λ²„ν…μŠ€ ν˜•μ‹μ„ μ•Œλ €μ•Ό ν•©λ‹ˆλ‹€.

vertex_attribute_pointer_interleaved_textures

glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)(6*sizeof(float)));
glEnableVertexAttribArray(2);  

이전 두 λ²„ν…μŠ€ 속성에 stride 맀개 λ³€μˆ˜λ„ 8 * sizeof(float) 둜 μ‘°μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ‹€μŒμœΌλ‘œ ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό λ²„ν…μŠ€ μ†μ„±μœΌλ‘œ 받아듀이도둝 λ²„ν…μŠ€ 셰이더λ₯Ό λ³€κ²½ ν•œ λ‹€μŒ ν•΄λ‹Ή μ’Œν‘œλ₯Ό ν”„λ ˆκ·Έλ¨ΌνŠΈ μ…°μ΄λ”λ‘œ 전달해야 ν•©λ‹ˆλ‹€.

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor;
    TexCoord = aTexCoord;
}

그러면 ν”„λž˜κ·Έλ¨ΌνŠΈ μ…°μ΄λ”λŠ” TexCoord 좜λ ₯ λ³€μˆ˜λ₯Ό μž…λ ₯ λ³€μˆ˜λ‘œ λ°›μ•„ λ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

ν”„λž˜κ·Έλ¨ΌνŠΈ 셰이더도 ν…μŠ€μ²˜ κ°œμ²΄μ— μ•‘μ„ΈμŠ€ ν•  수 μžˆμ–΄μ•Ό ν•˜μ§€λ§Œ ν…μŠ€μ²˜ 개체λ₯Ό ν”„λž˜κ·Έλ¨ΌνŠΈ μ…°μ΄λ”λ‘œ μ–΄λ–»κ²Œ μ „λ‹¬ν• κΉŒμš”? GLSLμ—λŠ” μš°λ¦¬κ°€ μ›ν•˜λŠ” ν…μŠ€μ²˜ μœ ν˜•μ„ μ ‘λ―Έμ‚¬λ‘œ μ·¨ν•˜λŠ” μƒ˜ν”ŒλŸ¬λΌλŠ” ν…μŠ€μ²˜ κ°œμ²΄μ— λŒ€ν•œ λ‚΄μž₯ 데이터 μœ ν˜•μ΄ μžˆμŠ΅λ‹ˆλ‹€. sampler1D, sampler3D λ˜λŠ” 이 경우 sampler2D μž…λ‹ˆλ‹€. 그런 λ‹€μŒ λ‚˜μ€‘μ— ν…μŠ€μ²˜λ₯Ό ν• λ‹Ή ν•  uniform sampler2D λ₯Ό μ„ μ–Έν•˜μ—¬ ν”„λ ˆκ·Έλ¨ΌνŠΈ 셰이더에 ν…μŠ€μ²˜λ₯Ό μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

#version 330 core
out vec4 FragColor;
  
in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;

void main()
{
    FragColor = texture(ourTexture, TexCoord);
}

ν…μŠ€μ²˜μ˜ 색상을 μƒ˜ν”Œλ§ν•˜κΈ° μœ„ν•΄ 첫 번째 인수둜 ν…μŠ€μ²˜ μƒ˜ν”ŒλŸ¬λ₯Ό, 두 번째 인수둜 ν•΄λ‹Ή ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό λ°›λŠ” GLSL의 λ‚΄μž₯ ν…μŠ€μ²˜ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. ν…μŠ€μ²˜ ν•¨μˆ˜λŠ” μ•žμ„œ μ„€μ •ν•œ ν…μŠ€μ²˜ 맀개 λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•΄λ‹Ή 색상 값을 μƒ˜ν”Œλ§ν•©λ‹ˆλ‹€. 이 ν”„λ ˆκ·Έλ¨ΌνŠΈ μ…°μ΄λ”μ˜ 좜λ ₯은 (보간 된) ν…μŠ€μ²˜ μ’Œν‘œμ—μ„œ ν…μŠ€μ²˜μ˜ (필터링 된) μƒ‰μƒμž…λ‹ˆλ‹€.

이제 남은 일은 glDrawElementsλ₯Ό ν˜ΈμΆœν•˜κΈ° 전에 ν…μŠ€μ²˜λ₯Ό λ°”μΈλ”©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 그러면 ν…μŠ€μ²˜κ°€ ν”„λ ˆκ·Έλ¨ΌνŠΈ μ…°μ΄λ”μ˜ μƒ˜ν”ŒλŸ¬μ— μžλ™μœΌλ‘œ ν• λ‹Ήλ©λ‹ˆλ‹€.

glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

λͺ¨λ“  것을 μ˜¬λ°”λ₯΄κ²Œ μˆ˜ν–‰ν–ˆλ‹€λ©΄ λ‹€μŒ 이미지가 ν‘œμ‹œλ©λ‹ˆλ‹€.

textures2

μ§μ‚¬κ°ν˜•μ΄ μ™„μ „νžˆ νžŒμƒ‰μ΄κ±°λ‚˜ 검은색이면 도쀑에 였λ₯˜κ°€ λ°œμƒν•œ 것 일 수 μžˆμŠ΅λ‹ˆλ‹€. 셰이더 둜그λ₯Ό ν™•μΈν•˜κ³  μ½”λ“œλ₯Ό μ†ŒμŠ€ μ½”λ“œμ™€ 비ꡐ ν•΄ λ³΄μ„Έμš”.

ν…μŠ€μ²˜ μ½”λ“œκ°€ μž‘λ™ν•˜μ§€ μ•Šκ±°λ‚˜ μ™„μ „ν•œ κ²€μ€μƒ‰μœΌλ‘œ ν‘œμ‹œλ˜λŠ” 경우, κ·Έλƒ₯ 계속 λ”°λΌκ°€μ„œ μž‘λ™ν•΄μ•Ό ν•˜λŠ” λ§ˆμ§€λ§‰ 예제λ₯Ό ν™•μΈν•˜μ„Έμš”. 일뢀 λ“œλΌμ΄λ²„μ—μ„œλŠ” 각 μƒ˜ν”ŒλŸ¬ μœ λ‹ˆνΌμ— ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό ν• λ‹Ήν•˜λŠ” 것이 ν•„μˆ˜μ΄λ©°, μ΄λŠ” 이 μž₯μ—μ„œ μžμ„Ένžˆ μ„€λͺ…ν•©λ‹ˆλ‹€.

μ’€ νŽ‘ν‚€ν•˜κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ κ²°κ³Ό ν…μŠ€μ²˜ 색상을 λ²„ν…μŠ€ 색상과 ν˜Όν•© ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. κ²°κ³Ό ν…μŠ€μ²˜ 색상을 ν”„λž˜κ·Έλ¨ΌνŠΈ μ…°μ΄λ”μ˜ λ²„ν…μŠ€ 색상과 κ³±ν•˜μ—¬ 두 색상을 ν˜Όν•©ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0);  

λ²„ν…μŠ€μ˜ 색상과 ν…μŠ€μ²˜μ˜ μƒ‰μƒμ˜ ν˜Όν•©μ€ λ‹€μŒκ³Ό 같이 λ³΄μž…λ‹ˆλ‹€.

textures_funky

우리 μ»¨ν…Œμ΄λ„ˆκ°€ λ””μŠ€μ½”λ₯Ό μ’‹μ•„ν•˜λŠ”κ±° κ°™μŠ΅λ‹ˆλ‹€.

Texture Units

glUniform으둜 값을 ν• λ‹Ήν•˜μ§€ μ•ŠλŠ” 경우 μ™œ sampler2D λ³€μˆ˜κ°€ κ· μΌν•œμ§€ ꢁ금 ν•  κ²ƒμž…λ‹ˆλ‹€. glUniform1iλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‹€μ œλ‘œ location 값을 ν…μŠ€μ²˜ μƒ˜ν”ŒλŸ¬μ— ν• λ‹Ήν•  수 μžˆμœΌλ―€λ‘œ ν”„λ ˆκ·Έλ¨ΌνŠΈ μ…°μ΄λ”μ—μ„œ ν•œ λ²ˆμ— μ—¬λŸ¬ ν…μŠ€μ²˜λ₯Ό μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν…μŠ€μ²˜μ˜ 이 μœ„μΉ˜λŠ” 일반적으둜 ν…μŠ€μ²˜ λ‹¨μœ„λ‘œ μ•Œλ €μ Έ μžˆμŠ΅λ‹ˆλ‹€. ν…μŠ€μ²˜μ˜ κΈ°λ³Έ ν…μŠ€μ²˜ λ‹¨μœ„λŠ” κΈ°λ³Έ ν™œμ„± ν…μŠ€μ²˜ λ‹¨μœ„μΈ 0 μ΄λ―€λ‘œ 이전 μ„Ήμ…˜μ—μ„œ μœ„μΉ˜λ₯Ό ν• λ‹Ή ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. λͺ¨λ“  κ·Έλž˜ν”½ λ“œλΌμ΄λ²„κ°€ κΈ°λ³Έ ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό ν• λ‹Ήν•˜λŠ” 것은 μ•„λ‹ˆλ―€λ‘œ 이전 μ„Ήμ…˜μ΄ λ Œλ”λ§ λ˜μ§€ μ•Šμ•˜μ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

ν…μŠ€μ²˜ μœ λ‹›μ˜ μ£Όμš” λͺ©μ μ€ μ…°μ΄λ”μ—μ„œ ν•˜λ‚˜ μ΄μƒμ˜ ν…μŠ€μ²˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. μƒ˜ν”ŒλŸ¬μ— ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό ν• λ‹Ήν•˜λ©΄ ν•΄λ‹Ή ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό λ¨Όμ € ν™œμ„±ν™”ν•˜λŠ” ν•œ ν•œλ²ˆμ— μ—¬λŸ¬ ν…μŠ€μ²˜μ— 바인딩 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. glBindTexture와 λ§ˆμ°¬κ°€μ§€λ‘œ μ‚¬μš©ν•  ν…μŠ€μ²˜ μœ λ‹›μ„ μ „λ‹¬ν•˜λŠ” glActiveTextureλ₯Ό μ‚¬μš©ν•˜μ—¬ ν…μŠ€μ²˜ μœ λ‹›μ„ ν™œμ„±ν™” ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

glActiveTexture(GL_TEXTURE0); // ν…μŠ€μ²˜λ₯Ό 바인딩 ν•˜κΈ° 전에 λ¨Όμ € ν…μŠ€μ²˜ μœ λ‹›μ„ ν™œμ„±ν™”ν•΄μ•Όν•¨
glBindTexture(GL_TEXTURE_2D, texture);

ν…μŠ€μ²˜ μœ λ‹›μ„ ν™œμ„±ν™” ν•œ ν›„ 후속 glBindTexture ν˜ΈμΆœμ€ ν•΄λ‹Ή ν…μŠ€μ²˜λ₯Ό ν˜„μž¬ ν™œμ„±ν™” 된 ν…μŠ€μ²˜ μœ λ‹›μ— λ°”μΈλ”©ν•©λ‹ˆλ‹€. ν…μŠ€μ²˜ λ‹¨μœ„ GL_TEXTURE0λŠ” 항상 기본적으둜 ν™œμ„±ν™”λ˜μ–΄ μžˆμœΌλ―€λ‘œ glBindTextureλ₯Ό μ‚¬μš©ν•  λ•Œ 이전 μ˜ˆμ œμ—μ„œ ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό ν™œμ„±ν™” ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

OpenGLμ—λŠ” GL_TEXTURE0 ~ GL_TEXTURE15λ₯Ό μ‚¬μš©ν•˜μ—¬ ν™œμ„±ν™” ν•  수 μžˆλŠ” μ΅œμ†Œ 16개의 ν…μŠ€μ²˜ λ‹¨μœ„κ°€ μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ GL_TEXTURE + 8을 톡해 GL_TEXTURE8을 얻을 수 μžˆλ„λ‘ μˆœμ„œλŒ€λ‘œ μ •μ˜λ©λ‹ˆλ‹€. μ΄λŠ” μ—¬λŸ¬ ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό λ°˜λ³΅ν•΄μ•Ό ν•  λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ λ‹€λ₯Έ μƒ˜ν”ŒλŸ¬λ₯Ό 받아듀이렀면 μ—¬μ „νžˆ ν”„λ ˆκ·Έλ¨ΌνŠΈ 셰이더λ₯Ό νŽΈμ§‘ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΄μ œλΆ€ν„΄ 비ꡐ적 κ°„λ‹¨ν•©λ‹ˆλ‹€.

#version 330 core
...

uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}

μ΅œμ’… 좜λ ₯ 색상은 이제 두 ν…μŠ€μ²˜μ˜ μ‘°ν•©μž…λ‹ˆλ‹€. GLSL의 λ‚΄μž₯된 ν˜Όν•© ν•¨μˆ˜λŠ” 두 개의 값을 μž…λ ₯으둜 μ·¨ν•˜κ³  μ„Έ 번째 인수λ₯Ό 기반으둜 두 값을 μ„ ν˜•μœΌλ‘œ λ³΄κ°„ν•©λ‹ˆλ‹€. μ„Έ 번째 값이 0.0 이면 첫 번째 μž…λ ₯을 λ°˜ν™˜ν•©λ‹ˆλ‹€. 1.0 이면 두 번째 μž…λ ₯ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€. 값이 0.2 이면 첫 번째 μž…λ ₯ μƒ‰μƒμ˜ 80% 와 두 번째 μž…λ ₯ μƒ‰μƒμ˜ 20% κ°€ λ°˜ν™˜λ˜μ–΄ 두 ν…μŠ€μ²˜κ°€ ν˜Όν•©λ©λ‹ˆλ‹€.

이제 λ‹€λ₯Έ ν…μŠ€μ²˜λ₯Ό λ‘œλ“œν•˜κ³  μƒμ„±ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 이제 단계에 μ΅μˆ™ν•΄μ§€μ…”μ•Ό ν•©λ‹ˆλ‹€. λ‹€λ₯Έ ν…μŠ€μ²˜ 개체λ₯Ό μƒμ„±ν•˜κ³  이미지λ₯Ό λ‘œλ“œν•˜κ³  glTexImage2Dλ₯Ό μ‚¬μš©ν•˜μ—¬ μ΅œμ’… ν…μŠ€μ²˜λ₯Ό 생성해야 ν•©λ‹ˆλ‹€. 두 번째 ν…μŠ€μ²˜μ—λŠ” OpenGL을 λ°”μš°λŠ” λ™μ•ˆμ˜ ν‘œμ • 이미지λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

unsigned char *data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
if (data)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 
									0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}

이제 μ•ŒνŒŒ(투λͺ…도) 채널을 ν¬ν•¨ν•˜λŠ” .png 이미지λ₯Ό λ‘œλ“œν•©λ‹ˆλ‹€. 즉, GL_RGBAλ₯Ό μ‚¬μš©ν•˜μ—¬ 이미지 데이터에 μ•ŒνŒŒ 채널도 ν¬ν•¨λ˜λ„λ‘ 지정해야 ν•©λ‹ˆλ‹€. 그렇지 μ•ŠμœΌλ©΄ OpenGL이 이미지 데이터λ₯Ό 잘λͺ» ν•΄μ„ν•©λ‹ˆλ‹€.

두 번째 ν…μŠ€μ²˜ (및 첫번째 ν…μŠ€μ²˜)λ₯Ό μ‚¬μš©ν•˜λ €λ©΄ 두 ν…μŠ€μ²˜λ₯Ό ν•΄λ‹Ή ν…μŠ€μ²˜ λ‹¨μœ„μ— λ°”μΈλ”©ν•˜μ—¬ λ Œλ”λ§ 절차λ₯Ό μ•½κ°„ λ³€κ²½ν•΄μ•Ό ν•©λ‹ˆλ‹€.

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);

glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 

λ˜ν•œ glUniform1iλ₯Ό μ‚¬μš©ν•˜μ—¬ 각 μƒ˜ν”ŒλŸ¬λ₯Ό μ„€μ •ν•˜μ—¬ 각 셰이더 μƒ˜ν”ŒλŸ¬κ°€ μ†ν•œ ν…μŠ€μ²˜ λ‹¨μœ„λ₯Ό OpenGL에 μ•Œλ €μ•Ό ν•©λ‹ˆλ‹€. ν•œ 번만 μ„€μ •ν•˜λ©΄ λ˜λ―€λ‘œ λ Œλ”λ§ 루프에 λ“€μ–΄κ°€κΈ° 전에 이 μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€

ourShader.use(); //μœ λ‹ˆνΌμ„ μ„€μ •ν•˜κΈ° 전에 셰이더λ₯Ό μ•‘ν‹°λΈŒν•˜λŠ” 것을 κΉŒλ¨Ήμ§€λ§ˆμ„Έμš”!  
glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0); // μˆ˜λ™μœΌλ‘œ μ„€μ •
ourShader.setInt("texture2", 1); // μ•„λ‹ˆλ©΄ 셰이더 클래슀둜 μ„€μ •
  
while(...) 
{
    [...]
}

glUniform1iλ₯Ό 톡해 μƒ˜ν”ŒλŸ¬λ₯Ό μ„€μ •ν•˜μ—¬ 각 κ· μΌν•œ μƒ˜ν”ŒλŸ¬κ°€ μ μ ˆν•œ ν…μŠ€μ²˜ λ‹¨μœ„μ— ν•΄λ‹Ήν•˜λŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€. λ‹€μŒκ³Ό 같은 κ²°κ³Όλ₯Ό μ–»μ–΄μ•Ό ν•©λ‹ˆλ‹€.

textures_combined

ν…μŠ€μ²˜κ°€ 거꾸둜 λ’€μ§‘νžŒ 것을 λ³Ό 수 μžˆμ„ κ²λ‹ˆλ‹€! 이것은 OpenGL이 yμΆ•μ˜ 0.0 μ’Œν‘œκ°€ μ΄λ―Έμ§€μ˜ μ•„λž˜μͺ½μ— μžˆμ„ κ²ƒμœΌλ‘œ μ˜ˆμƒν•˜κΈ° λ•Œλ¬Έμ— λ°œμƒν•˜μ§€λ§Œ μ΄λ―Έμ§€λŠ” 일반적으둜 yμΆ•μ˜ μœ„μͺ½μ— 0.0 이 μžˆμŠ΅λ‹ˆλ‹€. λ‹€ν–‰μŠ€λŸ½κ²Œλ„ stb_image.h λŠ” 이미지λ₯Ό λ‘œλ“œν•˜κΈ° 전에 λ‹€μŒ 문을 μΆ”κ°€ν•˜μ—¬ 이미지 λ‘œλ“œ 쀑에 y좕을 뒀집을 수 μžˆμŠ΅λ‹ˆλ‹€.

stbi_set_flip_vertically_on_load(true);  

이미지λ₯Ό λ‘œλ“œν•  λ•Œ stb_image.h μ—κ²Œ y좕을 뒀집도둝 μ§€μ‹œν•œ ν›„ λ‹€μŒ κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

textures_combined2

ν•΄ν”Ό μ»¨ν…Œμ΄λ„ˆλ₯Ό λ³Ό 수 있게 λ˜μ—ˆλ‹€λ©΄ μž˜ν•œκ²λ‹ˆλ‹€. μ†ŒμŠ€ μ½”λ“œμ™€ λΉ„κ΅ν•΄λ³΄μ„Έμš”.

Exercises

ν…μŠ€μ²˜μ— 더 μ΅μˆ™ν•΄ 지렀면 κ³„μ†ν•˜κΈ° 전에 μ΄λŸ¬ν•œ μ—°μŠ΅μ„ 톡해 μž‘μ—…ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

  • ν”„λž˜κ·Έλ¨ΌνŠΈ μ…°μ΄λ”λ§Œ λ³€κ²½ν•˜μ—¬ ν–‰λ³΅ν•œ 얼꡴이 λ°˜λŒ€ / μ—­λ°©ν–₯으둜 λ³΄μ΄λŠ”μ§€ ν™•μΈν•˜μ„Έμš”: μ •λ‹΅.
  • 0.0f ~ 1.0f λŒ€μ‹  0.0f ~ 2.0f λ²”μœ„μ˜ ν…μŠ€μ²˜ μ’Œν‘œλ₯Ό μ§€μ •ν•˜μ—¬ λ‹€μ–‘ν•œ ν…μŠ€μ²˜ λž˜ν•‘ 방법을 μ‹€ν—˜ν•΄λ³΄μ„Έμš”. κ°€μž₯μžλ¦¬μ— κ³ μ • 된 단일 μ»¨ν…Œμ΄λ„ˆ 이미지에 μ›ƒλŠ” μ–Όκ΅΄ 4개λ₯Ό ν‘œμ‹œ ν•  수 μžˆλŠ”μ§€ ν™•μΈν•˜μ„Έμš”: μ •λ‹΅, κ²°κ³Ό. λ‹€λ₯Έ 포μž₯ 방법도 μ‹€ν—˜ν•  수 μžˆλŠ”μ§€ ν™•μΈν•˜μ‹­μ‹œμ˜€.
  • ν…μŠ€μ³ μ’Œν‘œλ₯Ό λ³€κ²½ν•˜μ—¬ κ°œλ³„ 픽셀이 보이도둝 μ§μ‚¬κ°ν˜• ν…μŠ€μ²˜ μ΄λ―Έμ§€μ˜ 쀑심 ν•„μ…€λ§Œ ν‘œμ‹œν•˜λ„λ‘ ν•©λ‹ˆλ‹€. 픽셀을 더 λͺ…ν™•ν•˜κ²Œ 보렀면 ν…μŠ€μ²˜ 필터링 방법을 GL_NEAREST둜 μ„€μ •ν•˜μ‹­μ‹œμ˜€: μ •λ‹΅.
  • 균일 λ³€μˆ˜λ₯Ό ν˜Όν•© ν•¨μˆ˜μ˜ μ„Έ 번째 맀개 λ³€μˆ˜λ‘œ μ‚¬μš©ν•˜μ—¬ 두 ν…μŠ€μ²˜κ°€ ν‘œμ‹œλ˜λŠ” 양을 λ³€κ²½ν•©λ‹ˆλ‹€. μœ„μͺ½ 및 μ•„λž˜μͺ½ ν™”μ‚΄ν‘œ ν‚€λ₯Ό μ‚¬μš©ν•˜μ—¬ μ»¨ν…Œμ΄λ„ˆ λ˜λŠ” μ›ƒλŠ” 얼꡴이 ν‘œμ‹œλ˜λŠ” 정도λ₯Ό λ³€κ²½ν•©λ‹ˆλ‹€. μ •λ‹΅.