bool updateBrushAndCursorByIntersection (const ViewPointingEvent& e, bool useRecentOctree) { WingedFaceIntersection intersection; if (this->self->intersectsScene (e, intersection)) { this->cursor.enable (); this->cursor.position (intersection.position ()); if (e.primaryButton ()) { this->brush.mesh (&intersection.mesh ()); if (useRecentOctree) { Intersection octreeIntersection; if (this->self->intersectsRecentOctree (e, octreeIntersection)) { return this->brush.updatePointOfAction ( octreeIntersection.position () , octreeIntersection.normal () ); } else { return this->brush.updatePointOfAction ( intersection.position () , intersection.normal () ); } } else { return this->brush.updatePointOfAction ( intersection.position () , intersection.normal () ); } } else { return false; } } else { this->cursor.disable (); return false; } }
//getRadiance RGBColor RayCastingIntegrator::getRadiance(const Ray& ray) const { Intersection temp = world->scene->intersect(ray); if (!temp.b_intersection_) { return RGBColor(0.0f, 0.0f, 0.0f); } float cosine_theta = std::abs(dot(ray.d_, temp.normal())); return RGBColor(cosine_theta, cosine_theta, cosine_theta); }
Color Scene::shade(Intersection isect, Ray r, int level) { if (!isect.hits()) { return bgColor; } real eps; if (r.in()) { eps = 0.00001; } else { eps = -0.00001; } Texture *txt = isect.object()->getTexture(); Point isectPt = r.pointOn(isect.t()); Color curColor(0.0,0.0,0.0); Color specular(0,0,0); Color diffuse(0,0,0); Color shadowAmt(1,1,1); for (LightList::iterator lt_iter = lights.begin(); lt_iter != lights.end(); ++lt_iter) { Vector specL((*lt_iter)->location()-isectPt); Vector specV(cam.getLocation()-isectPt); Vector specHj((specL+specV)*(1.0/((specL+specV).length()))); Ray shade_ray = (*lt_iter)->getRayTo(r.pointOn(isect.t()+ eps)); ++shadow_rays_cast; Intersection tempI = rtrace(shade_ray, true, isect.object()); if (tempI.hits()) { if (level>0) { shadowAmt -= shade(tempI, shade_ray, level-1); } else { shadowAmt = Color(0.0,0.0,0.0); } } specular += (*lt_iter)->intensity()*std::pow(specHj.dot(isect.normal()), txt->n()); diffuse += (*lt_iter)->intensity()*shade_ray.getDir().dot(isect.normal()); } shadowAmt *= 1.0/real(lights.size()); Color reflective(0.0,0.0,0.0,0.0); if ((level>0) && (txt->kr().intensity()>0.01)) { ++reflective_rays_cast; Ray tempRay(r.pointOn(isect.t()+eps), r.getDir() - 2.0 * (r.getDir().dot(isect.normal())) * isect.normal()); reflective = shade(rtrace(tempRay), tempRay, level-1); } Color refractive(0.0,0.0,0.0); if ((level>0) && (txt->kt().intensity()>0.01)) { real eta; if (r.in()) { eta = 1.0/txt->ior(); } else { eta = txt->ior(); } real ci; if (r.in()) { ci = (r.getDir().dot(-1.0*isect.normal())); } else { ci = (r.getDir().dot(isect.normal())); } real costt = 1.0 - (eta*eta) * (1.0-ci*ci); if (costt<0.0) { refractive = Color(0,0,0); } else { ++refractive_rays_cast; Ray tempRay(r.pointOn(isect.t()+eps), ((eta*ci-std::sqrt(costt))*((r.in()?-1.0:1.0)*isect.normal()) - (eta*r.getDir())), !r.in()); refractive = shade(rtrace(tempRay, isect.object()), tempRay, level-1); } } curColor += txt->ka() + (txt->kd()*diffuse + txt->ks()*specular + txt->kr()*reflective + txt->kt()*refractive) * shadowAmt; return curColor.clamp(); }
RGBColor RecursiveRayTracingIntegrator::getRadianceRec(const Ray& ray, int counter) const { if(counter > 6) { return RGBColor::rep(0); } Intersection intersect = world->scene->intersect(ray); if(intersect) { RGBColor color = RGBColor::rep(0.1f) + intersect.solid->material->getEmission( intersect.solid->texMapper->getCoords(intersect), intersect.normal(), -ray.d); Point p = intersect.hitPoint(); if(intersect.solid->material->useSampling() == Material::Sampling::SAMPLING_NOT_NEEDED) { for(int i = 0; i < world->light.size();i++) { LightHit lh = world->light[i]->getLightHit(p); float n1 = dot(ray.o-p, intersect.normal()); float n2 = dot(lh.direction, intersect.normal()); if((n1 > 0 && n2 > 0) || (n1 < 0 && n2 < 0)) { Ray shadowRay = Ray(p, lh.direction); Intersection shadowIntrsct = world->scene->intersect(shadowRay, lh.distance); if(!shadowIntrsct) { RGBColor sourceColor = world->light[i]->getIntensity(lh); RGBColor reflectInt = intersect.solid->material->getReflectance(intersect.solid->texMapper->getCoords(intersect), intersect.normal(), -ray.d, lh.direction); RGBColor reflectColor = sourceColor * reflectInt; color = color + reflectColor; //color = color + reflectInt; } } } } else if(intersect.solid->material->useSampling() == Material::Sampling::SAMPLING_ALL) { Material::SampleReflectance sample = intersect.solid->material->getSampleReflectance(intersect.solid->texMapper->getCoords(intersect), intersect.normal(), -ray.d); RGBColor refColor = getRadianceRec(Ray(p, sample.direction), counter + 1); color = color + (refColor * sample.reflectance); } else if(intersect.solid->material->useSampling() == Material::Sampling::SAMPLING_SECONDARY) { for(int i = 0; i < world->light.size();i++) { LightHit lh = world->light[i]->getLightHit(p); float n1 = dot(ray.o-p, intersect.normal()); float n2 = dot(lh.direction, intersect.normal()); if((n1 > 0 && n2 > 0) || (n1 < 0 && n2 < 0)) { Ray shadowRay = Ray(p, lh.direction); Intersection shadowIntrsct = world->scene->intersect(shadowRay, lh.distance); if(!shadowIntrsct) { RGBColor sourceColor = world->light[i]->getIntensity(lh); RGBColor reflectInt = intersect.solid->material->getReflectance(intersect.solid->texMapper->getCoords(intersect), intersect.normal(), -ray.d, -lh.direction); RGBColor reflectColor = sourceColor * reflectInt; color = color + reflectColor; } } } Material::SampleReflectance sample = intersect.solid->material->getSampleReflectance(intersect.solid->texMapper->getCoords(intersect), intersect.normal(), -ray.d); RGBColor refColor = getRadianceRec(Ray(intersect.hitPoint(), sample.direction), counter + 1); color = color + (refColor * sample.reflectance); } return color; } return RGBColor::rep(0); }
Color Raytracer::trace(Scene *scene, Ray ray, int depth) { if (depth >= m_max_depth) { return scene->background(); } Intersection *intersection = get_closest_intersection(scene, ray); // If this ray hits nothing, return the background color if (intersection == nullptr) { return scene->background(); } // local illumination Color rv = m_phong_shader.shade(scene, intersection); float kr = intersection->intersected_shape()->reflective_constant(); float kt = intersection->intersected_shape()->transmissive_constant(); // spawn reflection ray if (kr > 0) { Ray reflection = make_reflection_ray(intersection->normal(), ray, intersection->intersection_point()); rv += trace(scene, reflection, depth + 1) * kr; } // spawn transmission ray if (kt > 0) { float alpha; bool insideShape = (dot_product(negate_vector(ray.direction()), intersection->normal()) < 0); if (insideShape) { intersection->set_normal(negate_vector(intersection->normal())); alpha = intersection->intersected_shape()->refraction_index(); } else { alpha = 1.0 / intersection->intersected_shape()->refraction_index(); } float cosine = dot_product(negate_vector(ray.direction()), intersection->normal()); float discriminant = 1.0 + ( (alpha * alpha) * ((cosine * cosine) - 1.0) ); bool total_internal_reflection = (discriminant < 0); if (total_internal_reflection) { // use the reflection ray with the kt value Ray reflection = make_reflection_ray(intersection->normal(), ray, intersection->intersection_point()); rv += trace(scene, reflection, depth + 1) * kt; } else { // spawn a transmission ray Ray transmission(intersection->intersection_point(), normalize( vector_add(scalar_multiply(ray.direction(), alpha), scalar_multiply(intersection->normal(), (alpha * cosine) - sqrt(discriminant))))); rv += trace(scene, transmission, depth + 1) * kt; } } delete intersection; return rv; }
RGBColor RayMarchingIntegrator::getRadiance(const Ray& ray) const { Intersection intersection = world->scene->intersect(ray); if (intersection) { RGBColor color = RGBColor(0, 0, 0); Point local; if (intersection.solid->texMapper == nullptr) { local = WorldMapper(Float4::rep(1)).getCoords(intersection); } else { local = intersection.solid->texMapper->getCoords(intersection); } RGBColor emission; if (intersection.solid->material == nullptr) { float greyScale = fabs(dot(intersection.ray.d, intersection.normalVector)); emission = RGBColor(greyScale, greyScale, greyScale); } else { emission = intersection.solid->material->getEmission(local, intersection.normalVector, -ray.d); } Material::SampleReflectance sample; Ray sampleRay; switch (intersection.solid->material->useSampling()) { case Material::SAMPLING_NOT_NEEDED: for (int i = 0; i < world->light.size(); i++) { LightHit shadowRay = world->light[i]->getLightHit(intersection.hitPoint()); if (dot(intersection.normalVector, shadowRay.direction) > 0) { Ray shadow = Ray(intersection.hitPoint() + EPSILON * shadowRay.direction, shadowRay.direction); //TODO more epsilon? Intersection shadowRayIntersection = world->scene->intersect(shadow, shadowRay.distance); if (!shadowRayIntersection) { RGBColor reflectance; if (intersection.solid->material == nullptr) { reflectance = RGBColor(0.5, 0.5, 0.5); } else { if(intersection.solid->isFracLand){ reflectance = intersection.solid->material->getReflectance( intersection.hitPoint(), intersection.normalVector, -ray.d, shadowRay.direction); } else{ reflectance = intersection.solid->material->getReflectance(local, intersection.normalVector, -ray.d, shadowRay.direction); } // reflectance = intersection.solid->material->getReflectance(local, // intersection.normalVector, -ray.d, shadowRay.direction); } RGBColor intensity = world->light[i]->getIntensity(shadowRay); RGBColor lightSourceColor = (reflectance * intensity); color = color + lightSourceColor; } } } break; case Material::SAMPLING_ALL: sample = intersection.solid->material->getSampleReflectance(intersection.hitPoint(), intersection.normalVector, -intersection.ray.d); // sample = intersection.solid->material->getSampleReflectance(local, intersection.normalVector, // -intersection.ray.d); sampleRay = Ray(intersection.hitPoint() + EPSILON * sample.direction, sample.direction); if (MarchRecursionDepth > MAX_RECURSION_DEPTH) { MarchRecursionDepth = 0.f; } else { MarchRecursionDepth++; color = color + getRadiance(sampleRay) * sample.reflectance; } break; case Material::SAMPLING_SECONDARY: for (int i = 0; i < world->light.size(); i++) { LightHit shadowRay = world->light[i]->getLightHit(intersection.hitPoint()); if (dot(intersection.normalVector, shadowRay.direction) > 0) { Ray shadow = Ray(intersection.hitPoint() + EPSILON * intersection.normal(), shadowRay.direction); Intersection shadowRayIntersection = world->scene->intersect(shadow, shadowRay.distance); if (!shadowRayIntersection) { RGBColor reflectance = intersection.solid->material->getReflectance(local, intersection.normalVector, -ray.d, shadowRay.direction); RGBColor emission = intersection.solid->material->getEmission(local, intersection.normalVector, -ray.d); RGBColor intensity = world->light[i]->getIntensity(shadowRay); RGBColor lightSourceColor = (reflectance * intensity); color = color + lightSourceColor; } } } sample = intersection.solid->material->getSampleReflectance(local, intersection.normalVector, -intersection.ray.d); if (sample.direction != Vector(0, 0, 1) && sample.reflectance != RGBColor(0.f, 0.f, 0.f)) { sampleRay = Ray(intersection.hitPoint() + EPSILON * sample.direction, sample.direction); if (MarchRecursionDepth > MAX_RECURSION_DEPTH) { MarchRecursionDepth = 0; } else { MarchRecursionDepth++; color = color + getRadiance(sampleRay) * sample.reflectance; } } break; default: break; } MarchRecursionDepth = 0; if (world->fogs.size() == 0) { return color + emission; } /* RGBColor fog = world->fog->modulateColor(ray.o, intersection.hitPoint()); float transmittance = world->fog->transmittance(ray.o, intersection.hitPoint()); return (color + emission) * transmittance + (1 - transmittance) * fog;*/ RGBColor fogColor = RGBColor::rep(0); for (int i = 0; i < world->fogs.size(); i++) { Intersection i1 = world->fogs[i]->getPrimitive()->intersect(ray, intersection.distance); if (i1) { float transmittance = 1; float enterDistance = 0; //i1.distance; //float exitDistance = i1.exitDistance == i1.distance ? intersection.distance : i1.exitDistance; float exitDistance = intersection.distance; //std::min(i1.exitDistance, intersection.distance); while (enterDistance < exitDistance) { float stepSize = std::min(STEP_SIZE, exitDistance - enterDistance); Point deltaPoint = ray.o + (enterDistance + stepSize / 2) * ray.d; float deltaTransmittance = exp( -world->fogs[i]->getDensity(deltaPoint) * stepSize); RGBColor deltaColor = RGBColor(0, 0, 0); for (int i = 0; i < world->light.size(); i++) { LightHit shadowRay = world->light[i]->getLightHit( deltaPoint); Ray shadow = Ray( deltaPoint + EPSILON * shadowRay.direction, shadowRay.direction); Intersection shadowRayIntersection = world->scene->intersect(shadow, shadowRay.distance); if (!shadowRayIntersection) { RGBColor intensity = world->light[i]->getIntensity( shadowRay); RGBColor lightSourceColor = (intensity); deltaColor = (deltaColor + lightSourceColor); } } fogColor = fogColor + transmittance * (1 - deltaTransmittance) * deltaColor * world->fogs[i]->getColor(deltaPoint); transmittance *= deltaTransmittance; enterDistance += STEP_SIZE; } //LOG_DEBUG("fogcolor " << fogColor.r << ", " << fogColor.g << ", " << fogColor.b); } } return (color + emission) + fogColor; } else { //if (!world->fog) return RGBColor(0, 0, 0); /*Intersection i1 = world->fog->getPrimitive()->intersect(ray); if (i1) { RGBColor fogColor = RGBColor::rep(0); float transmittance = 1; float enterDistance = i1.distance; //float exitDistance = i1.exitDistance == i1.distance ? intersection.distance : i1.exitDistance; float exitDistance = std::min(i1.exitDistance, intersection.distance); while (enterDistance < exitDistance) { float stepSize = std::min(STEP_SIZE, exitDistance - enterDistance); Point deltaPoint = ray.o + (enterDistance + stepSize / 2) * ray.d; float deltaTransmittance = exp(-world->fog->getDensity(deltaPoint) * stepSize); RGBColor deltaColor = RGBColor(0, 0, 0); for (int i = 0; i < world->light.size(); i++) { LightHit shadowRay = world->light[i]->getLightHit(deltaPoint); if (dot(intersection.normalVector, shadowRay.direction) > 0) { Ray shadow = Ray(deltaPoint + EPSILON * shadowRay.direction, shadowRay.direction); Intersection shadowRayIntersection = world->scene->intersect(shadow, shadowRay.distance); if (!shadowRayIntersection) { RGBColor reflectance = world->fog->getColor(deltaPoint); RGBColor intensity = world->light[i]->getIntensity(shadowRay); RGBColor lightSourceColor = (reflectance * intensity); deltaColor = (deltaColor + lightSourceColor); } } } fogColor = fogColor + transmittance * (1 - deltaTransmittance) * deltaColor; transmittance *= deltaTransmittance; enterDistance += STEP_SIZE; } return fogColor; } RGBColor fog = world->fog->getColor(intersection.hitPoint());*/ //return fog; } }
/** Calcul de l'éclairement local d'un point d'intersection => Phong avec ombres portées. - toutes les données nécessaires au point d'intersection sont dans le paramêtre intersection (point, normale, noeud CSG intersecté) - les données de la scène (sources lumineuses) sont accessibles par scene()->... */ Vector3 Raytrace::computeLocalColor(const Intersection &intersection) { /** * P est le point d'intersection (Vector3) * L est le vecteur d'éclairement (Vector3) * N est la normale au point d'intersection (Vector3) * V est le vecteur d'observation * m contient le materiel au point : m.diffuse() donne le matériel diffus (de type Vector3 : on peut utiliser les opérateurs *, +, etc), de même m.specular(), m.shininess() * intersection.incident() donne le rayon qui a provoqué l'intersection * Pour les sources : * - _scene->nbLight() donne le nombre de source lumineuses * - _scene->lightPosition(i) donne la position de la source i (uniquement des sources ponctuelles). * Remarque : il faut faire la somme des couleurs obtenues pour chacune des sources (risque de saturation si plusieurs sources lumineuses). */ Vector3 P; Vector3 L; Vector3 N; Vector3 V; Vector3 R; N=intersection.normal(); P=intersection.point(); N.normalize(); V = - intersection.incident().direction(); V.normalize(); double diffuseIntensity = 0; double specularIntensity = 0; Material m=intersection.node()->primitive()->material(); Vector3 result = m.ambient().xyz(); for (int i = 0 ; i < _scene->nbLight() ; i++){ if (V.dot(N) < 0) N = -N; L = _scene->lightPosition(i) - P; L.normalize(); R = 2* (N.dot(L))*N - L; R.normalize(); Ray shadow(P,_scene->lightPosition(i)-P); Intersection *nearestIntersection=_scene->intersection(shadow,0.1); if (nearestIntersection != NULL){ if(nearestIntersection->lambda()>1) { diffuseIntensity = max(N.dot(L),0.0); specularIntensity = pow(max(V.dot(R),0.0),m.shininess()); result += diffuseIntensity*m.diffuse()+specularIntensity*m.specular(); } } else { diffuseIntensity = max(N.dot(L),0.0); specularIntensity = pow(max(V.dot(R),0.0),m.shininess()); result += diffuseIntensity*m.diffuse()+specularIntensity*m.specular(); } delete nearestIntersection; } return result; }