새소식

인기 검색어

게임 개발/그래픽스

빛의 반사

  • -

기존 그냥 퐁 쉐이딩에서는 픽셀에서 ray를 쏴서 물체에 맞는 곳을 계산해주면 되었다.

이제 빛의 반사를 계산하기 위해서는 물체에 맞은 위치에서 또 ray를 쏴서 계산해주고, 또 그게 다른곳에 맞으면 거기서도 또 ray를 쏴서 계산해주고... recursive하게 계산을 해야 한다.

처음 ray가 물체에 맞아서 나온 color(그냥 퐁쉐이딩해서 나온color)와 첫번째 반사돼서 맞은 물체의 색,

두번째 반사돼서 맞은 물체의 색, 세번째 반사돼서 맞은 물체의 색... 을 적절히 섞어서 색을 결정하면 된다.

무한히 함수를 재귀호출 할 수 없기때문에 recursive level을 정해 놓고 해야 한다.

빛의 반사 개념
빛 반사 계산

// 광선이 물체에 닿으면 그 물체의 색 반환
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);

        // 그림자 생략
        //Ray shadowRay = { hit.point + dirToLight * 1e-4f, dirToLight };
        //if (FindClosestCollision(shadowRay).d < 0.0f)
        {
            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);

            // phong ambient
            if (hit.obj->ambTexture)
            {
                phongColor += hit.obj->amb * hit.obj->ambTexture->SampleLinear(hit.uv);
            }
            else
            {
                phongColor += hit.obj->amb;
            }

            // phong diffuse
            if (hit.obj->difTexture)
            {
                phongColor += diff * hit.obj->dif * hit.obj->difTexture->SampleLinear(hit.uv);
            }
            else
            {
                phongColor += diff * hit.obj->dif;
            }

            // phong specular
            phongColor += hit.obj->spec * specular;

            // 반사되는 양, 투명도 만큼 뺀 가중치를 곱함
            color += phongColor * (1.0f - hit.obj->reflection - hit.obj->transparency);

            if (hit.obj->reflection)
            {
                // 여기에 반사 구현
                // 수치 오류 주의
                // 반사광이 반환해준 색을 더할 때의 비율은 hit.obj->reflection

                const vec3 reflectedDirection = glm::normalize(-ray.dir + (-glm::dot(hit.normal, ray.dir)*hit.normal + ray.dir) * 2.0f);
                // const auto reflectedDirection = glm::normalize(hit.normal * 2.0f * dot(-ray.dir, hit.normal) + ray.dir);
                Ray reflectRay{ hit.point + reflectedDirection * 1e-4f, reflectedDirection };
                color += traceRay(reflectRay, recurseLevel - 1) * hit.obj->reflection;
            }

            if (hit.obj->transparency)
            {
                // 투명한 물체의 굴절 처리
            }
        }

        return color;
    }

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.