Exemple #1
0
        float WorldLightDistanceFalloff(worldlight_t light, Vector3 delta, bool noRadiusCheck)
        {
            float falloff = 0.0f;
            switch (light.Type)
            {
                case EmitType.SURFACE:
                    // Cull out stuff that's too far
                    if (light.radius != 0)
                    {
                        if (Vector3.Dot(delta, delta) > (light.radius * light.radius))
                            return 0.0f;
                    }

                    return InvRSquared(delta);
                case EmitType.SKYLIGHT:
                    return 1.0f;
                case EmitType.QUAKELIGHT:
                    // X - r;
                    falloff = light.Linear_Attn - (float)Math.Sqrt(Vector3.Dot(delta, delta));
                    if (falloff < 0f)
                        return 0f;

                    return falloff;
                case EmitType.SKYAMBIENT:
                    return 1.0f;
                case EmitType.SPOTLIGHT:
                case EmitType.POINT:    // directional & positional
                    float dist2 = Vector3.Dot(delta, delta);
                    float dist = (float)Math.Sqrt(dist2);

                    // Cull out stuff that's too far
                    if (!noRadiusCheck && (light.radius != 0) && (dist > light.radius))
                        return 0f;

                    return 1f / (light.Constant_Attn + light.Linear_Attn * dist + light.Quadratic_Attn * dist2);
            }
            return 1f;
        }
Exemple #2
0
        float WorldLightAngle(worldlight_t wl, Vector3 lnormal, Vector3 snormal, Vector3 delta)
        {
            float dot = 0, dot2 = 0, ratio = 0;
            switch (wl.Type)
            {
                case EmitType.SURFACE:
                    dot = Vector3.Dot(snormal, delta);
                    if (dot < 0)
                        return 0;

                    dot2 = -Vector3.Dot(delta, lnormal);
                    if (dot2 <= 0.1f / 10)
                        return 0;   // behind light surface

                    return dot * dot2;
                case EmitType.POINT:
                    dot = Vector3.Dot(snormal, delta);
                    if (dot < 0)
                        return 0;
                    return dot;
                case EmitType.SPOTLIGHT:
                    dot = Vector3.Dot(snormal, delta);
                    if (dot < 0)
                        return 0;

                    dot2 = -Vector3.Dot(delta, lnormal);
                    if (dot2 <= wl.stopdot2)
                        return 0;   // outside light cone

                    ratio = dot;
                    if (dot2 >= wl.stopdot)
                        return ratio;   // inside inner cone

                    if ((wl.exponent == 1 || wl.exponent == 0))
                    {
                        ratio *= (dot2 - wl.stopdot2) / (wl.stopdot - wl.stopdot2);
                    }
                    else
                    {
                        ratio *= (float)Math.Pow((dot2 - wl.stopdot2) / (wl.stopdot - wl.stopdot2), wl.exponent);
                    }
                    return ratio;
                case EmitType.SKYLIGHT:
                    dot2 = -Vector3.Dot(snormal, lnormal);
                    if (dot2 < 0)
                        return 0;
                    return dot2;
                case EmitType.QUAKELIGHT:
                    // linear falloff
                    dot = Vector3.Dot(snormal, delta);
                    if (dot < 0)
                        return 0;
                    return dot;
                case EmitType.SKYAMBIENT:
                    // not supported
                    return 1;
            }
            return 0;
        }
Exemple #3
0
 void ComputeAmbientFromSurface(int surfid, worldlight_t skyLight,ref Vector3 color)
 {
     if (surfid != -1)
     {
         // If we hit the sky, use the sky ambient
         if ((world.faces_t[surfid].face.texinfo.flags & SurfFlags.SURF_SKY) == SurfFlags.SURF_SKY)
         {
             if (skyLight != null)   // add in sky ambient
                 color = skyLight.Intensity;
         }
         else
         {
             Vector3 reflectivity = world.faces_t[surfid].face.texinfo.texdata_t.reflectivity;
             color.X *= reflectivity.X;
             color.Y *= reflectivity.Y;
             color.Z *= reflectivity.Z;
         }
     }
 }
