빛의반사(reflection)란 여러 물체가 있을 때 빛이 반사되어 오는 색 또한 할당하는 방법입니다. 예를들어 쇠구슬 여러개가 눈 앞에 있다고 생각해봅시다. 빛 반사 없이 쇠구슬만 그리면 보고있는 하나의 쇠구슬에 비춰지는 옆에있는 쇠구슬들이 보이지 않게되어 현실감이 떨어질 것입니다. 따라서 현실감을 반영하기 위해 빛 반사를 넣어야합니다.
그냥 구 두개와 텍스쳐를 입힌 평면을 하나 그린 그림입니다
여기서 반사를 입혀보겠습니다.
무엇이 바뀌었을까요?
서로 빛 반사가 됨과 동시에, 구와 평면의 색이 약간 옅어졌습니다. 일반적으로 원래 할당된 Color값에 반사된 물체의 color값을 더해주기 때문에 그 값만큼 기존의 값에서 빼야하기 때문입니다.
다음 그림을 보며 원리를 이해해봅시다. 원리는 https://pdy0930.tistory.com/54
이전 퐁 모델 글의 Specular부분에서와 똑같습니다. n과 d는 유닛벡터라는 점을 생각하여 유도하면 반사된 빛의 방향을 구할 수 있습니다.여기서 재귀문을 써서 몇번 반사될 것인지를 반드시 정해야 합니다. 그렇지 않으면 무한 반사되어 코드가 끊임없이 돌아가기 때문입니다.
다음 코드를 보며 명확히 이해해봅시다.
// 광선이 물체에 닿으면 그 물체의 색 반환
vec3 traceRay(Ray &ray, const int recurseLevel)
{
if (recurseLevel < 0)
return vec3(0.0f);
// Render first hit
const auto hit = FindClosestCollision(ray);
if (hit.d >= 0.0f)
{
glm::vec3 color(0.0f);
const vec3 dirToLight = glm::normalize(light.pos - hit.point);
{
glm::vec3 phongColor(0.0f);
const float diff = glm::max(dot(hit.normal, dirToLight), 0.0f);
const vec3 reflectDir = 2.0f * hit.normal * dot(dirToLight, hit.normal) - dirToLight;
const float specular = glm::pow(glm::max(glm::dot(-ray.dir, reflectDir), 0.0f), hit.obj->alpha);
if (hit.obj->ambTexture)
{
phongColor += hit.obj->amb * hit.obj->ambTexture->SampleLinear(hit.uv);
}
else
{
phongColor += hit.obj->amb;
}
if (hit.obj->difTexture)
{
phongColor += diff * hit.obj->dif * hit.obj->difTexture->SampleLinear(hit.uv);
}
else
{
phongColor += diff * hit.obj->dif;
}
phongColor += hit.obj->spec * specular;
color += phongColor * (1.0f - hit.obj->reflection);
if (hit.obj->reflection)
{
// 여기에 반사 구현
// 수치 오류 주의
// 반사광이 반환해준 색을 더할 때의 비율은 hit.obj->reflection
const vec3 reflectedDirection = glm::normalize(glm::dot(hit.normal, -ray.dir) * hit.normal*2.0f + ray.dir);
Ray nextRay = { hit.point+reflectedDirection*1e-2f,reflectedDirection};
color += traceRay(nextRay, recurseLevel - 1) * hit.obj->reflection;
}
}
return color;
}
return vec3(0.0f);
}
여기서 유의할 점은 Specular에서 유의할 점과 같은데, hit.point자리에서 Ray를 쏘면 안된다는 점입니다. 왜냐하면 빛 반사가 일어날 때 반사된 point에서 다시 Ray를 쏘는데 hit.point가 시작점이라 그 물체에 다시 한번 Ray가 맞는 현상이 일어나서 제대로 색이 반영이 안될 수 있기 때문입니다. 따라서 reflectedDirection*(1e-4f)이렇게 빛 방향으로 아주 조금 이동해서 똑같은 물체에 다시 Ray가 맞는 현상을 제거해야만 합니다.
강의 출처 :
https://honglab.co.kr/courses/graphicspt1
HongLab 홍정모 연구소
홍정모의 컴퓨터 그래픽스 새싹코스
honglab.co.kr
'Graphics Techniques' 카테고리의 다른 글
[Rasterization] 삼각형의 레스터화 (1) | 2024.10.24 |
---|---|
[Ray Tracing] - 투명한 구의 빛의 굴절 (0) | 2024.10.22 |
[Ray Tracing]- 수퍼 샘플링 (1) | 2024.10.22 |
[Ray Tracing] 월드좌표 도형에 텍스춰링 하는 방법 (3) | 2024.10.20 |
[Ray Tracing] Barycentric coordinates(무게 중심 좌표계)를 통한 텍스쳐 좌표 보간 (1) | 2024.10.17 |