Esempio n. 1
0
    float PointInShadow(const glm::vec3& point, RayTracerState& state) {
        Ray shadow_ray(point, position-point);

        const float z_offset = 10e-4f;
        float t = -1;
        float t_min = std::numeric_limits<float>::max();
        int k_min=-1;
        //Loop through all the objects, to find the closest intersection, if any
        for (unsigned int k=0; k<state.getScene().size(); ++k) {
            t = state.getScene().at(k)->intersect(shadow_ray);

            //skipping the cubemap
            if(t >= (std::numeric_limits<float>::max()))
                continue;

            if (t > z_offset && t <= t_min) {
                k_min = k;
                t_min = t;
            }
        }

        if (k_min >= 0) {
            glm::vec3 q = point + shadow_ray.getDirection()*t_min;
            float light_length = glm::length(position-point);
            float q_lenght = glm::length(q);

            if(q_lenght < light_length)
                return 0.0f;
        }
        return 1.0f;
    }
void LambertianMaterial::shade(Color& result,
							   const RenderContext& context,
							   const Ray& ray,
							   const HitRecord& record,
							   float attenuation,
							   int depth) const
{
	HitRecord temp_record;
	Point position = record.p;

	Normal N;
	record.obj->getNormal(N, record, position);
	float costheta = dot(N, ray.direction());

	if(costheta > 0)
	{
		N = -N;
	}
	
	result = context.scene->ambient*Ka;

	for(int i = 0; i < context.scene->lights.size(); i++)
	{
		Vector light_direction;
		Color light_color;
		context.scene->lights[i]->getLight(light_color, light_direction, context, position);
		float cosphi = dot(N, light_direction);
		Ray shadow_ray(position, light_direction);
		
		if(cosphi > 0)
		{
			temp_record.reset();
			if(!context.scene->object->hit(temp_record, context, shadow_ray))
			{
				result += light_color*(Kd * cosphi);
			}
			else
			{
				if(temp_record.obj->mat->getName() == "dielectricmaterial")
				{
					Color tempColor;
					temp_record.obj->mat->shade(tempColor, context, shadow_ray, temp_record, attenuation, depth + 1);
					result += tempColor*(Kd * cosphi);
				}
			}
		}
	}
	
	result *= color;
}
Esempio n. 3
0
vector3f get_light_distribution(primitive *pri, ray &r, kdtree &kdtree) 
{
	// distribution
	vector3f distribution(0.0, 0.0, 0.0);
	double delta = 1.0 / (shadow_sampling * shadow_sampling);

	for (int i = 0; i < shadow_sampling; i++) {
		for (int j = 0; j < shadow_sampling; j++) {
			vector3f light_pos = get_light_coordinate(i, j);
			vector3f shadow_dir = light_pos - r.origin;
			ray shadow_ray(r.origin, shadow_dir);
			primitive *shadow_pri = get_intersecting_primitive(kdtree, shadow_ray);

			if (shadow_pri == NULL || (shadow_ray.origin - r.origin).norm() > shadow_dir.norm()) {
				// clear
				double dist = shadow_dir.norm() / distance_factor;
				double phong = pri->get_normal(r.origin) * shadow_ray.direction;
				distribution += delta * max(0.0, phong) / (dist * dist);
			}
			else {
				double occupacy = shadow_pri->get_material().dif[3];

				if (occupacy < 1 - eps2) 
				{
					// approximated fraction light
					double cos_value = shadow_pri->get_normal(shadow_ray.origin) * shadow_ray.direction;
					double fraction_value = (1 - cos_value) * (1 - cos_value) / 4.0;
					double phong = pri->get_normal(r.origin) * shadow_ray.direction;
					double dist = shadow_dir.norm() / distance_factor;
					distribution += delta * max(0.0, phong) * fraction_value * (1 - occupacy) / (dist * dist);
				
				}

				else 
				{
					// nothing
				}
			}
		}
	}

	return distribution;
}
Esempio n. 4
0
// Moeller-Trumbore
bool Triangle::hit(const Ray& ray, const Ray_Tracer* rt,
                    float t_min, float t_max, Ray_Hit& rh, bool shadow) const {

    // Absolute Triangle Vertex Positions
    V3& v0 = m->verts[inds[0]];
    V3& v1 = m->verts[inds[1]];
    V3& v2 = m->verts[inds[2]];

    // Two edges of triangle
    V3 e0, e1;
    e0 = v1 - v0;
    e1 = v2 - v0; 

    V3 p = ray.s.cross(e1);
    float deter = e0.dot(p);

    if (deter  > -EPSILON && deter < EPSILON)
        return false; 

    V3 t = ray.o - v0;
    
    // Store the inverse to reduce divisions
    float inv_deter = 1.0 / deter;
    float u = t.dot(p) * inv_deter;

    if (u < 0.0 || u > 1.0)
        return false;

    V3 q = t.cross(e0);
    float v = ray.s.dot(q) * inv_deter;

    if (v < 0.0 || u + v > 1.0)
        return false;

    float t_inter = e1.dot(q) * inv_deter;

    if (t_inter < t_min || t_inter > t_max) {
        //std::cout << "Cull: " << t_inter << '\t' <<t_min<< '\t' <<t_max<<  std::endl;
        return false;
    }

    rh.t = t_inter;
    rh.col = 0.2*m->mat.col;
    rh.shape = m;

    if (shadow || ray.depth >= rt->depth_limit)
        return true;

/*
    if (is_light) {     
        rh.col = Color(1.0, 1.0, 1.0);
        return true;
    }
*/

    V3 int_loc = ray.at(t_inter);
    // Shadow
    for (Shape* light : rt->lights) {

        // BIG ASSUMPTION THAT ALL LIGHTS ARE SPHERES
        Sphere* sph = static_cast<Sphere*>(light);

        // Make ray from intersection to light
        V3 int_to_light = sph->c - int_loc; 
        float dist_to_light = int_to_light.norm();
        int_to_light.normalize();
        Ray shadow_ray(int_loc + EPSILON*int_to_light, int_to_light, ray.depth + 1);
        Ray_Hit shadow_hit;
        if (rt->kd->hit_helper(true, rt->kd->root, shadow_ray, rt,
                EPSILON, dist_to_light, shadow_hit, true, 0)) {
            if (!shadow_hit.shape->is_light) {
                continue;
            }
        }

        float inner = int_to_light.dot(normal);
        if (inner > 0.0) {
            rh.col += sph->mat.col *inner* m->mat.diff * m->mat.col;
        }
    }

    // Reflection 
    V3 refl_dir = ray.s - 2.0f * (normal.dot(ray.s)) * normal;
    Ray refl_ray(int_loc + EPSILON*refl_dir, refl_dir, ray.depth + 1);
    Ray_Hit refl_hit;
    if (rt->kd->hit_helper(true, rt->kd->root, refl_ray, rt,
            EPSILON, FLT_MAX, refl_hit, false, 0)) {
    //if (rt->trace(refl_ray, EPSILON, FLT_MAX, refl_hit, false)) {
        rh.col += m->mat.refl*refl_hit.col * refl_hit.shape->mat.col;
    }

    return true;  
}
Esempio n. 5
0
//Blinn-Phong shading model
Vector3
Specular::shade(Ray& ray, const HitInfo& hit, const Scene& scene) const
{
    Vector3 reflected = Vector3(0.0f, 0.0f, 0.0f);
    Vector3 L = Vector3(0.0f, 0.0f, 0.0f);
    
    //scale down intensity of light in proportion to num of ray bounces
    Vector3 attenuation = k_s * ( 1 / (ray.numBounces+1));
    
    const Lights *lightlist = scene.lights();
    
    // loop over all of the lights
    Lights::const_iterator lightIter;
    for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++)
    {
        //find reflected vector, given normal and incident light direction
        PointLight* pLight = *lightIter;
        
        //light vector points from hit point to light
        Vector3 l = pLight->position() - hit.P;
        
        //why did we use ray.d here instead of l? Would just need to change calculation a bit
        //to use l
        reflected = ray.d - 2.0f * (dot(hit.N, ray.d)) * hit.N;

        if (ray.numBounces < maxBounces)
        {
            //trace from reflected vector now
            Ray reflect(ray.numBounces + 1);
            reflect.o = hit.P;
            reflect.d = reflected;
            HitInfo hitReflect;
        
            if (scene.trace(hitReflect, reflect, 0.008f))
            {
                //get color from object hit
                //printf("Bounced reflected ray hit something!\n");
                L += attenuation * hitReflect.material->shade(reflect, hitReflect, scene);
            }
            else
            {
                //get color from background
                L += Vector3(0,0,0.5f);//bgColor;
            }
        }

        //Get halfway vector
        Vector3 h = (L + -1 * ray.d).normalize();
        
        Ray shadow_ray(0);
        HitInfo hi;
        
        shadow_ray.o = hit.P;
        shadow_ray.d = l;
        
        //std::cout<<"M = "<<M<< " hit.N = "<<hit.N<<std::endl;

        if (scene.trace(hi, shadow_ray, 0.001f, sqrt(l.length2())))
        {
            // We are in shadow
        }
        else
        {
            //get color of light
            Vector3 color = pLight->color();
            
            //flip vector from eye so points from hit point back to eye
            //L += k_s * color * pow(std::max(0.0f, dot(h, hit.N)), shinyExp);
            //L += attenuation * color * pow(std::max(0.0f, dot(reflected, -ray.d)), shinyExp);
            
            //Specular Highlights
            //This is separate from the reflection calculation because it
            //needs to be dependent on just the shinyExp
            //https://en.wikipedia.org/wiki/Specular_highlight
            
            //Specular calculation for ABSORBED light
            L += attenuation * pow(std::max(0.0f, dot(h, hit.N)), 50* shinyExp);

	    //check entering or exiting and change n1/n2 n2/n1
           //dot product ray.dot.normal  
            //Specular Refraction
            //L += attenuation * color * pow(std::max(0.0f, dot(wt, -ray.d)), shinyExp);
            //std::cout<<"Final Refraction vector = "<<(k_s * color * pow(std::max(0.0f,
            //dot(wt,ray.d)), shinyExp))<<std::endl;
        }
    }
    
    return L;
}
Esempio n. 6
0
void BasicDiffuseSpecularShader::shade( Scene & scene, RandomNumberGenerator & rng, RayIntersection & intersection )
{
    RGBColor diffuse_contrib( 0.0, 0.0, 0.0 );
    RGBColor specular_contrib( 0.0, 0.0, 0.0 );
    RGBColor direct_contrib( 0.0, 0.0, 0.0 );
    Ray new_ray;
    RayIntersection new_intersection;
    new_intersection.min_distance = 0.01;
    Vector4 offset( 0.0, 0.0, 0.0 );
    //offset = scale( intersection.normal, 0.01 ); // NOTE - Seems to help 
    new_ray.origin = add( intersection.position, offset );
    new_ray.depth = intersection.ray.depth + 1;
    const unsigned char max_depth = 5;
    //const unsigned char max_depth = 4;
    //const unsigned char max_depth = 3;
    //const unsigned char max_depth = 2;

    Vector4 from_dir = intersection.fromDirection();

    // Asserts
    intersection.normal.assertIsUnity();
    intersection.normal.assertIsDirection();

    // Direct lighting
    //
    // Area lights
    //for( Traceable * traceable : scene.lights ) {
    //    // TODO - sample lights
    //}
    // Point lights
    for( const PointLight & light : scene.point_lights ) {
        Vector4 to_light = subtract( light.position, intersection.position );
        float dist_sq_to_light = to_light.magnitude_sq();
        Vector4 direction = to_light.normalized();
        direction.makeDirection();

        // Shoot a ray toward the light to see if we are in shadow
        Ray shadow_ray( intersection.position, direction );
        RayIntersection shadow_isect;
        shadow_isect.min_distance = 0.01;
        if( scene.intersect( shadow_ray, shadow_isect )
            && sq(shadow_isect.distance) < dist_sq_to_light ) {
            continue;
        }

        // Not in shadow
        float cos_r_n = fabs( dot( direction, intersection.normal ) ); 
        RGBColor color = light.band_power;
        color.scale(cos_r_n);
        color.scale(1.0f / to_light.magnitude_sq()); // distance falloff
        // TODO: use actual material parameters properly so we can get specular here, too
        if( intersection.material )
            direct_contrib.accum( mult( color, intersection.material->diffuse ) );
        else
            direct_contrib.accum( color );
    }

    // TODO - How best should we choose between diffuse and specular?
    // FIXME: Should I scale by the cosine for a perfect reflector?

    if( intersection.ray.depth < max_depth ) {
        const float diffuse_chance = 0.9;
        float diff_spec_select = rng.uniform01();

        if( intersection.material->perfect_reflector
            || intersection.material->perfect_refractor ) {
            auto sample = intersection.material->sampleBxDF( rng, intersection );
            new_ray.direction = sample.direction;
            new_ray.index_of_refraction = sample.new_index_of_refraction;

            if( scene.intersect( new_ray, new_intersection ) ) {
                if( new_intersection.distance != FLT_MAX ) {
                    shade( scene, rng, new_intersection );
                }
                specular_contrib.accum( new_intersection.sample.color );
            }
        }
        else if( diff_spec_select < diffuse_chance ) {
            // Diffuse
            rng.uniformSurfaceUnitHalfSphere( intersection.normal, new_ray.direction );
            new_ray.direction.makeDirection();

            if( scene.intersect( new_ray, new_intersection ) ) {
                if( new_intersection.distance != FLT_MAX )
                    shade( scene, rng, new_intersection );
                float cos_r_n = dot( new_ray.direction, intersection.normal ); 
                new_intersection.sample.color.scale( cos_r_n );
                diffuse_contrib.accum( new_intersection.sample.color );
            }
        }
        else {
            // Specular
            // TODO - sample the specular lobe, not just the mirror direction
            new_ray.direction = mirror( from_dir, intersection.normal );
            new_ray.direction.makeDirection();

            if( scene.intersect( new_ray, new_intersection ) ) {
                if( new_intersection.distance != FLT_MAX )
                    shade( scene, rng, new_intersection );
                float cos_r_n = dot( new_ray.direction, intersection.normal ); 
                new_intersection.sample.color.scale( cos_r_n );
                specular_contrib.accum( new_intersection.sample.color );
            }
        }
    }

    if( intersection.material ) {
        intersection.sample.color = mult( diffuse_contrib, intersection.material->diffuse );
        intersection.sample.color.accum( mult( specular_contrib, intersection.material->specular ) );
        intersection.sample.color.accum( intersection.material->emittance );
        intersection.sample.color.accum( direct_contrib );
    }
    else {
        intersection.sample.color = diffuse_contrib;
        intersection.sample.color.accum( direct_contrib );
    }
}