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; }
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; }
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() ); }