/// Evaluate the BRDF for the given pair of directions Color3f eval(const BSDFQueryRecord &bRec) const { /* This is a smooth BRDF -- return zero if the measure is wrong, or when queried for illumination on the backside */ if (bRec.measure != ESolidAngle || Frame::cosTheta(bRec.wi) <= 0 || Frame::cosTheta(bRec.wo) <= 0) return Color3f(0.0f); Vector3f wh = (bRec.wi + bRec.wo).normalized(); float cosThetai = Frame::cosTheta(bRec.wi); float cosThetao = Frame::cosTheta(bRec.wo); //compute the Beckman term float D = Microfacet::D(m_alpha, wh) / Frame::cosTheta(wh); //float D = Warp::squareToBeckmannPdf(wh, m_alpha) / Frame::cosTheta(wh); //compute the Fresnel term float F = fresnel(wh.dot(bRec.wi), m_extIOR, m_intIOR); //compute the geometry term float G = Microfacet::G(m_alpha, bRec.wi, bRec.wo, wh); //float G = G1(bRec.wi, wh) * G1(bRec.wo, wh); return (m_kd * INV_PI) + (m_ks * ((D * F * G)/(4.0f * cosThetai * cosThetao))); }
MyRGBColor FresnelReflector::sample_f(const ShadeRec& sr, Vector3D& wr, const Vector3D& wo) const{ float ndotwo = sr.normal * wo; wr = -wo + 2.0 * sr.normal * ndotwo; return (fresnel(sr) * white / fabs(sr.normal * wr)); }
Spectrum fDelta(const BSDFQueryRecord &bRec) const { bool sampleReflection = (bRec.typeMask & EDeltaReflection) && (bRec.component == -1 || bRec.component == 0); bool sampleTransmission = (bRec.typeMask & EDeltaTransmission) && (bRec.component == -1 || bRec.component == 1); bool reflection = bRec.wo.z * bRec.wi.z > 0; Float fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR); if (sampleReflection && !sampleTransmission && !reflection) return Spectrum(0.0f); else if (!sampleReflection && sampleTransmission && reflection) return Spectrum(0.0f); if (reflection) { return m_specularReflectance->getValue(bRec.its) * fr; } else { Float etaI = m_extIOR, etaT = m_intIOR; bool entering = Frame::cosTheta(bRec.wi) > 0.0f; if (!entering) std::swap(etaI, etaT); Float factor = (bRec.quantity == ERadiance) ? (etaI*etaI) / (etaT*etaT) : 1.0f; return m_specularTransmittance->getValue(bRec.its) * factor * (1 - fr); } }
double Clothoid::calcD(double alpha) { double x, z; fresnel(sqrt(2 * alpha / PI), x, z); double d = cos(alpha) * (x)+ (sin(alpha) * z); return d; }
void Clothoid::getXY(double s, double a, double b, double c, double& x, double& y) { double storeX, storeY; if (a > 0) { double limit_ = (b + 2 * a * s) / (sqrt(2 * fabs(a) * PI)); fresnel(limit_, storeX, storeY); x = sqrt(PI / 2 / fabs(a))*((cos(b * b / 4 / a - c))*(storeX)+(sin(b * b / 4 / a - c))*(storeY)); y = sqrt(PI / 2 / fabs(a))*((cos(b * b / 4 / a - c))*(storeY)-(sin(b * b / 4 / a - c))*(storeX)); double x1, y1; limit_ = (b) / (sqrt(2 * fabs(a) * PI)); fresnel(limit_, storeX, storeY); x1 = sqrt(PI / 2 / fabs(a))*((cos(b * b / 4 / a - c))*(storeX)+(sin(b * b / 4 / a - c))*(storeY)); y1 = sqrt(PI / 2 / fabs(a))*((cos(b * b / 4 / a - c))*(storeY)-(sin(b * b / 4 / a - c))*(storeX)); x -= x1; y -= y1; } else { a = -a; double limit_ = (2 * a * s - b) / (sqrt(2 * fabs(a) * PI)); fresnel(limit_, storeX, storeY); x = sqrt(PI / 2 / fabs(a))*((cos(b * b / 4 / a + c))*(storeX)+(sin(b * b / 4 / a + c))*(storeY)); y = sqrt(PI / 2 / fabs(a))*(-(cos(b * b / 4 / a + c))*(storeY)+(sin(b * b / 4 / a + c))*(storeX)); double x1, y1; limit_ = (-b) / (sqrt(2 * a * PI)); fresnel(limit_, storeX, storeY); x1 = sqrt(PI / 2 / fabs(a))*((cos(b * b / 4 / a + c))*(storeX)+(sin(b * b / 4 / a + c))*(storeY)); y1 = sqrt(PI / 2 / fabs(a))*(-(cos(b * b / 4 / a + c))*(storeY)+(sin(b * b / 4 / a + c))*(storeX)); x -= x1; y -= y1; } }
Color trace(Ray& ray, int i){ if(!i) return Color(0,0,0); Obj* o; Vector x; Vector n; if(firstIntersect(ray, x, n, &o)<0) return La; Color c=directLight(ray.dir,x,n,o->mat); if(!o->mat.reflective&&!o->mat.refractive){ double px=(x.x/4+0.5)*phms; double py=(x.y/4+0.5)*phms; double u=px-(int)px; double v=py-(int)py; Color f=ph2((int)px, (int)py)*(1-u)*(1-v)+ ph2((int)px+1, (int)py)*(u)*(1-v)+ ph2((int)px, (int)py+1)*(1-u)*(v)+ ph2((int)px+1, (int)py+1)*(u)*(v); c=c+f*(5000./phLim); } if(o->mat.reflective) { Vector refd=reflectDir(ray.dir,n)+x; Ray ref(x,refd); if(o->mat.refractive){ bool valid=true; Vector refrd=refractDir(ray.dir,n,o->mat.n.r,valid); if(valid){ c=c+fresnel(ray.dir,n,o->mat,false)*trace(ref,i-1); } else { c=c+trace(ref,i-1); } } else { c=c+fresnel(ray.dir,n,o->mat,false)*trace(ref,i-1); } } if(o->mat.refractive){ bool valid=true; Vector refrd=refractDir(ray.dir,n,o->mat.n.r,valid)+x; if(valid){ Ray refr(x,refrd); c=c+fresnel(ray.dir,n,o->mat,true)*trace(refr,i-1); } } return c; }
Spectrum DipoleSubsurfaceIntegrator::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Intersection &isect, const Sample *sample, RNG &rng, MemoryArena &arena) const { Spectrum L(0.); Vector wo = -ray.d; // Compute emitted light if ray hit an area light source L += isect.Le(wo); // Evaluate BSDF at hit point BSDF *bsdf = isect.GetBSDF(ray, arena); const Point &p = bsdf->dgShading.p; const Normal &n = bsdf->dgShading.nn; Spectrum rho_dr = Spectrum(1.0f); // Evaluate BSSRDF and possibly compute subsurface scattering BSSRDF *bssrdf = isect.GetBSSRDF(ray, arena); if (bssrdf && octree) { Spectrum sigma_a = bssrdf->sigma_a(); Spectrum sigmap_s = bssrdf->sigma_prime_s(); Spectrum sigmap_t = sigmap_s + sigma_a; if (!sigmap_t.IsBlack()) { // Use hierarchical integration to evaluate reflection from dipole model PBRT_SUBSURFACE_STARTED_OCTREE_LOOKUP(const_cast<Point *>(&p)); DiffusionReflectance Rd(sigma_a, sigmap_s, bssrdf->eta()); Spectrum Mo = octree->Mo(octreeBounds, p, Rd, maxError); FresnelDielectric fresnel(1.f, bssrdf->eta()); Spectrum Ft = Spectrum(1.f) - fresnel.Evaluate(AbsDot(wo, n)); float Fdt = 1.f - Fdr(bssrdf->eta()); // modulate SSS contribution by rho_dr //L += (INV_PI * Ft) * (Fdt * Mo); rho_dr = wet->integrate_BRDF(bsdf, ray.d, 10, BxDFType(BSDF_REFLECTION | BSDF_GLOSSY)); L += (INV_PI * Ft) * (Fdt * Mo) * (Spectrum(1.0f) - rho_dr); //L += (INV_PI * Ft) * (Fdt * Mo) * (Spectrum(0.0f)); PBRT_SUBSURFACE_FINISHED_OCTREE_LOOKUP(); } } L += UniformSampleAllLights(scene, renderer, arena, p, n, wo, isect.rayEpsilon, ray.time, bsdf, sample, rng, lightSampleOffsets, bsdfSampleOffsets); if (ray.depth < maxSpecularDepth) { // Trace rays for specular reflection and refraction. //TODO: this has no effect? L += SpecularReflect(ray, bsdf, rng, isect, renderer, scene, sample, arena); L += SpecularTransmit(ray, bsdf, rng, isect, renderer, scene, sample, arena); } return L; }
Color Fresnel::sample(const IntersectionInfo& info) { float eta = ior; float NdotI = dot(info.normal, info.rayDir); if (NdotI > 0) eta = 1.0f / eta; else NdotI = -NdotI; float fr = fresnel(NdotI, eta); return Color(fr, fr, fr); }
// for global lighting MyRGBColor FresnelReflector::sample_f(const ShadeRec& sr, Vector3D& wr, const Vector3D& wo, float& pdf) const { float ndotwo = sr.normal * wo; wr = -wo + 2.0 * sr.normal * ndotwo; //pdf = sr.normal * wr; pdf = fabs(sr.normal * wr); // maybe this instead? // assuming this is correct based on the other sample_f return(fresnel(sr) * white); //return (kr * cr); }
Vec trace(const Ray& r, const int index, const int num_samps) { // ray-sphere intersection double t; if (!intersect(r, t)) return Vec(); // compute the intersection data const Vec x = r.o + r.d * t, n = (x - sph.p).normalized(), w = -r.d; // compute Fresnel transmittance at point of emergence const double T21 = 1.0 - fresnel(w.dot(n), eta); // integration of the BSSRDF over the surface unsigned int xi = next_rand(index); Vec result; for (int i = 0; i < num_samps; i++) { // generate a sample Vec sp, sn, sw; sample(i, Vec(hal(2, index), hal(3, index), 0.0), sp, sn); sw = Vec(1, 1, -0.5).normalized(); // directional light source const double radiance = 8.0*PI; const double cos_wi_n = sn.dot(sw); if (cos_wi_n > 0.0) { // Russian roulette (note that accept_prob can be any value in (0, 1)) const double accept_prob = exp(-(sp - x).len() * min_sigma_tr); if ((xi / rand_range) < accept_prob) { const double T12 = 1.0 - fresnel(cos_wi_n, eta); const double Li_cos = T12 * radiance * cos_wi_n / (samplePDF * accept_prob); for (int j = 0; j < 3; j++) result[j] += bssrdf(sp, sn, sw, x, n, w, j) * Li_cos; // reciprocal evaulation with the reciprocity hack //for (int j = 0; j < 3; j++) result[j] += 0.5 * (bssrdf(sp, sn, sw, x, n, w, j) + bssrdf(x, n, w, sp, sn, sw, j)) * Li_cos; } xi = next_rand(xi); } } return T21 * result / (double)num_samps; }
void shoot(const Color& pow, Ray& ray, int i){ if(i>8) return; Obj* o; Vector x; Vector n; if(firstIntersect(ray, x, n, &o)<0) return; if(i&&!o->mat.reflective&&!o->mat.refractive){ if(n*ray.dir<0){ addPhoton(x, pow*(n*ray.dir*-1)); } return; } if(o->mat.reflective) { Vector refd=reflectDir(ray.dir,n)+x;; Ray ref(x,refd); if(o->mat.refractive){ bool valid=true; Vector refrd=refractDir(ray.dir,n,o->mat.n.r,valid); if(valid){ shoot(pow*fresnel(ray.dir,n,o->mat,false), ref, i+1); } else { shoot(pow, ref, i+1); } } else { shoot(pow*fresnel(ray.dir,n,o->mat,false), ref, i+1); } } if(o->mat.refractive){ bool valid=true; Vector refrd=refractDir(ray.dir,n,o->mat.n.r,valid)+x; if(valid){ Ray refr(x,refrd); shoot(pow*fresnel(ray.dir,n,o->mat,true), refr, i+1); } } }
nex::color fresnel_refraction_btdf::sample(const lumen::sample& sample, const surface& surface, const nex::vector& wo, nex::vector* wi, float* pdf) const { float eta = ni / nt; *wi = refract(wo, surface.normal, &eta); *pdf = 1.0f; // check for total internal reflection if (*wi == nex::vector(0.0f, 0.0f, 0.0f)) { return nex::color::black(); } return (1.0f - fresnel(ni, nt, nex::dot(surface.normal, wo))) * transmittance / (eta * eta) / std::abs(nex::dot(surface.normal, *wi)); }
Spectrum Lo(const Scene *scene, Sampler *sampler, const Intersection &its, const Vector &d, int depth) const { if (!m_ready || m_ssFactor.isZero()) return Spectrum(0.0f); IsotropicDipoleQuery query(m_zr, m_zv, m_sigmaTr, m_Fdt, its.p); const Normal &n = its.shFrame.n; m_octree->execute(query); if (m_eta == 1.0f) { return query.getResult() * m_ssFactor * INV_PI; } else { Float Ft = 1.0f - fresnel(absDot(n, d)); return query.getResult() * m_ssFactor * INV_PI * (Ft / m_Fdr); } }
extern "C" void execute(void *params, BVHShader_functions *func, void *env) { BVHShader_surface *surface = (BVHShader_surface*)env; BVHShader_params *p = (BVHShader_params*)params; float rayRefract[3]; float rayReflect[3]; BVHColor colorRefraction; BVHColor colorReflection; float fresnelFactor; // Calculate refraction ray refract(surface->normal, surface->rayInput, rayRefract, p->indexRel); invert(rayRefract); normalize(rayRefract); // Calculate reflection ray reflect(surface->normal, surface->rayInput, rayReflect); invert(rayReflect); normalize(rayReflect); // Normalize vector normalize(surface->rayOutput); // Get fresnel fresnelFactor = fresnel(surface->normal, surface->rayInput, p->indexRel); // Calculate reflection and refraction color if (dotAbs(surface->rayOutput, rayRefract) > 0.9999f) { colorRefraction.init(1.0f / dotAbs(surface->rayOutput, surface->normal)); colorReflection.init(0.0f); } else if (dotAbs(surface->rayOutput, rayReflect) > 0.9999f) { colorRefraction.init(0.0f); colorReflection.init(1.0f / dotAbs(surface->rayOutput, surface->normal)); } else { colorRefraction.init(0.0f); colorReflection.init(0.0f); } surface->color = p->color * (colorRefraction * (1.0f - fresnelFactor) + colorReflection * fresnelFactor); surface->emission.init(0.0f); }
Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample) const { bRec.measure = EDiscrete; //check if your are inside or not //compute the angle between the normal and the incoming direction float theta1 = Frame::cosTheta(bRec.wi); float fresnelTerm = fresnel(theta1, m_extIOR, m_intIOR); //check if entering or leaving bRec.entering = (theta1 > 0); float et = m_extIOR; float ei = m_intIOR; Vector3f n = Vector3f(0.0, 0.0, 1.0); if(!bRec.entering) { std::swap(ei, et); n(2) = -1.0; } // check you should a reflection or refraction if(sample(0) < fresnelTerm) { //mirror like reflection bRec.wo = Vector3f( -bRec.wi.x(), -bRec.wi.y(), bRec.wi.z() ); bRec.eta = 1.0f; } else { float snellsTerm = et / ei; float wdotn = bRec.wi.dot(n); Vector3f fstPart = (bRec.wi - (wdotn) * n); float srqtTerm = std::sqrt(1.0f - snellsTerm * snellsTerm * (1.0f - wdotn * wdotn)); bRec.wo = - snellsTerm * fstPart - n * srqtTerm; bRec.eta = bRec.entering? m_intIOR / m_extIOR : m_extIOR / m_intIOR; } return Color3f(1.0f); }
Float pdfDelta(const BSDFQueryRecord &bRec) const { bool sampleReflection = (bRec.typeMask & EDeltaReflection) && (bRec.component == -1 || bRec.component == 0); bool sampleTransmission = (bRec.typeMask & EDeltaTransmission) && (bRec.component == -1 || bRec.component == 1); bool reflection = bRec.wo.z * bRec.wi.z > 0; Float result = 0.0f; if (sampleTransmission && sampleReflection) { Float fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR); result = reflection ? fr : (1-fr); } else if (sampleReflection) { result = reflection ? 1.0f : 0.0f; } else if (sampleTransmission) { result = reflection ? 0.0f : 1.0f; } return result * std::abs(Frame::cosTheta(bRec.wo)); }
/** * Simple program that starts our raytracer */ int main(int argc, char *argv[]) { try { RayTracer* rt; Timer t; rt = new RayTracer(800, 600); std::shared_ptr<SceneObjectEffect> color(new ColorEffect(glm::vec3(0.0, 1.0, 0.0))); std::shared_ptr<SceneObjectEffect> phong(new PhongEffect(glm::vec3(0.0, 0.0, 10.0))); std::shared_ptr<SceneObjectEffect> steel(new SteelEffect()); std::shared_ptr<SceneObjectEffect> fresnel(new FresnelEffect()); std::shared_ptr<SceneObject> s1(new Sphere(glm::vec3(-3.0f, 0.0f, 6.0f), 2.0f, steel)); rt->addSceneObject(s1); std::shared_ptr<SceneObject> s2(new Sphere(glm::vec3(3.0f, 0.0f, 3.0f), 2.0f, fresnel)); rt->addSceneObject(s2); std::shared_ptr<SceneObject> s3(new Sphere(glm::vec3(0.0f, 3.0f, 9.0f), 2.0f, steel)); rt->addSceneObject(s3); std::string path = "cubemaps/SaintLazarusChurch3/"; std::shared_ptr<SceneObject> cubeMap(new CubeMap(path + "posx.jpg", path + "negx.jpg", path + "posy.jpg", path + "negy.jpg", path + "posz.jpg", path + "negz.jpg")); rt->addSceneObject(cubeMap); std::shared_ptr<SceneObject> triangle(new Triangle(glm::vec3(0.0f, 2.0f, -1.0f), glm::vec3(-2.0f, -2.0f, -1.0f), glm::vec3(2.0f, -2.0f, 0.0f), steel)); rt->addSceneObject(triangle); t.restart(); rt->render(); double elapsed = t.elapsed(); std::cout << "Computed in " << elapsed << " seconds" << std::endl; rt->save("test", "bmp"); //We want to write out bmp's to get proper bit-maps (jpeg encoding is lossy) delete rt; } catch (std::exception &e) { std::string err = e.what(); std::cout << err.c_str() << std::endl; return -1; } return 0; }
const BSDF *MetalMaterial::GetBSDF(const DifferentialGeometry &i_dg, size_t i_triangle_index, MemoryPool &i_pool) const { BSDF *p_bsdf = new ( i_pool.Alloc(sizeof(BSDF)) ) BSDF(i_dg); SpectrumCoef_d r, a; if (mp_refractive_index && mp_absorption) { r = mp_refractive_index->Evaluate(i_dg, i_triangle_index); a = mp_absorption->Evaluate(i_dg, i_triangle_index); } else { ASSERT(mp_reflectance); SpectrumCoef_d reflectance = mp_reflectance->Evaluate(i_dg, i_triangle_index); reflectance.Clamp(0.0, 1.0); ApproximateFresnelParameters(reflectance, r, a); } FresnelConductor fresnel(r, a); BxDF *p_bxdf; if (mp_roughness) { typedef Microfacet<FresnelConductor,BlinnDistribution> BlinnMicrofacetMetal; double roughness = MathRoutines::Clamp(mp_roughness->Evaluate(i_dg, i_triangle_index), 0.001, 1.0); BlinnDistribution blinn(1.0/roughness); p_bxdf = new ( i_pool.Alloc(sizeof(BlinnMicrofacetMetal)) ) BlinnMicrofacetMetal(SpectrumCoef_d(1.0), fresnel, blinn); } else { ASSERT(mp_u_roughness && mp_v_roughness); typedef Microfacet<FresnelConductor,AnisotropicDistribution> AnisotropicMicrofacetMetal; double u_roughness = MathRoutines::Clamp(mp_u_roughness->Evaluate(i_dg, i_triangle_index), 0.001, 1.0); double v_roughness = MathRoutines::Clamp(mp_v_roughness->Evaluate(i_dg, i_triangle_index), 0.001, 1.0); AnisotropicDistribution anisotropic(1.0/u_roughness, 1.0/v_roughness); p_bxdf = new ( i_pool.Alloc(sizeof(AnisotropicMicrofacetMetal)) ) AnisotropicMicrofacetMetal(SpectrumCoef_d(1.0), fresnel, anisotropic); } p_bsdf->AddBxDF(p_bxdf); return p_bsdf; }
bool refractRay(const Vec3& origin, const Vec3&incident_dir, const Vec3& normal, const float rei[], Vec3& refract_dir, float& ref_weight) { float eta = rei[0] / rei[1]; float c1 = normal.dot(incident_dir), c2 = 1 - eta*eta*(1 - c1*c1); if (c2<0) { ref_weight = 1.0f; return false; } Vec3 v_nor = normal; if (c1<0.0f) c1 = -c1; else v_nor *= -1; refract_dir = eta*incident_dir + (eta*c1 - sqrt(c2))*v_nor; fresnel(c1, fabs(refract_dir.dot(normal)), rei, ref_weight); return true; }
RGBColor FresnelTransmitter::sample_f(const ShadeRec& sr, const Vector3D& wo, Vector3D& wt) const { Normal n(sr.normal); float cos_thetai = n * wo; float eta = eta_in / eta_out;//ior; if (cos_thetai < 0.0) { // transmitted ray is outside cos_thetai = -cos_thetai; n = -n; // reverse direction of normal eta = 1.0 / eta; // invert ior } float temp = 1.0 - (1.0 - cos_thetai * cos_thetai) / (eta * eta); float cos_theta2 = sqrt(temp); wt = -wo / eta - (cos_theta2 - cos_thetai / eta) * n; return (fresnel(sr) / (eta * eta) * white / fabs(sr.normal * wt)); }
static unsigned int ray_color(const point3 e, double t, const point3 d, idx_stack *stk, const rectangular_node rectangulars, const sphere_node spheres, const light_node lights, color object_color, int bounces_left) { rectangular_node hit_rec = NULL, light_hit_rec = NULL; sphere_node hit_sphere = NULL, light_hit_sphere = NULL; double diffuse, specular; point3 l, _l, r, rr; object_fill fill; color reflection_part; color refraction_part; /* might be a reflection ray, so check how many times we've bounced */ if (bounces_left == 0) { SET_COLOR(object_color, 0.0, 0.0, 0.0); return 0; } /* check for intersection with a sphere or a rectangular */ intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars, &hit_rec, spheres, &hit_sphere); if (!hit_rec && !hit_sphere) return 0; /* pick the fill of the object that was hit */ fill = hit_rec ? hit_rec->element.rectangular_fill : hit_sphere->element.sphere_fill; void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere; /* assume it is a shadow */ SET_COLOR(object_color, 0.0, 0.0, 0.0); for (light_node light = lights; light; light = light->next) { /* calculate the intersection vector pointing at the light */ subtract_vector(ip.point, light->element.position, l); multiply_vector(l, -1, _l); normalize(_l); /* check for intersection with an object. use ignore_me * because we don't care about this normal */ ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l), rectangulars, &light_hit_rec, spheres, &light_hit_sphere); /* the light was not block by itself(lit object) */ if (light_hit_rec || light_hit_sphere) continue; compute_specular_diffuse(&diffuse, &specular, d, l, ip.normal, fill.phong_power); localColor(object_color, light->element.light_color, diffuse, specular, &fill); } reflection(r, d, ip.normal); double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction; if (idx_stack_top(stk).obj == hit_obj) { idx_stack_pop(stk); idx_pass = idx_stack_top(stk).idx; } else { idx_stack_element e = { .obj = hit_obj, .idx = fill.index_of_refraction }; idx_stack_push(stk, e); } refraction(rr, d, ip.normal, idx, idx_pass); double R = (fill.T > 0.1) ? fresnel(d, rr, ip.normal, idx, idx_pass) : 1.0; /* totalColor = localColor + mix((1-fill.Kd) * fill.R * reflection, T * refraction, R) */ if (fill.R > 0) { /* if we hit something, add the color */ int old_top = stk->top; if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres, lights, reflection_part, bounces_left - 1)) { multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R, reflection_part); add_vector(object_color, reflection_part, object_color); } stk->top = old_top; } /* calculate refraction ray */ if ((length(rr) > 0.0) && (fill.T > 0.0) && (fill.index_of_refraction > 0.0)) { normalize(rr); if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres, lights, refraction_part, bounces_left - 1)) { multiply_vector(refraction_part, (1 - R) * fill.T, refraction_part); add_vector(object_color, refraction_part, object_color); } } protect_color_overflow(object_color); return 1; } /* @param background_color this is not ambient light */ void raytracing(void* args) { arg *data = (arg*) args; point3 u, v, w, d; color object_color = { 0.0, 0.0, 0.0 }; const viewpoint *view = (*data).View; color back = { 0.0 , 0.1 , 0.1 }; uint8_t *pixels = data->pixels; int start_j,end_j; /* Separate to count the pixels */ if(pthread_equal(pthread_self(),THREAD[0])) { start_j = 0; end_j = 128; } else if(pthread_equal(pthread_self(),THREAD[1])) { start_j = 128; end_j = 256; } else if(pthread_equal(pthread_self(),THREAD[2])) { start_j = 256; end_j = 384; } else if(pthread_equal(pthread_self(),THREAD[3])) { start_j = 384; end_j = 512; } /* calculate u, v, w */ calculateBasisVectors(u, v, w, view); idx_stack stk; int factor = sqrt(SAMPLES); #pragma omp parallel for num_threads(64) \ private(stk), private(d), \ private(object_color) for (int j = start_j ; j < end_j; j++) { for (int i = 0 ; i < (*data).row; i++) { double r = 0, g = 0, b = 0; /* MSAA */ for (int s = 0; s < SAMPLES; s++) { idx_stack_init(&stk); rayConstruction(d, u, v, w, i * factor + s / factor, j * factor + s % factor, view, (*data).row * factor, (*data).col * factor); if (ray_color(view->vrp, 0.0, d, &stk,(*data).rectangulars, (*data).spheres, (*data).lights, object_color, MAX_REFLECTION_BOUNCES)) { r += object_color[0]; g += object_color[1]; b += object_color[2]; } else { r += back[0]; g += back[1]; b += back[2]; } pixels[((i + (j * (*data).row)) * 3) + 0] = r * 255 / SAMPLES; pixels[((i + (j * (*data).row)) * 3) + 1] = g * 255 / SAMPLES; pixels[((i + (j * (*data).row)) * 3) + 2] = b * 255 / SAMPLES; } } } }
void fg(real_t x, real_t *f, real_t *g) { void fresnel(real_t, real_t *, real_t *); real_t absx,c,s,c1,s1,a,xinv,x3inv,c4,p,q; absx=fabs(x); if (absx <= 1.6) { fresnel(x,&c,&s); a=x*x*1.57079632679490; c1=cos(a); s1=sin(a); a = (x < 0.0) ? -0.5 : 0.5; p=a-c; q=a-s; *f = q*c1-p*s1; *g = p*c1+q*s1; } else if (absx <= 1.9) { xinv=1.0/x; a=xinv*xinv; x3inv=a*xinv; c4=a*a; p=(((1.35304235540388e1*c4+6.98534261601021e1)*c4+ 4.80340655577925e1)*c4+8.03588122803942e0)*c4+ 3.18309268504906e-1; q=(((6.55630640083916e1*c4+2.49561993805172e2)*c4+ 1.57611005580123e2)*c4+2.55491618435795e1)*c4+1.0; *f = xinv*p/q; p=((((2.05421432498501e1*c4+1.96232037971663e2)*c4+ 1.99182818678903e2)*c4+5.31122813480989e1)*c4+ 4.44533827550512e0)*c4+1.01320618810275e-1; q=((((1.01379483396003e3*c4+3.48112147856545e3)*c4+ 2.54473133181822e3)*c4+5.83590575716429e2)*c4+ 4.53925019673689e1)*c4+1.0; *g = x3inv*p/q; } else if (absx <= 2.4) { xinv=1.0/x; a=xinv*xinv; x3inv=a*xinv; c4=a*a; p=((((7.17703249365140e2*c4+3.09145161574430e3)*c4+ 1.93007640786716e3)*c4+3.39837134926984e2)*c4+ 1.95883941021969e1)*c4+3.18309881822017e-1; q=((((3.36121699180551e3*c4+1.09334248988809e4)*c4+ 6.33747155851144e3)*c4+1.08535067500650e3)*c4+ 6.18427138172887e1)*c4+1.0; *f = xinv*p/q; p=((((3.13330163068756e2*c4+1.59268006085354e3)*c4+ 9.08311749529594e2)*c4+1.40959617911316e2)*c4+ 7.11205001789783e0)*c4+1.01321161761805e-1; q=((((1.15149832376261e4*c4+2.41315567213370e4)*c4+ 1.06729678030581e4)*c4+1.49051922797329e3)*c4+ 7.17128596939302e1)*c4+1.0; *g = x3inv*p/q; } else { xinv=1.0/x; a=xinv*xinv; x3inv=a*xinv; c4=a*a; p=((((2.61294753225142e4*c4+6.13547113614700e4)*c4+ 1.34922028171857e4)*c4+8.16343401784375e2)*c4+ 1.64797712841246e1)*c4+9.67546032967090e-2; q=((((1.37012364817226e6*c4+1.00105478900791e6)*c4+ 1.65946462621853e5)*c4+9.01827596231524e3)*c4+ 1.73871690673649e2)*c4+1.0; *f = (c4*(-p)/q+0.318309886183791)*xinv; p=(((((1.72590224654837e6*c4+6.66907061668636e6)*c4+ 1.77758950838030e6)*c4+1.35678867813756e5)*c4+ 3.87754141746378e3)*c4+4.31710157823358e1)*c4+ 1.53989733819769e-1; q=(((((1.40622441123580e8*c4+9.38695862531635e7)*c4+ 1.62095600500232e7)*c4+1.02878693056688e6)*c4+ 2.69183180396243e4)*c4+2.86733194975899e2)*c4+1.0; *g = (c4*(-p)/q+0.101321183642338)*x3inv; } }
cv::Mat HologramDecoder::decode_hologram( cv::Mat hologram, float z, float lambda, float dx, float dy ) { return fresnel( hologram, dx, dy, lambda * z, lambda ); }
static unsigned int ray_color(const point3 e, double t, const point3 d, idx_stack *stk, const rectangular_node rectangulars, const sphere_node spheres, const light_node lights, color object_color, int bounces_left) { rectangular_node hit_rec = NULL, light_hit_rec = NULL; sphere_node hit_sphere = NULL, light_hit_sphere = NULL; double diffuse, specular; point3 l, _l, r, rr; object_fill fill; color reflection_part; color refraction_part; /* might be a reflection ray, so check how many times we've bounced */ if (bounces_left == 0) { SET_COLOR(object_color, 0.0, 0.0, 0.0); return 0; } /* check for intersection with a sphere or a rectangular */ intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars, &hit_rec, spheres, &hit_sphere); if (!hit_rec && !hit_sphere) return 0; /* pick the fill of the object that was hit */ fill = hit_rec ? hit_rec->element.rectangular_fill : hit_sphere->element.sphere_fill; void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere; /* assume it is a shadow */ SET_COLOR(object_color, 0.0, 0.0, 0.0); for (light_node light = lights; light; light = light->next) { /* calculate the intersection vector pointing at the light */ subtract_vector(ip.point, light->element.position, l); multiply_vector(l, -1, _l); normalize(_l); /* check for intersection with an object. use ignore_me * because we don't care about this normal */ ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l), rectangulars, &light_hit_rec, spheres, &light_hit_sphere); /* the light was not block by itself(lit object) */ if (light_hit_rec || light_hit_sphere) continue; compute_specular_diffuse(&diffuse, &specular, d, l, ip.normal, fill.phong_power); localColor(object_color, light->element.light_color, diffuse, specular, &fill); } reflection(r, d, ip.normal); double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction; if (idx_stack_top(stk).obj == hit_obj) { idx_stack_pop(stk); idx_pass = idx_stack_top(stk).idx; } else { idx_stack_element e = { .obj = hit_obj, .idx = fill.index_of_refraction }; idx_stack_push(stk, e); } refraction(rr, d, ip.normal, idx, idx_pass); double R = (fill.T > 0.1) ? fresnel(d, rr, ip.normal, idx, idx_pass) : 1.0; /* totalColor = localColor + mix((1-fill.Kd) * fill.R * reflection, T * refraction, R) */ if (fill.R > 0) { /* if we hit something, add the color */ int old_top = stk->top; if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres, lights, reflection_part, bounces_left - 1)) { multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R, reflection_part); add_vector(object_color, reflection_part, object_color); } stk->top = old_top; } /* calculate refraction ray */ if ((length(rr) > 0.0) && (fill.T > 0.0) && (fill.index_of_refraction > 0.0)) { normalize(rr); if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres, lights, refraction_part, bounces_left - 1)) { multiply_vector(refraction_part, (1 - R) * fill.T, refraction_part); add_vector(object_color, refraction_part, object_color); } } protect_color_overflow(object_color); return 1; } static void *parallel (void* range1) { Thread_range *range = (Thread_range *)range1; point3 d; idx_stack stk; color object_color = { 0.0, 0.0, 0.0 }; for (int j = range->height1; j < range->height2; j++) { for (int i = 0; i < range->ptr->width; i++) { double r = 0, g = 0, b = 0; /* MSAA */ for (int s = 0; s < SAMPLES; s++) { idx_stack_init(&stk); rayConstruction(d, range->ptr->u, range->ptr->v, range->ptr->w, i * range->ptr->factor + s / range->ptr->factor, j * range->ptr->factor + s % range->ptr->factor, range->ptr->view, range->ptr->width * range->ptr->factor, range->ptr->height * range->ptr->factor); if (ray_color(range->ptr->view->vrp, 0.0, d, &(stk), range->ptr->rectangulars, range->ptr->spheres, range->ptr->lights, object_color, MAX_REFLECTION_BOUNCES)) { r += object_color[0]; g += object_color[1]; b += object_color[2]; } else { r += range->ptr->background_color[0]; g += range->ptr->background_color[1]; b += range->ptr->background_color[2]; } range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 0] = r * 255 / SAMPLES; range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 1] = g * 255 / SAMPLES; range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 2] = b * 255 / SAMPLES; } } } return NULL; }