/// <summary> /// Trace single ray in a given direction. /// </summary> /// <param name="origin"></param> /// <param name="direction"></param> /// <param name="depth">Current recursion level.</param> /// <param name="lastReflected">The object from ray was cast.</param> /// <returns></returns> Color TraceSingleRay(Vector <double> origin, Vector <double> direction, uint depth = 0, ICollidable lastReflected = null) { if (depth >= MaxDepth) { return(Skybox.GetColorInDirection(direction)); } var nearest = GetNearestEntity(origin, direction, lastReflected); // If nearest entity is null it means that ray hasn't collide with anything if (nearest.Entity == null) { return(Skybox.GetColorInDirection(direction) * new Color(0.5, 0.5, 0.5)); } // Point of collision. var point = origin + nearest.Distance * direction; var entity = nearest.Entity; var material = entity.Material; var fragment = entity.GetMaterialFragmentInPoint(point); var localColor = material.GetColor(fragment); var diffuseColor = GetDiffuseColor(entity, point); // If reflection coefficient is zero no further casting is needed var reflectionColor = Color.Zero; if (material.ReflectionCoefficient > double.Epsilon) { reflectionColor = GetReflectionColor(entity, point, direction, depth); } return(localColor * (diffuseColor + material.ReflectionCoefficient * reflectionColor)); }