diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index 1888940b645a30a29c0b65fdb931e3597a007243..68f7af7d4af3ae76ed125610af855918e2bdda8f 100755 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -56,6 +56,7 @@ namespace CodeImp.DoomBuilder.Rendering private Matrix view2d; private Matrix world; private Vector3D cameraposition; + private Vector3D cameravector; private int shaderpass; // Window size @@ -257,8 +258,9 @@ namespace CodeImp.DoomBuilder.Rendering { // Calculate delta vector cameraposition = pos; - Vector3D delta = lookat - pos; - float anglexy = delta.GetAngleXY(); + Vector3D delta = lookat - pos; + cameravector = delta.GetNormal(); + float anglexy = delta.GetAngleXY(); float anglez = delta.GetAngleZ(); // Create frustum @@ -504,22 +506,45 @@ namespace CodeImp.DoomBuilder.Rendering visualvertices = null; } - //mxd - private void UpdateLights() + // [ZZ] black renderer magic here. + // todo maybe implement proper frustum culling eventually? + // Frustum2D.IntersectCircle doesn't seem to work here. + private bool CullLight(VisualThing t) + { + Vector3D lightToCamera = (cameraposition - t.CenterV3D).GetNormal(); + double angdiff = Vector3D.DotProduct(lightToCamera, cameravector); + if (angdiff <= 0) + return true; // light in front of the camera. it's not negative because I don't want to calculate things twice and need the vector to point at camera. + // otherwise check light size: large lights might have center on the back, but radius in front of the camera. + Vector3D lightToCameraWithRadius = (cameraposition - (t.CenterV3D + lightToCamera * t.LightRadius)).GetNormal(); + double angdiffWithRadius = Vector3D.DotProduct(lightToCameraWithRadius, cameravector); + if (angdiffWithRadius <= 0) + return true; // light's radius extension is in front of the camera. + return false; + } + + //mxd + private void UpdateLights() { - if(lightthings.Count > General.Settings.GZMaxDynamicLights) - { - // Calculate distance to camera - foreach(VisualThing t in lightthings) t.CalculateCameraDistance(cameraposition); - - // Sort by it, closer ones first - lightthings.Sort((t1, t2) => Math.Sign(t1.CameraDistance - t2.CameraDistance)); - - // Gather the closest - List<VisualThing> tl = new List<VisualThing>(General.Settings.GZMaxDynamicLights); - for(int i = 0; i < General.Settings.GZMaxDynamicLights; i++) tl.Add(lightthings[i]); - lightthings = tl; - } + // Calculate distance to camera + foreach(VisualThing t in lightthings) t.CalculateCameraDistance(cameraposition); + + // Sort by it, closer ones first + lightthings.Sort((t1, t2) => Math.Sign(t1.CameraDistance - t2.CameraDistance)); + + // Gather the closest + List<VisualThing> tl = new List<VisualThing>(lightthings.Count); + // Break on either end of things of max dynamic lights reached + for (int i = 0; i < lightthings.Count && tl.Count < General.Settings.GZMaxDynamicLights; i++) + { + // Make sure we can see this light at all + if (!CullLight(lightthings[i])) + continue; + tl.Add(lightthings[i]); + } + + // Update the array + lightthings = tl; // Sort things by light render style lightthings.Sort((t1, t2) => Math.Sign(t1.LightRenderStyle - t2.LightRenderStyle)); @@ -1374,7 +1399,7 @@ namespace CodeImp.DoomBuilder.Rendering } //negative lights - if(lightOffsets[3] > 0) + if(lightOffsets[3] > 0) { count += lightOffsets[3]; graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract); @@ -1728,13 +1753,13 @@ namespace CodeImp.DoomBuilder.Rendering public void AddThingGeometry(VisualThing t) { //mxd. Gather lights - if(General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && t.LightType != DynamicLightType.NONE) + if (General.Settings.GZDrawLightsMode != LightRenderMode.NONE && !fullbrightness && t.LightType != DynamicLightType.NONE) { t.UpdateLightRadius(); - if(t.LightRadius > 0) + if (t.LightRadius > 0) { - if(Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1) - t.UpdateBoundingBox(); + if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1) + t.UpdateBoundingBox(); lightthings.Add(t); } }