Exemple #4
0
        //-----------------------------------------------------------------------------
        // This method returns the effective intensity of a light as seen from
        // a particular point. PVS is used to speed up the task.
        //-----------------------------------------------------------------------------
        float LightIntensityAndDirectionAtpoint(worldlight_t light, Vector3 mid, int flags, ref Vector3 direction)
        {
            // Special case lights
            switch (light.Type)
            {
                case EmitType.SKYLIGHT:
                    // There can be more than one skylight, but we should only
                    // ever be affected by one of them (multiple ones are created from
                    // a single light in vrad)

                    // check to see if you can hit the sky texture
                    Vector3 end = ViewParams.VectorMA(mid, -65500, light.Normal);
                    trace_t trace = ClipMap.Instance.Box_Trace(mid, end, Vector3.Zero, Vector3.Zero, 0, (int)(brushflags.CONTENTS_SOLID | brushflags.CONTENTS_MOVEABLE | brushflags.CONTENTS_SLIME | brushflags.CONTENTS_OPAQUE));

                    // Here, we didn't hit the sky, so we must be in shadow
                    if (((SurfFlags)trace.surfaceFlags & SurfFlags.SURF_SKY) != SurfFlags.SURF_SKY)
                        return 0.0f;

                    // fudge delta and dist for skylights
                    direction.X = direction.Y = direction.Z = 0;
                    return 1.0f;
                case EmitType.SKYAMBIENT:
                    // always ignore these
                    return 0.0f;
            }
            // all other lights

            // check distance
            direction = light.Origin - mid;
            float ratio = WorldLightDistanceFalloff(light, direction, (flags & 2) != 0);

            // Add in light style component
            //ratio *= light.Style;

            // Early out for really low-intensity lights
            // That way we don't need to ray-cast or normalize
            float intensity = Math.Max(light.Intensity[0], light.Intensity[1]);
            intensity = Math.Max(intensity, light.Intensity[2]);

            // This is about 1/256
            if (intensity * ratio < 1f / 256f)
                return 0.0f;

            float dist = direction.Length();
            direction.Normalize();

            if ((flags & 1) == 1) // LIGHT_NO_OCCLUSION_CHECK
                return ratio;

            trace_t pm = ClipMap.Instance.Box_Trace(mid, light.Origin, Vector3.Zero, Vector3.Zero, 0, 0x1 | 0x40);

            // hack
            if ((1f - pm.fraction) * dist > 8)
                return 0;

            return ratio;
        }
Exemple #5
0
        static void LoadWorldLights(BinaryReader br, Header header)
        {
            br.BaseStream.Seek(header.lumps[15].fileofs, SeekOrigin.Begin);
            int numWorldlights = header.lumps[15].filelen / 88;
            if (header.lumps[15].filelen % 88 != 0)
                Common.Instance.WriteLine("LoadWorldLights: WARNING: Funny lump size");
            worldlight_t[] lights = new worldlight_t[numWorldlights];
            for (int i = 0; i < numWorldlights; i++)
            {
                worldlight_t light = new worldlight_t();
                light.Origin = new Vector3(br.ReadSingle(),br.ReadSingle(),br.ReadSingle());
                light.Intensity = new Vector3(br.ReadSingle(),br.ReadSingle(),br.ReadSingle());
                light.Normal = new Vector3(br.ReadSingle(),br.ReadSingle(),br.ReadSingle());  // for surfaces and spotlights
                light.Cluster = br.ReadInt32();
                light.Type = (EmitType)br.ReadInt32();
                light.Style = br.ReadInt32();
                light.stopdot = br.ReadSingle();   // start of penumbra for emit_spotlight
                light.stopdot2 = br.ReadSingle();  // end of penumbra for emit_spotlight
                light.exponent = br.ReadSingle();
                light.radius = br.ReadSingle();    // cutoff distance
                // falloff for emit_spotlight + emit_point:
                // 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2)
                light.Constant_Attn = br.ReadSingle();
                light.Linear_Attn = br.ReadSingle();
                light.Quadratic_Attn = br.ReadSingle();
                light.Flags = br.ReadInt32();
                light.Texinfo = br.ReadInt32();
                light.Owner = br.ReadInt32();   // entity that this light it relative to

                // Fixup for backward compatability
                if (light.Type == EmitType.SPOTLIGHT)
                {
                    if (light.Quadratic_Attn == 0.0f && light.Linear_Attn == 0.0f && light.Constant_Attn == 0.0f)
                        light.Quadratic_Attn = 1.0f;
                    if (light.exponent == 0.0f)
                        light.exponent = 1.0f;
                }
                else if (light.Type == EmitType.POINT)
                {
                    // To match earlier lighting, use quadratic...
                    if (light.Quadratic_Attn == 0.0f && light.Linear_Attn == 0.0f && light.Constant_Attn == 0.0f)
                        light.Quadratic_Attn = 1.0f;
                }

                if (light.radius < 1)
                    light.radius = 0;

                lights[i] = light;
            }
            world.worldlights = lights;
        }