예제 #1
0
        /// <summary>
        /// Get diffuse color and specular for the hit point with a specific light
        /// </summary>
        /// <param name="light"></param>
        /// <param name="ray"></param>
        /// <param name="hit"></param>
        /// <param name="specular"></param>
        /// <param name="debug"></param>
        /// <returns></returns>
        protected Vector3 illuminateBy(Vector3 ppos, Light light, Ray ray, RayHit hit, ref Vector3 specular, bool debug)
        {
            // Calclulate if we are within light range
            var   light_vec = ppos - hit.Position;
            float dist_sq   = Vector3.Dot(light_vec, light_vec);
            float intens_sq = light.LightCache.IntensitySq;

            if (dist_sq >= intens_sq * Constants.LIGHT_DECAY)
            {
                return(Vector3.Zero);
            }

            // Create a shadow ray
            var dist = (float)Math.Sqrt(dist_sq);

            light_vec = light_vec / dist;
            var shadow_ray = new Ray(hit.Position + (light_vec * Constants.EPSILON), light_vec);

            var tmp = RayHit.Default();

            foreach (var o in World.Objects)
            {
                if (o.Intersect(shadow_ray, ref tmp) && tmp.T < dist)
                {
                    if (debug)
                    {
                        DebugData.ShadowRaysOccluded.Add(new Tuple <Ray, RayHit>(shadow_ray, tmp));
                    }
                    return(new Vector3());
                }
            }

            // Diffuse
            var materialColor = hit.Obj.Material.Texture == null
                ? hit.Obj.Material.Diffuse
                : hit.Obj.Material.Texture.GetColor(hit.Obj.GetUV(hit));
            var color = materialColor * Math.Max(0.0f, Vector3.Dot(hit.Normal, light_vec));

            // Inverse square law
            var light_powah = light.Intensity / (Constants.PI4 * dist_sq);

            light_powah *= light.AngleEnergy(light_vec.Normalized());

            // Specular will be used separately
            if (hit.Obj.Material.IsGlossy)
            {
                var hardness = Math.Max(.0f, Vector3.Dot(-ray.Direction, QuickMaths.Reflect(-light_vec, hit.Normal)));
                specular += light.Colour * light_powah * hit.Obj.Material.Specular *
                            (float)Math.Pow(hardness, hit.Obj.Material.Shinyness);
            }

            if (debug)
            {
                DebugData.ShadowRays.Add(new Tuple <Ray, Vector3>(shadow_ray, ppos));
            }
            return(light.Colour * color * light_powah);
        }