cv::Vec3b Camera::CastRay(Scene scene, Ray r) { std::vector<SpherePoint> Intersections = FindIntersectionPoints(scene.GetSphereList(), r); cv::Vec3b ReturnColor(255, 255, 255); // If the ray intersected with any of them, find the closest point if (Intersections.size() != 0) { Sphere ClosestSphere(Point(0,0,0),0,cv::Vec3b(0,0,0),Finish(0,0,0,0)); Point ClosestPoint(0, 0, 0); double ShortestDistance = std::numeric_limits<double>::max(); for (auto& SpherePoint : Intersections) { Sphere& S = SpherePoint.s; Point& P = SpherePoint.p; double TempDist = r.Location.FromThisToThat(P).Length(); if (TempDist < ShortestDistance) { ShortestDistance = TempDist; ClosestSphere = S; ClosestPoint = P; } } // Compute ambient component cv::Vec3d& SceneAmb = scene.GetAmbientLightColor(); cv::Vec3b SphereAmbientColor = ClosestSphere.Color * ClosestSphere.Fin.Ambient; SphereAmbientColor[0] *= SceneAmb[0]; SphereAmbientColor[1] *= SceneAmb[1]; SphereAmbientColor[2] *= SceneAmb[2]; // Compute diffuse component // Translate the intersection point to avoid precision errors cv::Vec3b DiffuseColor(0, 0, 0); cv::Vec3b SpecularColor(0, 0, 0); Vector SphereNormal = SphereNormalAtPoint(ClosestSphere, ClosestPoint); ClosestPoint = ClosestPoint.Translate(SphereNormal * 0.01); Vector PointToLight = ClosestPoint.FromThisToThat(scene.GetLightPosition()).Normalize(); // Check to see if intersection point is on the same side as the light // And to make sure there is not another sphere in the way double DotProduct = PointToLight.Dot(SphereNormal); if (DotProduct > 0) { Intersections = FindIntersectionPoints(scene.GetSphereList(), Ray(ClosestPoint, PointToLight)); // Need to account for when spheres are past the light if (Intersections.size() == 0) { cv::Vec3d& LightColor = scene.GetLightColor(); DiffuseColor = ClosestSphere.Color * ClosestSphere.Fin.Diffuse; DiffuseColor[0] *= DotProduct * LightColor[0]; DiffuseColor[1] *= DotProduct * LightColor[1]; DiffuseColor[2] *= DotProduct * LightColor[2]; // Compute the specular light contribution Vector ReflectionVector = PointToLight - (SphereNormal * (2 * DotProduct)); Vector ViewDirection = r.Location.FromThisToThat(ClosestPoint).Normalize(); double SpecIntensity = ReflectionVector.Dot(ViewDirection); if (SpecIntensity > 0) { double Multiplier = ClosestSphere.Fin.Specular * std::pow(SpecIntensity, 1 / ClosestSphere.Fin.Roughness); SpecularColor[0] = Multiplier * LightColor[0] * 255; SpecularColor[1] = Multiplier * LightColor[1] * 255; SpecularColor[2] = Multiplier * LightColor[2] * 255; } } } ReturnColor = SphereAmbientColor + DiffuseColor + SpecularColor; } return ReturnColor; }