Home [learn-opengl] Lighting: Lighting maps
Post
Cancel

[learn-opengl] Lighting: Lighting maps

Lighting maps


  • 실제 사물들은 여러 material로 이루어져 있다.
  • 좀더 정확하게 묘사하도록 오브젝트의 시각적 출력에대해 유연성을 줘보자

Diffuse maps


  • 오브젝트에 대한 각각의 fragment들의 diffuse 컬러를 설정해야한다.

    • 이는 텍스처와 같다.
    • 빛이 존재하는 scene에서는 이 텍스처 이미지가 오브젝트의 모든 diffuse 컬러들을 나타내기 때문에 일반적으로 diffuse map 이라고 부른다.
  • 아래 이미지를 사용하여 작업을 할것이다. 이미지

  • 셰이더에서 diffuse map을 사용하는것은 정확히 텍스처와 동일.

    • 추가적으로, material struct내부에 sampler2D로 저장한다.(vec3sampler2D로)
    • 또한 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 data

    • 이 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);
  • 이제 아래와 같이 보일것이다.

diffuse_map

Specular maps


  • 위의 이미지에서 나무부분에 specular 하이라이트를 제거해보자.
  • 이를 위해 텍스처 맵하나를 사용한다.(아래 이미지)

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 같은 다른 텍스처 맵을 사용하여 디테일을 좀 더 살릴 수 있다.

출처

Lighting maps

This post is licensed under CC BY 4.0 by the author.

[learn-opengl] Lighting: Materials

[learn-opengl] Lighting: Light casters