Lighting maps
- 실제 사물들은 여러 material로 이루어져 있다.
- 좀더 정확하게 묘사하도록 오브젝트의 시각적 출력에대해 유연성을 줘보자
Diffuse maps
오브젝트에 대한 각각의 fragment들의 diffuse 컬러를 설정해야한다.
- 이는 텍스처와 같다.
- 빛이 존재하는 scene에서는 이 텍스처 이미지가 오브젝트의 모든 diffuse 컬러들을 나타내기 때문에 일반적으로
diffuse map
이라고 부른다.
아래 이미지를 사용하여 작업을 할것이다.
셰이더에서 diffuse map을 사용하는것은 정확히 텍스처와 동일.
- 추가적으로,
material struct
내부에sampler2D
로 저장한다.(vec3
을sampler2D
로) - 또한
ambient
컬러는 대부분 diffuse 컬러와 동일하므로, 제거한다. - 그리고 fragment 셰이더에 텍스처 좌표가 필요하므로 입력 변수 선언
- 추가적으로,
sampler2D
는 오직 uniform으로만 정의할 수 있는opaque type
이라고 불린다. 만약 uniform이 아닌 다른 형태로 인스턴스화(함수 파라미터 등) 한다면 오류, 이는 opaque type을 가지고 있는 모든 struct 에 동일하게 적용됨
1
2
3
4
5
6
struct Material {
sampler2D diffuse;
vec3 specular;
float shininess;
};
in vec2 TexCoords;
- fragment 셰이더에 diffuse 컬러 값을 얻기 위해 텍스처를 간단히 샘플링한다.
1
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
- 또한, ambient material 도 diffuse matterial 컬러와 똑같게한다.
1
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
이제 vertex 데이터에 텍스처 좌표를 업데이트하고,
vertex attribute
로서 fragment shader로 전달해야한다.- 텍스처를 로드하고 적절한 텍스처 유닛에 바인딩
- 이 vertex 데이터는 지금 큐브의 각 vertex에 대해 vertex 위치, 법선 벡터, 텍스처 좌표를 포함한다,
수정된 fragment 셰이더는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
...
out vec2 TexCoords;
void main()
{
...
TexCoords = aTexCoords;
}
- VAO 역시 수정해야한다.
1
2
3
4
5
lightingShader.setInt("material.diffuse", 0);
...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
- 이제 아래와 같이 보일것이다.
Specular maps
- 위의 이미지에서 나무부분에 specular 하이라이트를 제거해보자.
- 이를 위해 텍스처 맵하나를 사용한다.(아래 이미지)
- specular 하이라이트의 세기는 위 이미지의 각 픽셀의 밝기로 얻을 수 있다.
- 검정색 =>
vec3(0.0)
=> 어두워짐 fragment shader
에서 해당 컬러 값을 샘플링하고, light의 specular 세기와 곱한다.
- 검정색 =>
Sampling specular maps
Specular map
은 다른 텍스처들과 비슷diffuse map
코드와 비슷
아래와 같이 다른 채널 1에 바인딩
1
2
3
4
lightingShader.setInt("material.specular", 1);
...
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, specularMap);
sampler2D
로 변경
1
2
3
4
5
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
- 샘플링
1
2
3
4
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
FragColor = vec4(ambient + diffuse + specular, 1.0);
- 흑백 이미지를 사용하여 오직 세기만을 얻는다.
- 이런 매핑을 통해, 디테일을 살릴 수 있음. Normal/Bump map 이나 reflection maps 같은 다른 텍스처 맵을 사용하여 디테일을 좀 더 살릴 수 있다.