public Color Li( Shape obj, ILight light, Vector4 point, Vector4 eyev, Vector4 normalv, double intensity = 1.0) { Color color, ambient, diffuse, specular; if (this.Pattern != null) { color = this.Pattern.GetColor(obj, point); } else { color = this.Color; } var effectiveColor = color * light.Intensity; ambient = effectiveColor * this.Ambient; var sum = Color.Black; foreach (var lightPos in light.Sample()) { var lightv = (lightPos - point).Normalize(); var lightDotNormal = Vector4.Dot(lightv, normalv); if (lightDotNormal < 0) { diffuse = Color.Black; specular = Color.Black; } else { diffuse = effectiveColor * this.Diffuse * lightDotNormal; var reflectv = Vector4.Reflect(-lightv, normalv); var reflectDotEye = Vector4.Dot(reflectv, eyev); if (reflectDotEye <= 0) { specular = Color.Black; } else { var factor = (double)Math.Pow(reflectDotEye, this.Shininess); specular = light.Intensity * this.Specular * factor; } } sum += diffuse; sum += specular; } return(ambient + (sum * (1.0 / light.Samples)) * intensity); }
public Color Lighting(Shape shape, ILight light, Point point, Vector eye, Vector normal, double intensity = 1.0) { Color ambient; Color diffuse; Color specular; Color specColor = Color.Black; Vector bumpVec = new Vector(0, 0, 0); Color color = this.Color; if (this.Pattern != null) { color = this.Pattern.PatternAtShape(shape, point); } if (this.SpecularMap != null) { specColor = this.SpecularMap.PatternAtShape(shape, point); } if (this.NormalMap != null) { var bumpColor = this.NormalMap.PatternAtShape(shape, point); bumpVec = new Vector(bumpColor.Red, bumpColor.Blue, bumpColor.Green).Normalize(); normal = normal + bumpVec * 10.0; } // combine the surface color with the light's color/intensity var effective_color = color * light.Color; // compute the ambient contribution ambient = effective_color * this.Ambient; var sum = Color.Black; foreach (Point sample in light.Sample()) { // find the direction to the light source var lightv = (sample - point).Normalize(); // light_dot_normal represents the cosine of the angle between the // light vector and the normal vector. A negative number means the // light is on the other side of the surface. var light_dot_normal = lightv.Dot(normal); if (light_dot_normal < 0) { diffuse = Color.Black; specular = Color.Black; } else { // compute the diffuse contribution diffuse = effective_color * this.Diffuse * light_dot_normal; // reflect_dot_eye represents the cosine of the angle between the // reflection vector and the eye vector. A negative number means the // light reflects away from the eye. var reflect = -lightv.Reflect(normal); var reflect_dot_eye = reflect.Dot(eye); if (reflect_dot_eye <= 0) { specular = Color.Black; } else { // compute the specular contribution var factor = Math.Pow(reflect_dot_eye, this.Shininess); if (this.SpecularMap != null) { specular = light.Color * this.Specular * specColor * factor; } else { specular = light.Color * this.Specular * factor; } } } sum = sum + diffuse; sum = sum + specular; } return(ambient + (sum / light.Samples) * intensity); }
public static RgbSpectrum EstimateDirect(ref Vector wo, IAccellerationStructure intersector, SceneGeometryInfo scene, ILight light, IntersectionInfo isect, SurfaceBsdf bsdf, FastRandom rnd) { RgbSpectrum Ld = new RgbSpectrum(); Vector wi; float lightPdf, bsdfPdf; RayInfo shadowRay; RgbSpectrum Li = light.Sample(ref isect.GeometryInfo.HitPoint, ref isect.GeometryInfo.GeoNormal, rnd.NextFloat(), rnd.NextFloat(), rnd.NextFloat(), out shadowRay, out lightPdf); if (lightPdf > 0f && !Li.IsBlack()) { wi = -shadowRay.Dir; RgbSpectrum f ; bsdf.f(ref wo, ref wi, ref isect.GeometryInfo.GeoNormal, ref Ld, out f); if (!f.IsBlack() && !intersector.Intersect(shadowRay)) { // Add light's contribution to reflected radiance //Li *= visibility.Transmittance(scene, renderer, NULL, rng, arena); if (light.IsDelta) Ld += f * Li * (Vector.AbsDot(ref wi, ref isect.GeometryInfo.GeoNormal) / lightPdf); else { bsdfPdf = bsdf.Pdf(ref wo, ref wi, BxDFTypes.BSDF_ALL_TYPES); float weight = MC.PowerHeuristic(1, lightPdf, 1, bsdfPdf); Ld += f * Li * (Vector.AbsDot(ref wi, ref isect.GeometryInfo.GeoNormal) * weight / lightPdf); } } } if (!light.IsDelta) { //float bsdfPdf; bool spb; BsdfSampleData result; bsdf.Sample_f(ref wo, ref isect.GeometryInfo.GeoNormal, ref isect.GeometryInfo.ShadingNormal, ref Ld, rnd.NextFloat(), rnd.NextFloat(), rnd.NextFloat(), ref isect.TextureData, out result); bsdfPdf = result.Pdf; if (!result.F.IsBlack() && result.Pdf > 0f) { if (lightPdf > 0f) { float weight = MC.PowerHeuristic(1, bsdfPdf, 1, lightPdf); IntersectionInfo lightIsect; RgbSpectrum li = new RgbSpectrum(); var ray = new RayInfo(isect.GeometryInfo.HitPoint, result.Wi, 1e-4f, 1e+4f); if (intersector.Intersect(ray, out lightIsect)) { if (light is TriangleLight && lightIsect.PrimitiveId.Equals(((TriangleLight)light).Owner.Id)) li = light.Le(-result.Wi); } else li = light.Le(ray.Dir); if (!li.IsBlack()) { //Li *= scene->Transmittance(ray); Ld += result.F * li * Vector.AbsDot(ref result.Wi, ref isect.GeometryInfo.GeoNormal) * weight / bsdfPdf; } } } } /* if (!light->IsDeltaLight()) { BxDFType flags = BxDFType(BSDF_ALL & ~BSDF_SPECULAR); Spectrum f = bsdf->Sample_f(wo, &wi, bs1, bs2, bcs, &bsdfPdf, flags); if (!f.Black() && bsdfPdf > 0.) { lightPdf = light->Pdf(p, n, wi); if (lightPdf > 0.) { // Add light contribution from BSDF sampling float weight = PowerHeuristic(1, bsdfPdf, 1, lightPdf); Intersection lightIsect; Spectrum Li(0.f); RayDifferential ray(p, wi); if (scene->Intersect(ray, &lightIsect)) { if (lightIsect.primitive->GetAreaLight() == light) Li = lightIsect.Le(-wi); } else Li = light->Le(ray); if (!Li.Black()) { Li *= scene->Transmittance(ray); Ld += f * Li * AbsDot(wi, n) * weight / bsdfPdf; } } } } */ return Ld; }
public Color PathTrace(Ray ray, HitRecord record, List <List <Sample> > subPathSamples, LightSample lightSample) { float q = 0f; int depth = 0; Color pixelColor = new Color(0, 0, 0); Color alpha = new Color(1, 1, 1); bool isGeneratedFromRefraction = false; while (depth < Constants.MaximalPathLength) { if (record == null) { return(pixelColor); } //Select one light at random ILight light = Randomizer.PickRandomLight(lights); //Sample that light light.Sample(record, lightSample); if (isGeneratedFromRefraction && record.HitObject.Light != null) { isGeneratedFromRefraction = false; pixelColor.Append(record.HitObject.Light.LightColor); } pixelColor.Append(alpha.Mult(Shade(record, lightSample)).Div(lightSample.Pdf)); //Break with Russian roulette if (depth > 2) { q = 0.5f; if (random.NextDouble() <= q) { return(pixelColor); } } List <Sample> directionSamples = subPathSamples[depth]; //Create the next Ray if (record.Material is LambertMaterial || record.Material is BlinnPhongMaterial) { Sample directionSample = Randomizer.PickRandomSample(directionSamples); Vector3 direction = UniformHemisphereSample(directionSample.X, directionSample.Y, record.SurfaceNormal); record = scene.Intersect(new Ray(record.IntersectionPoint, direction)); if (record == null) { break; } alpha = alpha.Mult(record.Material.Diffuse.Div(1 - q)); } else if (record.Material is MirrorMaterial) { record = scene.Intersect(record.CreateReflectedRay()); isGeneratedFromRefraction = true; } else if (record.Material is RefractiveMaterial) { isGeneratedFromRefraction = true; float fresnel = Reflectance(record); //Pick refraction / reflection path with p=0.5 each if (random.NextDouble() < fresnel) { record = scene.Intersect(record.CreateReflectedRay()); alpha = alpha.Mult(fresnel); } else { record = scene.Intersect(record.CreateRefractedRay()); alpha = alpha.Mult(1 - fresnel); } } depth++; } return(pixelColor); }