cómo definir un campo de visión para todo el map de sombra?

Recientemente agregué "Shadow Mapping" en mis juegos de XNA para include sombras. Seguí el bonito y famoso tutorial de "Riemers": http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series3/Shadow_map.php .

Este código funciona bien y puedo ver mi fuente de luz y sombra. Pero el problema es que mi fuente de luz no coincide con el campo de visión que creé. Quiero que la luz cubra todo el map de mi juego. No sé por qué, pero la luz solo afecta a 2-3 cubos de mi map.

ScreenShot : (la emisión de luz ilumina solo 2-3 bloques y no el map completo) enter image description here

Aquí está mi código, creo el fieldOfView para LightviewProjection Matrix:

Vector3 lightDir = new Vector3(10, 52, 10); Vector3 lightPos = new Vector3(2, 52, 2); Matrix lightsView = Matrix.CreateLookAt(lightPos, lightDir ,new Vector3(0, 1, 0)); Matrix lightsProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1f, 20f, 1000f); lightsViewProjectionMatrix = lightsView * lightsProjection; 

Como puede ver, mi nearPlane y FarPlane están configurados en 20f y 100f. Así que no sé por qué la luz se detiene después de 2 cubos. debe ser más grande

Aquí se establece el valor de mi efecto personalizado HLSL en el file de sombreado

  /* SHADOW VALUE */ effectWorld.Parameters["LightDirection"].SetValue(lightDir); effectWorld.Parameters["xLightsWorldViewProjection"].SetValue(Matrix.Identity * .lightsViewProjectionMatrix); effectWorld.Parameters["xWorldViewProjection"].SetValue(Matrix.Identity * arcadia.camera.View * arcadia.camera.Projection); effectWorld.Parameters["xLightPower"].SetValue(1f); effectWorld.Parameters["xAmbient"].SetValue(0.3f); 

Aquí está mi file de efecto de sombreado HLSL personalizado "* .fx"

  // This sample uses a simple Lambert lighting model. float3 LightDirection = normalize(float3(-1, -1, -1)); float3 DiffuseLight = 1.25; float3 AmbientLight = 0.25; uniform const float3 DiffuseColor = 1; uniform const float Alpha = 1; uniform const float3 EmissiveColor = 0; uniform const float3 SpecularColor = 1; uniform const float SpecularPower = 16; uniform const float3 EyePosition; // FOG attribut uniform const float FogEnabled ; uniform const float FogStart ; uniform const float FogEnd ; uniform const float3 FogColor ; float3 cameraPos : CAMERAPOS; texture Texture; sampler Sampler = sampler_state { Texture = (Texture); magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = mirror; AddressV = mirror; }; texture xShadowMap; sampler ShadowMapSampler = sampler_state { Texture = <xShadowMap>; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = clamp; AddressV = clamp; }; /* *************** */ /* SHADOW MAP CODE */ /* *************** */ struct SMapVertexToPixel { float4 Position : POSITION; float4 Position2D : TEXCOORD0; }; struct SMapPixelToFrame { float4 Color : COLOR0; }; struct SSceneVertexToPixel { float4 Position : POSITION; float4 Pos2DAsSeenByLight : TEXCOORD0; float2 TexCoords : TEXCOORD1; float3 Normal : TEXCOORD2; float4 Position3D : TEXCOORD3; }; struct SScenePixelToFrame { float4 Color : COLOR0; }; float DotProduct(float3 lightPos, float3 pos3D, float3 normal) { float3 lightDir = normalize(pos3D - lightPos); return dot(-lightDir, normal); } SSceneVertexToPixel ShadowedSceneVertexShader(float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL) { SSceneVertexToPixel Output = (SSceneVertexToPixel)0; Output.Position = mul(inPos, xWorldViewProjection); Output.Pos2DAsSeenByLight = mul(inPos, xLightsWorldViewProjection); Output.Normal = normalize(mul(inNormal, (float3x3)World)); Output.Position3D = mul(inPos, World); Output.TexCoords = inTexCoords; return Output; } SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn) { SScenePixelToFrame Output = (SScenePixelToFrame)0; float2 ProjectedTexCoords; ProjectedTexCoords[0] = PSIn.Pos2DAsSeenByLight.x / PSIn.Pos2DAsSeenByLight.w / 2.0f + 0.5f; ProjectedTexCoords[1] = -PSIn.Pos2DAsSeenByLight.y / PSIn.Pos2DAsSeenByLight.w / 2.0f + 0.5f; float diffuseLightingFactor = 0; if ((saturate(ProjectedTexCoords).x == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords).y == ProjectedTexCoords.y)) { float depthStonetworkingInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).r; float realDistance = PSIn.Pos2DAsSeenByLight.z / PSIn.Pos2DAsSeenByLight.w; if ((realDistance - 1.0f / 100.0f) <= depthStonetworkingInShadowMap) { diffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal); diffuseLightingFactor = saturate(diffuseLightingFactor); diffuseLightingFactor *= xLightPower; } } float4 baseColor = tex2D(Sampler, PSIn.TexCoords); Output.Color = baseColor*(diffuseLightingFactor + xAmbient); return Output; } SMapVertexToPixel ShadowMapVertexShader(float4 inPos : POSITION) { SMapVertexToPixel Output = (SMapVertexToPixel)0; Output.Position = mul(inPos, xLightsWorldViewProjection); Output.Position2D = Output.Position; return Output; } SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn) { SMapPixelToFrame Output = (SMapPixelToFrame)0; Output.Color = PSIn.Position2D.z / PSIn.Position2D.w; return Output; } /* ******************* */ /* END SHADOW MAP CODE */ /* ******************* */ / For rendering without instancing. technique ShadowMap { pass Pass0 { VertexShader = compile vs_2_0 ShadowMapVertexShader(); PixelShader = compile ps_2_0 ShadowMapPixelShader(); } } technique ShadowedScene { /* pass Pass0 { VertexShader = compile vs_2_0 VSBasicTx(); PixelShader = compile ps_2_0 PSBasicTx(); } */ pass Pass1 { VertexShader = compile vs_2_0 ShadowedSceneVertexShader(); PixelShader = compile ps_2_0 ShadowedScenePixelShader(); } } technique SimpleFog { pass Pass0 { VertexShader = compile vs_2_0 VSBasicTx(); PixelShader = compile ps_2_0 PSBasicTx(); } } 

