Fixed: lights behind the camera shouldn't count towards the max lights counter

This commit is contained in:
ZZYZX 2017-02-09 14:28:54 +02:00
parent 2b69b38e18
commit 3d69ec12d4

View file

@ -56,6 +56,7 @@ namespace CodeImp.DoomBuilder.Rendering
private Matrix view2d; private Matrix view2d;
private Matrix world; private Matrix world;
private Vector3D cameraposition; private Vector3D cameraposition;
private Vector3D cameravector;
private int shaderpass; private int shaderpass;
// Window size // Window size
@ -257,8 +258,9 @@ namespace CodeImp.DoomBuilder.Rendering
{ {
// Calculate delta vector // Calculate delta vector
cameraposition = pos; cameraposition = pos;
Vector3D delta = lookat - pos; Vector3D delta = lookat - pos;
float anglexy = delta.GetAngleXY(); cameravector = delta.GetNormal();
float anglexy = delta.GetAngleXY();
float anglez = delta.GetAngleZ(); float anglez = delta.GetAngleZ();
// Create frustum // Create frustum
@ -504,22 +506,45 @@ namespace CodeImp.DoomBuilder.Rendering
visualvertices = null; visualvertices = null;
} }
//mxd // [ZZ] black renderer magic here.
private void UpdateLights() // todo maybe implement proper frustum culling eventually?
{ // Frustum2D.IntersectCircle doesn't seem to work here.
if(lightthings.Count > General.Settings.GZMaxDynamicLights) private bool CullLight(VisualThing t)
{ {
// Calculate distance to camera Vector3D lightToCamera = (cameraposition - t.CenterV3D).GetNormal();
foreach(VisualThing t in lightthings) t.CalculateCameraDistance(cameraposition); 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;
}
// Sort by it, closer ones first //mxd
lightthings.Sort((t1, t2) => Math.Sign(t1.CameraDistance - t2.CameraDistance)); private void UpdateLights()
{
// Gather the closest // Calculate distance to camera
List<VisualThing> tl = new List<VisualThing>(General.Settings.GZMaxDynamicLights); foreach(VisualThing t in lightthings) t.CalculateCameraDistance(cameraposition);
for(int i = 0; i < General.Settings.GZMaxDynamicLights; i++) tl.Add(lightthings[i]);
lightthings = tl; // 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 // Sort things by light render style
lightthings.Sort((t1, t2) => Math.Sign(t1.LightRenderStyle - t2.LightRenderStyle)); lightthings.Sort((t1, t2) => Math.Sign(t1.LightRenderStyle - t2.LightRenderStyle));
@ -1374,7 +1399,7 @@ namespace CodeImp.DoomBuilder.Rendering
} }
//negative lights //negative lights
if(lightOffsets[3] > 0) if(lightOffsets[3] > 0)
{ {
count += lightOffsets[3]; count += lightOffsets[3];
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract); graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract);
@ -1728,13 +1753,13 @@ namespace CodeImp.DoomBuilder.Rendering
public void AddThingGeometry(VisualThing t) public void AddThingGeometry(VisualThing t)
{ {
//mxd. Gather lights //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(); t.UpdateLightRadius();
if(t.LightRadius > 0) if (t.LightRadius > 0)
{ {
if(Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1) if (Array.IndexOf(GZBuilder.GZGeneral.GZ_ANIMATED_LIGHT_TYPES, t.LightType) != -1)
t.UpdateBoundingBox(); t.UpdateBoundingBox();
lightthings.Add(t); lightthings.Add(t);
} }
} }