private Ray CastRefractionRay(Ray ray, HitRecord record, float refractive) { Vector rayDirection = ray.Direction; Vector surfaceNormal = record.SurfaceNormal; Vector refractedColor = new Vector(); float newRefractive = record.Material.RefractionIndex.x; if (newRefractive == refractive) { newRefractive = 1.0f; } //rayDirection = -surfaceNormal; float dDotn = Vector.Dot3(ray.Direction, surfaceNormal); float sqrtArgs = 1.0f - (refractive * refractive * (1 - dDotn * dDotn)) / (newRefractive * newRefractive); Vector refractiveDir = new Vector(); Ray refractionRay; if (sqrtArgs > 0.0f) { Vector nSqrt = surfaceNormal * (float)Math.Sqrt(sqrtArgs); refractiveDir = (refractive * (rayDirection - surfaceNormal * dDotn)) / newRefractive - nSqrt; refractiveDir.Normalize3(); //refractiveDir = rayDirection; refractionRay = new Ray(record.HitPoint + refractiveDir * 0.1f, refractiveDir); refractionRay.Time = ray.Time; if (RenderingParameters.showMouse) { //Console.WriteLine("Refracting"); // Console.WriteLine("Ray direction: "); // Console.WriteLine(rayDirection); // Console.WriteLine("Refraction direction: "); // Console.WriteLine(refractiveDir); // Console.WriteLine(); } return refractionRay; } else return ray; }
private Vector CalculateColor(Ray ray, float minDistance, float maxDistance, int reflections, int refractions, float refractive) { HitRecord record = new HitRecord(); Vector finalColor = new Vector(); Vector lightDirection = new Vector(); bool hitSomething = false; Vector surfaceNormal = new Vector(); Vector rayDirection = ray.Direction; foreach (SceneObject sceneObject in scene.Objects) { //First check intersection bool intersects = sceneObject.IsHit(ray, record, minDistance, maxDistance); //If it intersects, diffuse color is set, so set shading color if (intersects) { hitSomething = true; surfaceNormal = record.SurfaceNormal; if (record.Material.RefractionIndex.x > 0.0f && record.Material.Refractiveness.x == 1.0f) { continue; } record.ShadedColors.Clear(); foreach (SceneLight light in scene.Lights) { Vector currentLightColor = new Vector(); lightDirection = light.Position - record.HitPoint; lightDirection.Normalize3(); //Get cosine of angle between vectors float similarity = Vector.Dot3(surfaceNormal, lightDirection); Vector lambertColor = new Vector(); if (record.Material.TextureImage != null) { lambertColor = Vector.ColorMultiplication(light.Color, record.TextureColor) * Math.Max(0, similarity); } else { lambertColor = Vector.ColorMultiplication(light.Color, record.Material.Diffuse) * Math.Max(0, similarity); } //Get half vector between camera direction and light direction Vector halfVector = -1 * rayDirection + lightDirection; halfVector.Normalize3(); //Phong shading calculations float normalHalfSimilarity = Vector.Dot3(surfaceNormal, halfVector); Vector phongLightCoefficient = Vector.ColorMultiplication(light.Color, record.Material.Specular); float shininessComponent = (float)Math.Pow(Math.Max(0, normalHalfSimilarity), record.Material.Shininess); Vector phongColor = phongLightCoefficient * shininessComponent; //Add colors and ambient light //Assume no transparency currentLightColor = Vector.LightAdd(lambertColor, phongColor); record.ShadedColors.Add(currentLightColor); } } } if (hitSomething) { if (RenderingParameters.showMouse) { Console.WriteLine("Hit material " + record.Material.Name); } finalColor = new Vector(); ////////////////////////////////////////////////////////////// ///////////////////////SHADOWS/////////////////////////////// ///////////////////////////////////////////////////////////// if (RenderingParameters.showMouse) { Console.WriteLine("Checking for shadows!"); } for (int i = 0; i < scene.Lights.Count; i++) //For each light { if (renderingParameters.EnableShadows) { if (record.Material.RefractionIndex.x == 0.0f) //Not refractive surface { Vector direction = scene.Lights[i].Position - record.HitPoint; direction.Normalize3(); Vector shadowStart = record.HitPoint + direction * 0.1f; Ray shadowRay = new Ray(shadowStart, direction); bool makesShadow = MakesShadow(shadowRay, scene.Lights[i], reflections, refractions, refractive, ray.Time); if (makesShadow) { record.ShadedColors[i] = new Vector(); } } } if (record.Material.Refractiveness.x != 1.0f) { finalColor = Vector.LightAdd(finalColor, record.ShadedColors[i]); finalColor.w = 1.0f; } } /////////////////////////////////////////////////////////////// //////////////////////REFRACTIONS///////////////////////////// ////////////////////////////////////////////////////////////// if (renderingParameters.EnableRefractions && refractions < 10 && !record.Material.RefractionIndex.IsBlack()) { if (record.Material.Refractiveness.x < 1.0f) { int a = 1; } Ray refractedRay = CastRefractionRay(ray, record, refractive); Vector refractiveNess = record.Material.Refractiveness; if (RenderingParameters.showMouse) Console.WriteLine("REFRACTING"); finalColor = Vector.ColorMultiplication(refractiveNess, CalculateColor(refractedRay, float.MinValue, float.MaxValue, reflections, refractions + 1, record.Material.RefractionIndex.x)) + Vector.ColorMultiplication(new Vector(1.0f, 1.0f, 1.0f) - refractiveNess, finalColor); } /////////////////////////////////////////////////////////////// //////////////////////REFLECTIONS///////////////////////////// ////////////////////////////////////////////////////////////// if (renderingParameters.EnableReflections && reflections < 20 && !record.Material.Reflective.IsBlack() ) { Vector d = rayDirection; //Check for reflections Vector reflection = d -2* Vector.Dot3(d, surfaceNormal) * surfaceNormal; reflection.Normalize3(); HitRecord reflectionRecord = new HitRecord(); Ray reflectionRay = new Ray(record.HitPoint + reflection * 0.01f, reflection); reflectionRay.Time = ray.Time; //if (showMouse) //{ // Console.WriteLine("Reflection direction: "); // Console.WriteLine(reflection); // Console.WriteLine(); //} Vector reflectiveColor = record.Material.Reflective; if (RenderingParameters.showMouse) { Console.WriteLine("REFLECTING - NORMAL: " + surfaceNormal + "\tReflection: " + reflection); } Vector reflectedObjectColor = CalculateColor(reflectionRay, float.MinValue, float.MaxValue, reflections + 1, refractions, refractive); finalColor = Vector.LightAdd(finalColor, Vector.ColorMultiplication(reflectiveColor, reflectedObjectColor)); finalColor = Vector.LightAdd(finalColor, scene.Background.AmbientLight); } } if (reflections == 0 && refractions == 0) { //finalColor = Vector.LightAdd(finalColor, scene.Background.AmbientLight); if (RenderingParameters.showMouse) { RenderingParameters.showMouse = false; Console.WriteLine("-------------------------------------------------------"); Console.WriteLine("-------------------------------------------------------"); } } finalColor.w = 1.0f; return finalColor; }