12 - More Lighting, Texture
Revised Class Schedule
- ์ด์ ์ ๊ณต์ ๋ ๊ฐ์ ์ผ์ ๋ฐ ๊ธฐ๋ง ์ํ ๋ฒ์์ ์ค๋ฅ๊ฐ ์์์ต๋๋ค.
- ์์ธํ ๋ด์ฉ์ LMS ๊ฒ์๊ธ ์ฐธ์กฐ:
https://learning.hanyang.ac.kr/courses/178704/discussion_topics/418144 - ์์ ๋ ์ผ์ :
- Lecture 12: 6์ 5์ผ
- Lecture 13 (๋ง์ง๋ง ์์ ): 6์ 12์ผ (Lab ์์)
Final Exam Announcement
์ผ์: 6์ 18์ผ (์), ์คํ 6:30โ7:30
์ฅ์: IT/BT Room 911
๋ฒ์: Lecture 8โ12, Lab 8โ12
์ํ ์์ ํ 30๋ถ ์ ์๋ ํด์คํ ์ ์์ต๋๋ค. (์ํ์ ์ผ์ฐ ๋๋ด๋๋ผ๋)
์ฆ, ์ํ ์์ ํ 30๋ถ ์ดํ์๋ ์ ์ฅํ ์ ์์ต๋๋ค. (์ง๊ฐ ์ ๋ ๊ธ์ง!)
ํ์์ฆ์ ๋ฐ๋์ ์ง์ฐธํ ๊ฒ
Outline
More Lighting
- BRDF
- Local & Global Illumination
Texture Mapping
- ๊ฐ๋
- UV Mapping
- Texture Mapping ๊ณผ์
- Texture ์ขํ ํจ์ ์ ์
- Texture๊ฐ ์ ์ฉ๋ ๊ฐ์ฒด ๋ ๋๋ง
- Diffuse, Specular, Normal Map
- Texture Map์ ๋ค์ํ ํ์ฉ
More Lighting
Recall: Reflection of General Materials
- ๋ง์ ์ฌ์ง์ ํ๋ฉด์ diffuse reflection๊ณผ specular reflection์ ๋ชจ๋ ๊ฐ์ง
- ํ๋ฉด์ ๋ฐ์ฌ ํน์ฑ์ ๋ถํฌ ํจ์(distribution function)๋ก ํํ ๊ฐ๋ฅ
- โ BRDF
Bidirectional Reflectance Distribution Function (BRDF)
๋ถํฌ๋ช ํ๋ฉด์์ ๋น์ด ์ด๋ป๊ฒ ๋ฐ์ฌ๋๋์ง ์ ์
- : ์ ์ฌ๊ด ๋ฐฉํฅ
- : ๋ฐ์ฌ๊ด ๋ฐฉํฅ
- : ์ถ์ฌ ๋ฐฉํฅ์ ๋ฐ๋ฅธ ๋ฐ์ฌ ๋ณต์ฌ๋ ๋น์จ์ ๋ฐํ
์์ ํํ:
Examples of BRDF
(theoretical approximation, not from measurement)
- ์๋์ฐจ ๋ฐฑ๋ฏธ๋ฌ์ ๊ฐํ ๋ฐ์ฌ
- ๋ถํ ํ๋ฉด์ฒ๋ผ ๋งค์ฐ diffuseํ ์ฌ์ง
- ๋๋ฆฌ์ ๋ฐ๋ฅ๊ณผ ๊ฐ์ด ๊ดํ์ด ์๋ ํ๋ฉด
- ์ฌ๊ณผ์ฒ๋ผ ๋ณตํฉ ๋ฐ์ฌ๋ฅผ ๊ฐ์ง ์ฌ์ง
Phong Illumination Model & BRDF
- Phong ๋ชจ๋ธ์ ๋ค์ ๋ ๊ฐ์ง๋ฅผ ๊ฐ์ง BRDF๋ฅผ ๋ชจ๋ธ๋งํจ:
- ๋ฐ๊ตฌ(hemisphere): diffuse ์ฑ๋ถ ํํ
- lobe(๋ก๋ธ): specular ์ฑ๋ถ์ cosโฟ(ฮฑ) ํํ๋ก ํํ
Measuring BRDF
- ํน์ ์ฌ์ง์ BRDF๋ ๋ค์๊ณผ ๊ฐ์ ์ฅ๋น๋ก ์ธก์ ๊ฐ๋ฅ:
- ๊ธฐ๋ณธ ๊ฐ๋ : ํ์ ํ๋ ๊ด์๊ณผ ํ์ ํ๋ ์ผ์ ์ฌ์ฉ
Using Measured BRDF for Rendering
- ์ธก์ ๋ BRDF๋ ๋ ๋๋ง์ ์ฌ์ฉ๋ ์ ์์
Measured BRDF | Nickel | Pink fabric | Gray plastic | Nylon |
---|---|---|---|---|
Rendered object | ๋ ๋๋ง๋ ์ค๋ธ์ ํธ | |||
Real object example | ์ค์ ๋ฌผ์ฒด ์์ |
Local vs. Global Illumination
- Local (๋๋ direct, non-global) illumination
- ๊ด์์์ ์ง์ ์ค๋ ๋น๋ง์ ๋ชจ๋ธ๋ง
- ๋น ๋ฅด๊ฒ ๋ ๋๋ง ๊ฐ๋ฅํ์ง๋ง, ์ฌ์ค์ฑ์ด ๋จ์ด์ง
- ์: Phong illumination ๋ชจ๋ธ
(๊ทธ๋ฆผ: Direct illumination ์์)
- Global illumination
- ์ง์ ์กฐ๋ช +
- ๋ค๋ฅธ ๋ฌผ์ฒด์์ ๋ฐ์ฌ๋ ๊ฐ์ ์กฐ๋ช (inter-object reflections) ํฌํจ
- ํจ์ฌ ๋ ์ฌ์ค์
- ์: Ray tracing, Path tracing, Radiosity
(๊ทธ๋ฆผ: ์ง์ ์กฐ๋ช + ๊ฐ์ ์กฐ๋ช = ์ ์ญ ์กฐ๋ช )
Phong Illumination Model & Local, Global Illumination
- Phong ์กฐ๋ช ๋ชจ๋ธ์ ๊ธฐ๋ณธ์ ์ผ๋ก local illumination model
- ๊ฐ์ ์กฐ๋ช ์ ์ฃผ๋ณ๊ด(ambient component)์ผ๋ก๋ง ๋๋ต์ ์ผ๋ก ๊ทผ์ฌ๋จ
(๊ทธ๋ฆผ: Phong direct vs. ambient ๊ทผ์ฌ ๋น๊ต)
Texture Mapping
ํ๋ฉด์์ ์์น์ ๋ฐ๋ผ ํ๋ฉด ์์ฑ์ ์ ์ํ๋ ๊ธฐ๋ฒ
๋ณดํต 2D texture ์ด๋ฏธ์ง(= texture map)๋ฅผ 3D ๊ฐ์ฒด ํ๋ฉด์ ์ ์ฉ
์ฃผ์ ๋ชฉ์ : ํ๋ฉด ๋ํ ์ผ ์ถ๊ฐ
- ๊ณ ํด๋ฆฌ๊ณค ๋ชจ๋ธ๋ณด๋ค
- ๋ ์ ์ ํด๋ฆฌ๊ณค์ผ๋ก ๋์ ๋ํ ์ผ ํํ ๊ฐ๋ฅ
- ๋ ๋๋ง ์๋ ๋ํญ ํฅ์
- texture map์ ๋ณต์ก๋๋ ์ฒ๋ฆฌ ๋ณต์ก๋์ ์ํฅ ์์
(๊ทธ๋ฆผ: ๊ณ ์ ๋ฐ vs. ํ ์ค์ฒ ์ ์ฉ ๋ชจ๋ธ)
UV Mapping
Texture mapping์ ๋ณดํต UV mapping์ ํตํด ์ ์๋จ
UV mapping: 2D ํ ์ค์ฒ ์ขํ (u, v)๋ฅผ 3D ๋ชจ๋ธ์ ๊ฐ ์ ์ ์ ๋งคํ
- ๊ฐ ์ ์ ์ด 2D ์ด๋ฏธ์ง์์ ์ด๋ค ์์น์ ๋์๋๋์ง ์ค๋ช
UV mapping ํจ์๋ texture coordinate function์ผ๋ก๋ ๋ถ๋ฆผ
(๊ทธ๋ฆผ: UV ์ขํ ๋ฐ ๋งคํ ์์)
Texture Mapping Process
- ํ๋ฉด์ ์ ์ UV ๊ณต๊ฐ(UV map)์์์ ์ ์ ๋งคํ (UV mapping)
- ํด๋น UV ์ขํ๋ฅผ ํ ์ค์ฒ ์์ ์ ์ผ๋ก ๋งคํ
- Step 2๋ ๋จ์ ์ค์ผ์ผ๋ง์ด๋ฉฐ ์์คํ ์ด ์๋ ์ํ
- Step 1์ด ๋ฐ๋ก ์ฐ๋ฆฌ๊ฐ ์ ์ํด์ผ ํ texture coordinate function
(๊ทธ๋ฆผ: ์ง๊ตฌ ํ๋ฉด UV๋ก ํด๊ธฐ)
Defining Texture Coordinate Function:
- Creating "UV map"
- ๋ฌผ์ฒด ํ๋ฉด์ "ํผ์น๊ธฐ(Unwrap)"
- Blender ๋ฑ 3D ๋ชจ๋ธ๋ง ํด์์ ์๋ ์ํ๋จ
- ํ์ ์, ์ํฐ์คํธ๊ฐ ์์์ ์ผ๋ก UV ์ขํ๋ฅผ ์ถ๊ฐ ๋ณด์ ํ๊ธฐ๋ ํจ
"Unwrapping"
- ์๋ "unwrapping" ์๊ณ ๋ฆฌ์ฆ
- ์ผ๋ถ ์ต์ ํ ์๊ณ ๋ฆฌ์ฆ์ 3D ๊ฐ์ฒด๋ฅผ ํผ์น ๋ ๊ฐ ์ ์ ์ (u, v)๋ฅผ ๋ถ๋๋ฝ๊ณ ์๊ณก์ด ์ ์ ๋ฐฉ์์ผ๋ก ์ ํ
- Blender, Maya ๋ฑ ๋ค์ํ 3D ๋ชจ๋ธ๋ง ํด์ ๊ฐ๊ธฐ ๋ค๋ฅธ unwrapping ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉ
(๊ทธ๋ฆผ: ๋ค์ํ unwrap ์์)
UV Map Examples
(๊ทธ๋ฆผ: ๋๋ฌด ์์ ๋ฐ ๋ฒ์ฏ ๋ชจ๋ธ์ UV ๋งคํ ์์)
(๊ทธ๋ฆผ: ์บ๋ฆญํฐ, ์๋์ฐจ ๋ฑ ๋ค์ํ UV ๋งคํ ์์)
Defining Texture Coordinate Function:
- Projections to Parametric Surfaces
- ์ฌ๊ฐํ, ๊ตฌ, ์๊ธฐ๋ฅ ๋ฑ ํ๋ผ๋ฉํธ๋ฆญ ํ๋ฉด(parametric surfaces)๊ณผ ์ ์ฌํ ๊ฐ์ฒด๋
- ํด๋น ํ๋ผ๋ฉํธ๋ฆญ ํ๋ฉด์ ์ ์ ์ ํฌ์ฌํ์ฌ ํ ์ค์ฒ ์ขํ ํจ์๋ฅผ ์ ์ํ ์ ์์
Examples of coordinate functions
Planar projection
(๊ทธ๋ฆผ: ํ๋ฉด ํฌ์์ ์ํ UV ๋ถํฌ) Spherical projection
(๊ทธ๋ฆผ: ๊ตฌ๋ฉด ํฌ์์ ์ํ ์ง๊ตฌ ํ ์ค์ฒ ์ ์ฉ)
Cylindrical projection
(๊ทธ๋ฆผ: ์ค๋ฆฐ๋ ํํ๋ก ํฌ์๋ ํ ์ค์ฒ)
Rendering Texture-Mapped Objects
for each pixel:
(u, v) = texture coordinates at pixel
color = texture.get_color(u, v)
pixel.color = color
- ๊ทธ๋ฌ๋ ํ ์ค์ฒ ์ขํ ํจ์๋ ๊ฐ ์ ์ (vertex)์ ๋ํด ์ ์๋จ
- ๊ทธ๋ ๋ค๋ฉด ๊ฐ ํฝ์ ๋ง๋ค์ ํ ์ค์ฒ ์ขํ๋ ์ด๋ป๊ฒ ๊ณ์ฐํ ์ ์์๊น?
- ํ ์ค์ฒ ์ขํ๋ ๋ค๊ฐํ ๋ด๋ถ์์ barycentric interpolation์ผ๋ก ๊ณ์ฐ๋จ
- ๋ค๊ฐํ ๋ด๋ถ์ ๊ฐ ํฝ์
์ ๋ํด, ํฝ์
์ด ํฌํจ๋ ์ผ๊ฐํ์ ์ ์ ์ขํ์ ๋ฐ๋ผ
(u, v)
๊ฐ ๊ฒฐ์ ๋จ
Diffuse, Specular, Normal Maps
- ํ
์ค์ฒ ๋งต์ ํตํด ์ ์ํ ์ ์๋ ํ๋ฉด ์์ฑ์?
- diffuse color, specular color
- specular ์ง์, ํฌ๋ช ๋, ๋ฐ์ฌ์จ ๊ณ์
- surface normal
- ๊ทธ๋ฆผ์ ๋๋ ๋ฐ์ฌ ์ ๋ณด
- ๊ธฐํ
Examples of Diffuse, Specular, Normal Map
(์ผ์ชฝ๋ถํฐ)
- diffuse map
- specular map
- normal map
(์์: Game of Thrones ์บ๋ฆญํฐ ํ ์ค์ฒ)
- final ๋ ๋๋ง
- diffuse
- specular
- wireframe
- normal
- texture map
Normal Mapping - Motivation
circle, sphere ๋น๊ต
circle์ ์ผ๊ฐํ ๊ฐ์๊ฐ ์ ์ด ๋ ๋๋ง์ด ๋ ๋น ๋ฆ
normal vector๊ฐ ์ ์ ํ๋ฉด circle๋ sphere์ฒ๋ผ ๋ณด์ผ ์ ์์
์ธ๊ฐ ์๊ฐ์ ์ค์ ํ์์ด ์๋ ๋ฐ๊ธฐ ํจํด์ผ๋ก ํํ๋ฅผ ์ธ์
- ์ฆ, ๋ฐ๊ณ ์ด๋์ด ์์ญ์ ํจํด์ normal์ ์ํด ๊ฒฐ์ ๋จ
Normal Mapping - Basic Idea
๋ชฉํ: ๊ณ ํด๋ฆฌ ๋ชจ๋ธ์ฒ๋ผ ๋ณด์ด๋ ์ ํด๋ฆฌ ๋ชจ๋ธ ๋ง๋ค๊ธฐ
- ๊ณ ํด๋ฆฌ ๋ชจ๋ธ์ normal์ ํ ์ค์ฒ ์ด๋ฏธ์ง์ somehow ์ธ์ฝ๋ฉ
- ๊ทธ ํ ์ค์ฒ ์ด๋ฏธ์ง๋ฅผ ์ ํด๋ฆฌ ๋ชจ๋ธ์ ์ ์ฉ
(๊ทธ๋ฆผ: normal ์ ํ ์์)
Normal Mapping - Example
- ์ข: high-poly (814 triangles)
- ์ค: simplified (900 triangles)
- ์ฐ: ๋ ๊ฐ๋จํ ๋ชจ๋ธ (200 triangles)
Normal Mapping - Details
- ๊ณ ํด๋ฆฌ(high-poly) ๋ชจ๋ธ์ normal vector๋ฅผ ๊ฐ ํฝ์ ์ RGB ๊ฐ์ผ๋ก ์ธ์ฝ๋ฉ
- tangent space normal map์์๋ ํฝ์ RGB๊ฐ u, v, w ์ถ์ ํด๋นํ๋ normal ์ฑ๋ถ์ ๋ํ๋
ํ๊ธฐ:
R = Nแตค, G = Nแตฅ, B = Nสท
u: ํ ์ค์ฒ u์ถ
v: ํ ์ค์ฒ v์ถ
w: ํ๋ฉด์ ์ค์ normal ๋ฐฉํฅ
R = Nแตค, G = Nแตฅ, B = Nสท
- U: -1 to +1 โ Red: 0 to 255
- V: -1 to +1 โ Green: 0 to 255
- W: 0 to +1 โ Blue: 128 to 255
tangent space normal map์ด ํธ๋ฅด์ค๋ฆํ ์ด์ :
- ๋๋ถ๋ถ์ normal์ tangent space ๊ธฐ์ค
(128, 128, 255)
๊ทผ์ฒ์ด๊ธฐ ๋๋ฌธ
- ๋๋ถ๋ถ์ normal์ tangent space ๊ธฐ์ค
Bump Mapping
๋ชฉ์ ์ normal mapping๊ณผ ๋์ผ
ํต์ฌ ์์ด๋์ด:
- normal vector๋ฅผ ์ธ์ฝ๋ฉํ๋ ๋์ ์๋์ ์ธ ๋์ด(relative heights)๋ฅผ ์ ์ฅ
- ๊ฒ์ : ์ต์ ๋์ด ๋ณํ
- ํฐ์: ์ต๋ ๋์ด ๋ณํ
- normal vector๋ฅผ ์ธ์ฝ๋ฉํ๋ ๋์ ์๋์ ์ธ ๋์ด(relative heights)๋ฅผ ์ ์ฅ
normal์ ๋์ด๋งต์ผ๋ก๋ถํฐ ๊ณ์ฐํ์ฌ ์ ์ฉ
Bump Mapping Example
(๊ทธ๋ฆผ: ์๋ณธ ์ค๋ธ์ ํธ + bump map = bump๊ฐ ์ ์ฉ๋ ๊ฒฐ๊ณผ)
Displacement Mapping
height map์ ๋์ด ๋ณํ๋์ ์ฐธ์กฐํ์ฌ ์ค์ ๋ก ์ ์ ์ ์์น๋ฅผ ์ด๋์ํด
- bump/normal mapping๊ณผ ๋ฌ๋ฆฌ ์ค๋ฃจ์ฃ ๋ฐ ์๊ธฐ ๊ทธ๋ฆผ์(self-shadowing)๊ฐ ์์ฐ์ค๋ฝ๊ฒ ํํ๋จ
๊ธฐ๋ณธ์ ์ผ๋ก normal/bump์ฒ๋ผ ์ ์ ๊ฐ์ ์ธ๋ถ ํํ์ ์ ๊ณตํ์ง๋ ์์
- ์ธ๋ถ ํํ์ ๋์ด๋ ค๋ฉด ์ ์ ์ ๋ ์ถ๊ฐํด์ผ ํ๋ฏ๋ก ์ฐ์ฐ๋ ์ฆ๊ฐ
(๊ทธ๋ฆผ: subdivision ์ ๋์ ๋ฐ๋ฅธ displacement ์ฐจ์ด)
[Demo] Normal / Bump / Displacement Mapping
- Normal mapping / Displacement mapping
- https://threejs.org/examples/#webgl_materials_displacementmap
- Bump mapping
- https://threejs.org/examples/#webgl_materials_bumpmap
Light Map
- light map์ ์ฌ์ ๊ณ์ฐ๋ ์กฐ๋ช ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉ๋จ
ํญ๋ชฉ | Texture Maps | Light Maps |
---|---|---|
๋ฐ์ดํฐ | RGB | ๋ฐ๊ธฐ(Intensity) |
ํด์๋ | ๋์ | ๋ฎ์ |
(์ด๋ฏธ์ง: ํ ์ค์ฒ๋ง ์ ์ฉ๋ ์ฅ๋ฉด vs. ๋ผ์ดํธ๋งต์ด ์ ์ฉ๋ ์ฅ๋ฉด ๋น๊ต)
Shadow Map
- light view์์์ depth map์ ์ด์ฉํด ์ํ ์ง์ ์ด ๋ณด์ด๋์ง๋ฅผ ํ๋จ
- ๋์๋ ๋ณด์ด์ง๋ง ๊ด์์ ๊ฐ๋ ค์ง ์ง์ ์ ๊ทธ๋ฆผ์๋ก ํ์๋จ
(๊ทธ๋ฆผ: teapot์ ๊ธฐ์ค์ผ๋ก ๊ด์ ๋ฐฉํฅ์์ ๊น์ด ํ์ธ)
Environment Map
- ๋ณต์กํ ๊ฑฐ์ธ๊ฐ์ ํจ๊ณผ๋ฅผ ๊ฐ๋ ๊ฐ์ฒด ์๋ฎฌ๋ ์ด์
- ๊ฐ์ฒด ์ฃผ๋ณ ํ๊ฒฝ์ ํ ์ค์ฒ๋ก ์บก์ฒ
- ํ๋ฉด normal์ ์ด์ฉํด ํ ์ค์ฒ ์ขํ ๊ณ์ฐ
(๊ทธ๋ฆผ: ๊ตฌ๋ฉด์ ์ ์ฉ๋ environment map)
[Practice] Online Demos
Light mapping
- https://threejs.org/examples/?q=light#webgl_lights_physical
Shadow mapping
- https://threejs.org/examples/#webgl_shadowmap
Environment mapping
- https://threejs.org/examples/#webgl_materials_cubemap_dynamic
- https://threejs.org/examples/?q=refrac#webgl_materials_cubemap_refraction
12 - Lab - Texture Mapping
Outline
- Pillow ์ค์น
- ํ ์ค์ฒ๊ฐ ์ ์ฉ๋ ๋จ์ผ ์ผ๊ฐํ
- ํ ์ค์ฒ ํํฐ๋ง
- ๋ฐ๋งต
- ํ ์ค์ฒ ๋ํ
- ๋ค์ค ํ ์ค์ฒ
Install Pillow
Pillow: ๋์ค์ ์ธ ํ์ด์ฌ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ค์น:
$ workon cg-course
$ pip install pillow
- ๋ฌธ์:
https://pillow.readthedocs.io/en/stable/index.html
[Code] 1-triangle-texture
- "5-Lab-3DTransformations-VertProcess/1/3-lookat.py"์์ ์์
- ํ๋ ์์ ๊ทธ๋ฆฌ๋ ์ฝ๋ ์ ๊ฑฐ
- PIL(Pillow) ๋ชจ๋ import:
from PIL import Image
- VAO
- ์ด์ vertex ๋ฐ์ดํฐ์๋ ๊ผญ์ง์ ์์น์ ์์๋ฟ ์๋๋ผ ํ ์ค์ฒ ์ขํ๋ ํฌํจ๋จ
vertex ๋ฐฐ์ด ๊ตฌ์ฑ ์์:
# positions # colors # texture coordinates
0.0, 0.5, 0.0, 1.0, 0.0, 0.0, 0.5, 1.0,
-0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0
- VAO ์์ฑ ๋ฐ ํ์ฑํ
- VBO ์์ฑ ๋ฐ ๋ฐ์ดํฐ ๋ณต์ฌ
def prepare_vao_triangle():
# ๊ผญ์ง์ ์์น ์์ฑ ์ค์
glVertexAttribPointer(index, size, type, normalized, stride, pointer)
glEnableVertexAttribArray(index)
# ๊ผญ์ง์ ์์ ์์ฑ ์ค์
glVertexAttribPointer(...)
glEnableVertexAttribArray(...)
# ํ
์ค์ฒ ์ขํ ์์ฑ ์ค์ - 2D ๋ฐ์ดํฐ
glVertexAttribPointer(...)
glEnableVertexAttribArray(...)
return VAO
์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ๊ณ ํ ์ค์ฒ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ณผ์
ํ ์ค์ฒ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๋ฐ์ธ๋ฉ:
glGenTextures
,glBindTexture
์ด๋ฏธ์ง ๋ก๋: Pillow ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ (
Image.open
)๋ก๋ํ ์ด๋ฏธ์ง๋ฅผ ํ ์ค์ฒ๋ก ์ค์ :
glTexImage2D
def main():
# ํ
์ค์ฒ ๊ฐ์ฒด ์์ฑ
texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)
# ํ
์ค์ฒ ํํฐ๋ง ํ๋ผ๋ฏธํฐ ์ค์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
try:
img = Image.open("./A02pysc-Solarsystemscope_texture_8k_earth_daymap.jpg")
# ์ด๋ฏธ์ง ์์ง ๋ค์ง๊ธฐ (OpenGL์ y์ถ ๋ฐฉํฅ ๋๋ฌธ)
img = img.transpose(Image.FLIP_TOP_BOTTOM)
# ํ
์ค์ฒ ์ด๋ฏธ์ง๋ก ์ค์
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width, img.height, 0,
GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())
img.close()
except:
print("Failed to load texture")
glTexImage2D
ํจ์ ์ฌ์ฉ ์์ ๋ฐ ์ค๋ช
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width, img.height, 0,
GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())
glTexImage2D(target, level, internalformat, width, height, border, format, type, data)
target
: ํ ์ค์ฒ ๋์. GL_TEXTURE_2D๋ก ์ค์ level
: ๋ํ ์ผ ๋ ๋ฒจ. ๋ณดํต 0 (glGenerateMipmap ์ฌ์ฉ ์ ๋ณ๊ฒฝ ๊ฐ๋ฅ)internalformat
: ํ ์ค์ฒ๋ฅผ ์ ์ฅํ ๋ด๋ถ ํฌ๋งทwidth
,height
: ์ด๋ฏธ์ง ํฌ๊ธฐborder
:0
(๋ ๊ฑฐ์ ๊ฐ)format
,type
: ์๋ณธ ์ด๋ฏธ์ง์ ํฌ๋งท๊ณผ ๋ฐ์ดํฐ ํ์data
: ๋ฉ๋ชจ๋ฆฌ ์์ ์ด๋ฏธ์ง ๋ฐ์ดํฐ
- Vertex Shader ์ฝ๋
#version 330 core
layout (location = 0) in vec3 vin_pos;
layout (location = 1) in vec3 vin_color;
layout (location = 2) in vec2 vin_uv;
out vec3 vout_color;
out vec2 vout_uv;
uniform mat4 MVP;
void main() {
// ๋์ฐจ ์ขํ๊ณ์์์ 3D ์์น ๊ณ์ฐ
vec4 pos4 = vec4(vin_pos.xyz, 1.0);
gl_Position = MVP * pos4;
vout_color = vec4(vin_color, 1.0);
vout_uv = vin_uv;
}
- Fragment Shader ์ฝ๋
#version 330 core
in vec2 vout_uv; // ๋ณด๊ฐ๋ ํ
์ค์ฒ ์ขํ
in vec3 vout_color;
out vec4 FragColor;
uniform sampler2D texture1; // GLSL ๋ด์ฅ sampler ํ์
void main()
{
// FragColor = vec4(vout_color, 1.0); // ์์๋ง ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
// ํ
์ค์ฒ ์ขํ์ ๋ฐ๋ผ ์์ ์ํ๋ง
FragColor = texture(texture1, vout_uv);
}
- ์ต์ข ๊ทธ๋ฆฌ๊ธฐ ๋ฃจํ
def main():
...
while not glfwWindowShouldClose(window):
# ํ์ฌ ํ๋ ์ ๊ธฐ์ค์ผ๋ก ์ผ๊ฐํ์ ๊ทธ๋ฆผ
glBindVertexArray(vao_triangle)
glDrawArrays(GL_TRIANGLES, 0, 3)
...
- ์์ง uniform ๋ณ์
texture1
์ ๊ฐ์ ์ค์ ํ์ง ์์ - GLSL์์๋ sampler uniform์ด ๊ธฐ๋ณธ๊ฐ 0์ผ๋ก ์ค์ ๋๋ค๋ ๋ณด์ฅ์ด ์์
- ๋๋ถ๋ถ ๋๋ผ์ด๋ฒ์์ ๊ธฐ๋ณธ๊ฐ์ด 0(GL_TEXTURE0)์ด๊ธฐ ๋๋ฌธ์ ์ ์๋ํ์ง๋ง,
ํ๋ซํผ์ด๋ GPU์ ๋ฐ๋ผ ๋ช ์์ ์ผ๋ก ์ง์ ํด์ฃผ๋ ๊ฒ์ด ์์ ํจ - ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ฌ uniform ๋ฐ์ธ๋ฉ์ ๋ช ํํ ์ค์ :
loc_texture1 = glGetUniformLocation(shader_program, "texture1");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(loc_texture1, 0);
(์ด๋ฏธ์ง ์ค๋ช : ์ข์ธก ํ๋จ ๊ทธ๋ฆผ์ ์ง๊ตฌ ํ ์ค์ฒ๋ฅผ ์ผ๊ฐํ์ ๋งคํํ ์์์)
[Code] 2-triangle-texture-color
- vertex ์์๊ณผ ํ ์ค์ฒ๋ฅผ ํจ๊ป ์ฌ์ฉํ ์ ์์
- ์: ํ ์ค์ฒ ๊ฐ์ ์์ ๊ฐ์ ๊ณฑํด ์๊ฐ์ ํจ๊ณผ ์ถ๊ฐ
void main() {
...
FragColor = texture(texture1, vout_uv) * vout_color;
}
(์ด๋ฏธ์ง ์ค๋ช : ์์์ด ์ ์ฉ๋ ์ง๊ตฌ ์ด๋ฏธ์ง์ ํ ์ค์ฒ ์์)
[Code] 3-triangle-texture-filter
- ๋ ํฐ ์ผ๊ฐํ์ ๊ทธ๋ ค๋ณด์
def main():
while not glfwWindowShouldClose(window):
...
# ๋ชจ๋ธ๋ง ํ๋ ฌ
M = glm.mat4()
M = glm.scale(glm.vec3(3.5, 5.5, 1.0))
...
(์ด๋ฏธ์ง ์ค๋ช : ํ๋๋ ์ผ๊ฐํ์ ์ ํด์๋ ํ ์ค์ฒ๊ฐ ๋๋ ทํ๊ฒ ๋ณด์)
- ๋ ๋ถ๋๋ฌ์ด ๊ฒฐ๊ณผ๋ฅผ ์ป์ผ๋ ค๋ฉด?
(์ด๋ฏธ์ง ์ค๋ช
: ์ผ์ชฝ์ GL_NEAREST๋ก ํฝ์
์ด ๋๋ ทํจ, ์ค๋ฅธ์ชฝ์ GL_LINEAR๋ก
๋ณด๊ฐ๋์ด ๋ถ๋๋ฝ๊ฒ ํํ๋จ)
- ํ
์ค์ฒ ํํฐ๋ง(Texture filtering)์ ์ฃผ์ด์ง
(u, v)
์ ๋ํ ์์ ๊ฐ์ ๊ณ์ฐํ๋ ๋ฐฉ์ ์ง์ - ํ ์ค์ฒ ์ขํ๋ ์ค์์ด๋ฏ๋ก ์ ํํ ํฝ์ ์ค์ฌ๊ณผ ์ผ์นํ์ง ์์ ์ ์์
GL_NEAREST
: ๊ฐ์ฅ ๊ฐ๊น์ด ํ ์ (texel)์ ์์์ ์ฌ์ฉ (ํฝ์ ํ๋ ๊ฒฐ๊ณผ)GL_LINEAR
: ์ฃผ๋ณ ํ ์ ์ ๋ณด๊ฐํ์ฌ ์์์ ๊ณ์ฐ (๋ถ๋๋ฌ์ด ๊ฒฐ๊ณผ) (์ด๋ฏธ์ง ์ค๋ช : ์ข์ธก์ Nearest ํํฐ, ์ฐ์ธก์ Linear ํํฐ์ ๋ฐ๋ฅธ ํฝ์ ์๊ฐํ ์์)MIN
ํํฐ์MAG
ํํฐ๋ฅผ ๊ตฌ๋ถํด์ ์ค์ ๊ฐ๋ฅMIN
ํํฐ: ์ถ์ ์MAG
ํํฐ: ํ๋ ์
def main():
...
# ํ
์ค์ฒ ์์ฑ
texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)
# GL_NEAREST ์ค์ ์์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
# GL_LINEAR ์ค์ ์์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
try:
img = Image.open("./230px-Solarsystemscope_texture_8k_earth_daymap.jpg")
(์ด๋ฏธ์ง ์ค๋ช : Python ์ฝ๋์์ MIN/MAG ํํฐ๋ฅผ GL_LINEAR ๋๋ GL_NEAREST๋ก ์ค์ ํ๋ ์์)
[Code] 4-triangle-texture-mipmaps
- ๊ณ ํด์๋ ํ ์ค์ฒ๋ฅผ ๋ฉ๋ฆฌ ์๋ ๋ฌผ์ฒด์ ์ฌ์ฉํ ๊ฒฝ์ฐ, ํ ํฝ์ ์ ๋ชจ๋ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ ๋นํจ์จ์ ์
- ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด mipmap ์ฌ์ฉ
- mipmap์ ๋์ผ ํ ์ค์ฒ์ ํด์๋๋ฅผ ์ ์ ๋ฎ์ถ ์ด๋ฏธ์ง ์งํฉ
- ๊ฐ์ฒด์์ ๊ฑฐ๋ฆฌ ๋ฑ์ ๋ฐ๋ผ ์ ์ ํ ํด์๋์ ๋ ๋ฒจ์ ์ ํํด ์ฌ์ฉ
- OpenGL์ ์๋์ผ๋ก ์ ์ ํ mipmap ๋ ๋ฒจ์ ์ ํ
(์ด๋ฏธ์ง ์ค๋ช : ๊ฐ ๋ ๋ฒจ๋ง๋ค ํ ์ค์ฒ ํด์๋๊ฐ ์ ๋ฐ์ฉ ์ค์ด๋ค๋ฉฐ, ํฝ์ ์์ค์ ์ํ๋ง์ด ์ด๋ฃจ์ด์ง)
def main():
...
# GL_TEXTURE_MIN_FILTER: ์ถ์ ์ ํํฐ๋ง ๋ฐฉ์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
# GL_LINEAR_MIPMAP_LINEAR: ์ธ์ ํ ๋ mipmap ๋ ๋ฒจ์์ ๊ฐ๊ฐ ์ ํ ๋ณด๊ฐ ํ, ๋ค์ ์ ํ ๋ณด๊ฐ
# GL_LINEAR_MIPMAP_NEAREST: ๊ฐ๊น์ด ๋ ๋ ๋ฒจ ์ค ํ๋ ์ ํ + ๋ด๋ถ๋ ์ ํ ๋ณด๊ฐ
# GL_TEXTURE_MAG_FILTER: ํ๋ ์ ํํฐ๋ง ๋ฐฉ์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width, img.height, 0,
GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())
glGenerateMipmap(GL_TEXTURE_2D)
[Code] 5-triangle-texture-wrap
ํ ์ค์ฒ ์ขํ๊ฐ
(0.0, 1.0)
๋ฒ์๋ฅผ ๋ฒ์ด๋ ๊ฒฝ์ฐ OpenGL์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ๊น?ํ ์ค์ฒ ๋ํ ๋ฐฉ์ 4๊ฐ์ง:
GL_REPEAT
: ๊ธฐ๋ณธ๊ฐ, ํ ์ค์ฒ ๋ฐ๋ณตGL_MIRRORED_REPEAT
: ๋ฐ์ ํ๋ฉฐ ๋ฐ๋ณตGL_CLAMP_TO_EDGE
: ๊ฐ์ฅ์๋ฆฌ๋ฅผ ๋๋ฆผGL_CLAMP_TO_BORDER
: ํ ๋๋ฆฌ ์์์ผ๋ก ์ฑ์
(์ด๋ฏธ์ง ์ค๋ช : ๊ฐ๊ฐ์ wrapping ๋ชจ๋์ ๋ฐ๋ฅธ ์๊ฐ์ ์ฐจ์ด ๋น๊ต)
def prepare_vao_triangle():
vertices = glm.array(glm.float32,
# position # color # texture coordinates
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -0.5, -0.5, # v0
0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, -0.5, # v1
0.0, 0.5, 0.0, 0.0, 0.0, 1.0, -0.5, 2.0 # v2
)
(ํ ์ค์ฒ ์ขํ๊ฐ 0~1์ ๋ฒ์ด๋๋๋ก ์ง์ ํด wrap ๋ชจ๋์ ๋ฐ๋ฅธ ์ฐจ์ด๋ฅผ ์คํ)
def main():
...
# ๊ธฐ๋ณธ๊ฐ์ GL_REPEAT
# GL_TEXTURE_WRAP_S: ์ํ(u) ๋ฐฉํฅ ์ค์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT)
# GL_TEXTURE_WRAP_T: ์์ง(v) ๋ฐฉํฅ ์ค์
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
# ๊ฒฝ๊ณ์ ์ค์ (GL_CLAMP_TO_BORDER ์ ์ฌ์ฉ๋จ)
border_color = [1.0, 1.0, 1.0, 1.0]
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color)
try:
...
[Code] 6-cube-multiple-textures
- ๋ ๊ฐ์ ์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ์ฌ diffuse map๊ณผ specular map์ผ๋ก ๊ฐ๊ฐ ์ฌ์ฉ
- ๋ค์ํ ์กฐ๋ช ํจ๊ณผ ํํ ๊ฐ๋ฅ
(์ด๋ฏธ์ง ์ค๋ช : ์ผ์ชฝ์ diffuse map, ๊ฐ์ด๋ฐ๋ specular map, ์ค๋ฅธ์ชฝ์ ๊ฒฐ๊ณผ ํ๋ธ)
glUniform1i
๋ฅผ ์ฌ์ฉํ์ฌ sampler uniform์ texture unit์ ์์น๋ฅผ ํ ๋น ๊ฐ๋ฅ- ์ด๋ฅผ ํตํด fragment shader์์ ์ฌ๋ฌ ํ ์ค์ฒ๋ฅผ ๋์์ ์ฌ์ฉํ ์ ์์
- ๊ธฐ๋ณธ ๋ฐฉ์:
- ๊ฐ sampler ๋ณ์์ ๋ํด
glUniform1i
๋ก texture unit ์ธ๋ฑ์ค ์ง์ glActiveTexture(GL_TEXTUREi)
๋ก ํ์ฑํglBindTexture(GL_TEXTURE_2D, texture)
๋ก ๋ฐ์ธ๋ฉ
- ๊ฐ sampler ๋ณ์์ ๋ํด
(์์ฝ: diffuse map๊ณผ specular map์ ๋์์ ์ฌ์ฉํ๋ ๊ตฌ์กฐ)
8-Lab-Lighting/4-all-components-phong-faceonvm.py
์์ ์์- Pillow import
- VAO์ vertex data์ texture coordinate ์ถ๊ฐ
- sampler uniform ๋ณ์
texture_diffuse
,texture_specular
๋ฅผ ํ ์ค์ฒ ๊ฐ์ฒด์ ์ฐ๊ฒฐ - shader ๋ด๋ถ์์ diffuse/ambient๋
texture_diffuse
๋ก๋ถํฐ,
specular์texture_specular
๋ก๋ถํฐ ์ํ๋ง
def main():
# diffuse texture
texture_diffuse = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_diffuse)
try:
img = Image.open("./230px-Solarsystemscope_texture_8k_earth_daymap.jpg")
# specular texture
texture_specular = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_specular)
try:
img = Image.open("./plain-checkerboard.jpg")
# ์ ๋ํผ์ texture unit ์ธ๋ฑ์ค ์ง์
glUniform1i(glGetUniformLocation(shader_program, "texture_diffuse"), 0)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, texture_diffuse)
glUniform1i(glGetUniformLocation(shader_program, "texture_specular"), 1)
glActiveTexture(GL_TEXTURE1)
glBindTexture(GL_TEXTURE_2D, texture_specular)
- Vertex Shader
#version 330 core
layout (location = 0) in vec3 vin_pos;
layout (location = 1) in vec3 vin_normal;
layout (location = 2) in vec2 vin_uv;
out vec3 vout_surface_pos;
out vec3 vout_normal;
out vec2 vout_uv;
uniform mat4 MVP;
uniform mat4 M;
void main() {
vec4 pos4 = vec4(vin_pos.xyz, 1.0);
gl_Position = MVP * pos4;
vout_surface_pos = vec3(M * pos4);
vout_normal = normalize(mat3(transpose(inverse(M))) * vin_normal);
vout_uv = vin_uv;
}
- Fragment Shader
in vec2 vout_uv;
uniform sampler2D texture_diffuse;
uniform sampler2D texture_specular;
void main() {
// ์ฌ์ง ์์ ๊ณ์ฐ ์์
vec3 material_color = vec3(1.0, 0.0, 0.0); // ๊ธฐ๋ณธ๊ฐ
// ํ
์ค์ฒ์์ diffuse ์์ ์ํ๋ง
vec3 material_diffuse = vec3(texture(texture_diffuse, vout_uv));
// ๋น๊ธ์ ์ฌ์ง์์ specular ์ฌ์ฉ ์์
vec3 material_specular = vec3(texture(texture_specular, vout_uv));
// ์ต์ข
์์ ์กฐํฉ ์์
FragColor = vec4(diffuse + specular, 1.0);
}
- ํ๋ธ๋ฅผ ๊ตฌ์ฑํ๋ 12๊ฐ์ ์ผ๊ฐํ์ ๋ํด vertex ๋ฐ์ดํฐ ๊ตฌ์ฑ
def prepare_vao_cube():
vertices = glm.array(glm.float32,
# pos normal texcoord
-1, -1, 1, 0, 0, 1, 0, 0, # v0
1, -1, 1, 0, 0, 1, 1, 0, # v1
1, 1, 1, 0, 0, 1, 1, 1, # v2
-1, -1, 1, 0, 0, 1, 0, 0, # v0
1, 1, 1, 0, 0, 1, 1, 1, # v2
-1, 1, 1, 0, 0, 1, 0, 1, # v3
...
)