private static void AddSpotLightRenderElement(MyLight light) { float cosAngle = 1 - light.ReflectorConeMaxAngleCos; // Near clip is 5 to prevent cockpit bugs float nearClip = 5; float c = nearClip / cosAngle; // 'a' is "screen size" at near clip (a, c and nearclip makes right triangle) float a = (float)Math.Sqrt(c * c - nearClip * nearClip); if (nearClip < light.ReflectorRange) { Matrix lightView = Matrix.CreateLookAt(light.Position, light.Position + light.ReflectorDirection, light.ReflectorUp); float distanceSquared = Vector3.DistanceSquared(MyCamera.Position, light.Position); bool drawShadows = DrawPlayerLightShadow || (PlayerLight != light); drawShadows &= distanceSquared < light.ShadowDistance * light.ShadowDistance * MyRenderConstants.RenderQualityProfile.SpotShadowsMaxDistanceMultiplier; //drawShadows &= distanceSquared < 200*200 * MyRenderConstants.RenderQualityProfile.SpotShadowsMaxDistanceMultiplier; Matrix lightProjection = Matrix.CreatePerspectiveOffCenter(-a, a, -a, a, nearClip, light.ReflectorRange); bool renderShadows = EnableSpotShadows && MyRender.CurrentRenderSetup.EnableSmallLightShadows.Value && drawShadows; MyLightRenderElement lightElement = null; lightElement = m_spotLightsPool.Allocate(true); Debug.Assert(lightElement != null, "Out of lights, increase pool"); if (lightElement != null) { lightElement.Light = light; lightElement.World = light.SpotWorld; lightElement.View = lightView; lightElement.Projection = lightProjection; lightElement.RenderShadows = renderShadows; lightElement.BoundingBox = light.SpotBoundingBox; lightElement.UseReflectorTexture = (light.LightOwner == MyLight.LightOwnerEnum.SmallShip); if (renderShadows) { Matrix lightViewProjectionShadow = m_spotShadowRenderer.CreateViewProjectionMatrix(lightView, a, nearClip, light.ReflectorRange); lightElement.ShadowLightViewProjection = lightViewProjectionShadow; } m_spotLightRenderElements.Add(lightElement); } } }
static void RenderSpotLight(MyLightRenderElement lightElement, MyEffectPointLight effectPointLight) { MyRenderLight light = lightElement.Light; //Matrix lightViewProjectionShadow = Matrix.Identity; // Always cull clockwise (render inner parts of object), depth test is done in PS using light radius and cone angle RasterizerState.CullClockwise.Apply(); DepthStencilState.None.Apply(); //m_device.BlendState = BlendState.Additive; //Need to use max because of overshinning places where multiple lights shine MyStateObjects.Light_Combination_BlendState.Apply(); if (lightElement.RenderShadows && lightElement.ShadowMap != null) { m_spotShadowRenderer.SetupSpotShadowBaseEffect(effectPointLight, lightElement.ShadowLightViewProjectionAtZero, lightElement.ShadowMap); } effectPointLight.SetNearSlopeBiasDistance(0); effectPointLight.SetLightPosition((Vector3)(light.Position - MyRenderCamera.Position)); effectPointLight.SetLightIntensity(light.Intensity); effectPointLight.SetSpecularLightColor(light.SpecularColor); effectPointLight.SetFalloff(light.Falloff); effectPointLight.SetLightViewProjection((Matrix)(lightElement.ViewAtZero * lightElement.Projection)); effectPointLight.SetReflectorDirection(light.ReflectorDirection); effectPointLight.SetReflectorConeMaxAngleCos(1 - light.ReflectorConeMaxAngleCos); effectPointLight.SetReflectorColor(light.ReflectorColor); effectPointLight.SetReflectorRange(light.ReflectorRange); effectPointLight.SetReflectorIntensity(light.ReflectorIntensity); effectPointLight.SetReflectorTexture(light.ReflectorTexture); effectPointLight.SetReflectorFalloff(light.ReflectorFalloff); if (lightElement.RenderShadows) { effectPointLight.SetTechnique(effectPointLight.SpotShadowTechnique); } else { effectPointLight.SetTechnique(effectPointLight.SpotTechnique); } MyDebugDraw.DrawConeForLight(effectPointLight, lightElement.World); }
static void RenderSpotLight(MyLightRenderElement lightElement, MyEffectPointLight effectPointLight) { MyLight light = lightElement.Light; Matrix lightViewProjectionShadow = Matrix.Identity; // Always cull clockwise (render inner parts of object), depth test is done in PS using light radius and cone angle RasterizerState.CullClockwise.Apply(); DepthStencilState.None.Apply(); //m_device.BlendState = BlendState.Additive; //Need to use max because of overshinning places where multiple lights shine MyStateObjects.Light_Combination_BlendState.Apply(); if (lightElement.RenderShadows && lightElement.ShadowMap != null) { m_spotShadowRenderer.SetupSpotShadowBaseEffect(effectPointLight, lightElement.ShadowLightViewProjection, lightElement.ShadowMap); } effectPointLight.SetNearSlopeBiasDistance(4); effectPointLight.SetLightPosition(light.Position); effectPointLight.SetLightIntensity(light.Intensity); effectPointLight.SetSpecularLightColor(light.SpecularColor); effectPointLight.SetFalloff(light.Falloff); effectPointLight.SetLightViewProjection(lightElement.View * lightElement.Projection); effectPointLight.SetReflectorDirection(light.ReflectorDirection); effectPointLight.SetReflectorConeMaxAngleCos(1 - light.ReflectorConeMaxAngleCos); effectPointLight.SetReflectorColor(light.ReflectorColor); effectPointLight.SetReflectorRange(light.ReflectorRange); effectPointLight.SetReflectorIntensity(light.ReflectorIntensity); effectPointLight.SetReflectorTexture(light.ReflectorTexture); effectPointLight.SetReflectorFalloff(light.ReflectorFalloff); if (lightElement.RenderShadows) effectPointLight.SetTechnique(effectPointLight.DefaultSpotShadowTechnique); else effectPointLight.SetTechnique(effectPointLight.DefaultSpotTechnique); MySimpleObjectDraw.DrawConeForLight(effectPointLight, lightElement.World); }
private static void AddSpotLightRenderElement(MyRenderLight light) { float cosAngle = 1 - light.ReflectorConeMaxAngleCos; // Near clip is 5 to prevent cockpit bugs float nearClip = 0.5f; float c = nearClip / cosAngle; // 'a' is "screen size" at near clip (a, c and nearclip makes right triangle) float a = (float)Math.Sqrt(c * c - nearClip * nearClip); if (nearClip < light.ReflectorRange) { MatrixD lightView = MatrixD.CreateLookAt(light.Position, light.Position + light.ReflectorDirection * light.ReflectorRange, (Vector3D)light.ReflectorUp); MatrixD lightViewAtZero = MatrixD.CreateLookAt(light.Position - MyRenderCamera.Position, light.Position + light.ReflectorDirection * light.ReflectorRange - MyRenderCamera.Position, (Vector3D)light.ReflectorUp); var distanceSquared = (MyRenderCamera.Position - light.Position).LengthSquared(); bool drawShadows = light.CastShadows; drawShadows &= distanceSquared < light.ShadowDistance * light.ShadowDistance * MyRenderConstants.RenderQualityProfile.SpotShadowsMaxDistanceMultiplier; var lightProjection = Matrix.CreatePerspectiveOffCenter(-a, a, -a, a, nearClip, light.ReflectorRange); bool renderShadows = Settings.EnableSpotShadows && MyRender.CurrentRenderSetup.EnableSmallLightShadows.Value && drawShadows; MyLightRenderElement lightElement = null; lightElement = m_spotLightsPool.Allocate(true); Debug.Assert(lightElement != null, "Out of lights, increase pool"); if (lightElement != null) { MatrixD spotWorld = light.SpotWorld; spotWorld.Translation = light.SpotWorld.Translation - MyRenderCamera.Position; lightElement.Light = light; lightElement.World = spotWorld; lightElement.ViewAtZero = lightViewAtZero; lightElement.Projection = lightProjection; lightElement.RenderShadows = renderShadows; if ((light.SpotQuery != null) && (light.SpotQueryState == QueryState.CheckOcc) && (light.SpotQuery.IsComplete)) { light.QueryPixels = light.SpotQuery.PixelCount; if (light.QueryPixels < 0) //ATI { light.QueryPixels = 0; } light.SpotQueryState = QueryState.WaitOcc; } //lightElement.UseReflectorTexture = (light.LightOwner == MyLight.LightOwnerEnum.SmallShip); if (renderShadows) { var lightViewProjectionShadow = m_spotShadowRenderer.CreateViewProjectionMatrix(lightView, a, nearClip, light.ReflectorRange); var lightViewProjectionShadowAtZero = m_spotShadowRenderer.CreateViewProjectionMatrix(lightViewAtZero, a, nearClip, light.ReflectorRange); lightElement.ShadowLightViewProjection = lightViewProjectionShadow; lightElement.ShadowLightViewProjectionAtZero = lightViewProjectionShadowAtZero; } m_spotLightRenderElements.Add(lightElement); } } }