Función de dibujo:

 public void Draw(GameTime gameTime) { GraphicsDevice.SetRenderTarget(shadowMapRender); GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Microsoft.Xna.Framework.Color.Black, 1.0f, 0); // "ShadowMap" as technique param DrawWorld("ShadowMap"); GraphicsDevice.SetRenderTarget(null); shadowMap = (Texture2D)shadowMapRender; GraphicsDevice.SetRenderTarget(null); GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Microsoft.Xna.Framework.Color.Black, 1.0f, 0); // "ShadowedScene" as technique param DrawWorld("ShadowedScene"); shadowMap = null; } 

Edité mi file fx, para mostrarle solo información y funciones sobre la sombra 😉

ACTUALIZACIÓN: lo intenté con una matriz ortográfica como nos aconsejó, pero todavía no funciona. no puedo ver la luz y la sombra

 Vector3 lightDir = new Vector3(10, 52, 10); Vector3 lightPos = new Vector3(2, 52, 2); Matrix lightViewMatrix = Matrix.CreateLookAt(lightPos, lightDir, Vector3.Up); float minX = 0, maxX = 1000; float minY = 50, maxY = 100; float minZ = 0, maxZ = 1000; Matrix lightProjectionMatrix = Matrix.CreateOrthographicOffCenter(minX, maxX, minY, maxY, minZ, maxZ); lightsViewProjectionMatrix = lightViewMatrix * lightProjectionMatrix; 

Los maps de sombras en perspectiva como ese no suelen usarse para sombrear toda la escena, sino para una sola lámpara o linterna.
Si desea sombrear toda la escena, probablemente no desee utilizar maps de sombras persistentes, sino ortogonales (supongo que desea sombras del sol). Cuando está creando una matriz otográfica ( MSDN ), especifica sus dimensiones, como un cubo (porque proyectará todo en ese cubo). Supongo que es fácil calcular su tamaño requerido. Es incluso mejor para la luz del sol por otra razón, porque las sombras generadas a partir de eso se verán como si hubieran sido generadas a partir de una fuente de luz que está infinitamente lejos (o tan lejos como el sol).

Si sombreas toda una escena como esa, probablemente un map de sombra no sea suficiente (o eficiente), así que cuando lo tengas trabajando con uno, entonces deberías mirar maps en sombra en cascada.