コード例 #1
0
real BlinnPhongShader<real>::GetAmbientOcclusion(const int samples, real radius){

    ////////////////////////////////////////////
    //////////////////IFT 3355//////////////////
    ////////////////////////////////////////////
    // "samples" est le nombre d'échantillons
    // que l'on souhaite générer. Ici, vous
    //devrez générer "samples" échantillons
    //dans une sphère unitaire et ensuite
    //vérifier si le vecteur induit intersecte
    //une géométrie dans le rayon "radius".
    //Vous calculerez ensuite le facteur
    //d'occlusion ambiente.
    //N.B.
    //Vous pouvez vous servir de la classe
    //CoreLib/SphereSampling pour échantillonner
    //uniformément la sphère.
    ////////////////////////////////////////////
    //////////////////IFT 3355//////////////////
    ////////////////////////////////////////////

    if (radius == 0)
        return 1;

    real ao = 0;
    CoreLib::Node<real>* node = NULL;
    Intersection<real> inter;
    Vector3<real> x = mIntersection.GetPosition() + EPS*mIntersection.GetNormal();

    srand((int)time(NULL));
    for (int i = 0; i < samples; ++i) {
        real theta = acos(1 - 2 * drand48());
        real phi = 2 * PI * drand48();
        real sin_theta = sin(theta);
        Vector3<real> omega(
            cos(phi)*sin_theta,
            sin(phi)*sin_theta,
            cos(theta)
        );
        Ray<real> r(x, omega);
        bool hit = !mRayTracer.GetNearestIntersection(r, node, inter)
            || (inter.GetPosition() - x).Length() > radius;
        ao += std::max<real>(mIntersection.GetNormal() * omega, 0) * hit;
    }

    // srand((int)time(NULL));
    // std::vector<Vector3<real > > coords(samples);
    // SphereSampling<real> ss;
    // ss.HaltonSample(coords, samples, 7);
    // for (int k = 0; k < samples; ++k) {
    //   Vector3<real> sample = coords[k];
    //   sample.Normalize();
    //   Ray<real> r (x, sample);
    //   bool hit = !mRayTracer.GetNearestIntersection(r, node, inter)
    // 	|| (inter.GetPosition() - x).Length() > radius;
    //   ao += std::max<real>(mIntersection.GetNormal() * sample, 0) * hit;
    // }

    return ao * 4.0 / samples;
}
コード例 #2
0
bool SphereIntersector<real>::Intersect( const Sphere<real>* sphere, const Ray<real>& ray, Intersection<real>& oIntersection )
{
	// Compute the equation corresponding to x²+y²+z²=0 with p+t*d to obtain a quadratic equation
	real a = ray.GetDirection().SquaredLength();
	real b = 2.0 * ray.GetDirection() * ray.GetOrigin();
	real c = ray.GetOrigin().SquaredLength() - sphere->GetRadius() * sphere->GetRadius();

	real discriminant = b*b - 4*a*c;

	// Discriminant >= 0 => the must be at least one intersection
	if ( discriminant >= 0 )
	{
		// Compute the two potential intersections and only keep the nearest
		real sqrtDisc = sqrt( discriminant );
		real t = 0;
		real t1 = ( -b - sqrtDisc ) / ( 2.0 * a );
		real t2 = ( -b + sqrtDisc ) / ( 2.0 * a );

		if ( t1 >= 0 )
		{
			t = t1;
			oIntersection.IsInside( false );
		}
		else if ( t2 >= 0 )
		{
			t = t2;
			oIntersection.IsInside( true );
		}
		else
			return false;

		oIntersection.SetPosition( ray.GetOrigin() + t * ray.GetDirection() );
		oIntersection.SetNormal( oIntersection.GetPosition().Normalized() );
		oIntersection.SetTextureCoordinates( oIntersection.GetPosition().Normalized() );

		// The normal must be flipped to coincide with the hit direction
		if ( oIntersection.IsInside() )
			oIntersection.SetNormal( -oIntersection.GetNormal() );

		return true;
	}

	return false;
}
コード例 #3
0
void NodeIntersector<real>::TransformIntersectionToGlobalCoordinates( const CoreLib::Node<real>* node, Intersection<real>& ioIntersection )
{
	// newPosition = M * position
	// newNormal = M^{-T} * normal
	const Matrix4<real>& localToGlobal = node->GetLocalToGlobal();
	Matrix4<real> localToGlobalForNormals = node->GetGlobalToLocal();
	localToGlobalForNormals.Transpose();

	ioIntersection.SetPosition( localToGlobal * ioIntersection.GetPosition() );
	ioIntersection.SetNormal( localToGlobalForNormals ^ ioIntersection.GetNormal() );
}