전공 지식 컴퓨터 그래픽스

문제

유리구(glass sphere) 뒤에 놓인 불투명한 세 개의 구를 화면에 그려야 한다.
이 때 유리구의 굴절률은 3/2 또는 1이고 transparency coefficient는 0.95이다.
단, ray tracing의 depth는 4로 제한한다.

문제의 상황을 그림으로 표현하면 다음과 같다. diagram

코드

// Compute the intensity from ray using recursive ray casting.
// Exclude an intersection with the object E where the ray start from.
vec3
intensity(const Ray& ray, const Light l[], int nLights, int depth, int E = -1)
{
    vec3 I(0, 0, 0);              // Final intensity

    // Find the closest intersection point and the normal
    vec3 p, n;                  // Position and normal in the eye coordinate system
    int iObject = findIntersection(ray, p, n, E);

    if (iObject != -1)          // Hit an object
    {
        if (ray.currMedium == Medium::AIR)
			for (int i = 0; i < nLights; i++)
			{
				// Shadow ray
				vec3 p_shadow, n_shadow;        // Not used

				vec3 pDistantLight = p + 1.0e10f * l[i].p_eye;
				Ray shadowRay(p, pDistantLight);

				int jObject = findIntersection(shadowRay, p_shadow, n_shadow, iObject);

				if (jObject == -1)              // Not shadowed
				{
					// Phong reflection
					vec3 v = glm::normalize(ray.p0 - ray.p1);        // Direction to the viewer
					vec3 r = glm::normalize(reflect(l[i].p_eye, n)); // Direction of Reflected light
					I += phong(n, v, l[i], r, iObject);
				}
				else
					I += ambient(l[i], iObject);                        // Shadowed
			}

        // Recursive ray casting
        if (depth < DEPTH)
        {
            // Reflection ray
            if (reflection && ray.currMedium!=Medium::GLASS)       // No reflection inside the glass sphere
            // if (reflection)                                           // Reflection inside the glass sphere
            {
				vec3 direction_reflection = glm::normalize(reflect(ray.p0 - ray.p1, n));
				vec3 pr = p + 1.0E10f * direction_reflection;      // Point far away from p along r
				Ray recursiveRay_reflection(p, pr);
				vec3 I_R_reflection = intensity(recursiveRay_reflection, l, nLights, depth + 1, iObject);

				for (int i = 0; i < 3; i++)
				    I[i] += material[iObject].s[i] * I_R_reflection[i];
            }

            // Refraction ray
            if (iObject == GLASS_SPHERE && translucent)
            {
                if (refraction)
                {
					// next medium
					Medium nextMedium = ray.currMedium;

					if (ray.currMedium == Medium::GLASS)            // GLASS -> AIR
						nextMedium = Medium::AIR;   
					else if (ray.currMedium == Medium::AIR)         // AIR -> GLASS
						nextMedium = Medium::GLASS;

					vec3 direction_refraction = glm::normalize(refractedRay(ray.p0 - ray.p1, n, nextMedium));
					vec3 pr = p + 1.0E10f * direction_refraction;
					Ray recursiveRay_refraction(p + 0.0001f * direction_refraction, pr);
					recursiveRay_refraction.currMedium = nextMedium;

					vec3 I_R_refraction = intensity(recursiveRay_refraction, l, nLights, depth + 1);

					for (int i = 0; i < 3; i++)
						I[i] += k_t * I_R_refraction[i];
                }
                else    // without refraction
                {
                    vec3 I_R_translucent = intensity(ray, l, nLights, depth + 1, iObject);

					for (int i = 0; i < 3; i++)
						I[i] += k_t * I_R_translucent[i];
                }

            }

        }
    }
    else I = I_back;

    return I;
}

결과

굴절률 3/2 3-2

굴절률 1 1

Comments