相机截锥计算出错了

我正在计算一个点光源的6个方向的视图/投影/视锥体,而且我沿着Y轴指向视图时遇到了麻烦。 我们的游戏使用了一个右手的Y-up系统。 对于其他4个方向,我使用(0,1,0)作为向上vector创建LookAtmatrix。 显然,当沿着Y轴观察时,这是不起作用的,因此对于那些我使用向上( – 1,0,0)向量为-Y和(1,0,0)为+ Y的向量。 视图matrix似乎正确地出来了(并且投影matrix总是保持不变),但是边界的平截头体是绝对错误的。 任何人都可以看到我做错了什么?

这是我正在使用的代码:

camera.Projection = Matrix.PerspectiveFovRH((float)Math.PI / 2, ShadowMapSize / (float)ShadowMapSize, 1, 5); for(var i = 0; i < 6; i++) { var renderTargetView = shadowMap.GetRenderTargetView((TextureCubeFace)i); var up = DetermineLightUp((TextureCubeFace) i); var forward = DirectionToVector((TextureCubeFace) i); camera.View = Matrix.LookAtRH(this.Position, this.Position + forward, up); camera.BoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); } private static Vector3 DirectionToVector(TextureCubeFace direction) { switch (direction) { case TextureCubeFace.NegativeX: return -Vector3.UnitX; case TextureCubeFace.NegativeY: return -Vector3.UnitY; case TextureCubeFace.NegativeZ: return -Vector3.UnitZ; case TextureCubeFace.PositiveX: return Vector3.UnitX; case TextureCubeFace.PositiveY: return Vector3.UnitY; case TextureCubeFace.PositiveZ: return Vector3.UnitZ; default: throw new ArgumentOutOfRangeException("direction"); } } private static Vector3 DetermineLightUp(TextureCubeFace direction) { switch (direction) { case TextureCubeFace.NegativeY: return -Vector3.UnitX; case TextureCubeFace.PositiveY: return Vector3.UnitX; default: return Vector3.UnitY; } } 

编辑:这是什么值出来的Pos​​itiveX和PositiveY方向:

常量:

 Position = {X:0 Y:360 Z:0} camera.Projection = [M11:0.9999999 M12:0 M13:0 M14:0] [M21:0 M22:0.9999999 M23:0 M24:0] [M31:0 M32:0 M33:-1.25 M34:-1] [M41:0 M42:0 M43:-1.25 M44:0] 

PositiveX:

 up = {X:0 Y:1 Z:0} target = {X:1 Y:360 Z:0} camera.View = [M11:0 M12:0 M13:-1 M14:0] [M21:0 M22:1 M23:0 M24:0] [M31:1 M32:0 M33:0 M34:0] [M41:0 M42:-360 M43:0 M44:1] camera.BoundingFrustum: Matrix = [M11:0 M12:0 M13:1.25 M14:1] [M21:0 M22:0.9999999 M23:0 M24:0] [M31:0.9999999 M32:0 M33:0 M34:0] [M41:0 M42:-360 M43:-1.25 M44:0] Top = {A:0.7071068 B:-0.7071068 C:0 D:254.5584} Bottom = {A:0.7071068 B:0.7071068 C:0 D:-254.5584} Left = {A:0.7071068 B:0 C:0.7071068 D:0} Right = {A:0.7071068 B:0 C:-0.7071068 D:0} Near = {A:1 B:0 C:0 D:-1} Far = {A:-1 B:0 C:0 D:5} 

PositiveY:

 up = {X:0 Y:0 Z:-1} target = {X:0 Y:361 Z:0} camera.View = [M11:-1 M12:0 M13:0 M14:0] [M21:0 M22:0 M23:-1 M24:0] [M31:0 M32:-1 M33:0 M34:0] [M41:0 M42:0 M43:360 M44:1] camera.BoundingFrustum: Matrix = [M11:-0.9999999 M12:0 M13:0 M14:0] [M21:0 M22:0 M23:1.25 M24:1] [M31:0 M32:-0.9999999 M33:0 M34:0] [M41:0 M42:0 M43:-451.25 M44:-360] Top = {A:0 B:0.7071068 C:0.7071068 D:-254.5585} Bottom = {A:0 B:0.7071068 C:-0.7071068 D:-254.5585} Left = {A:-0.7071068 B:0.7071068 C:0 D:-254.5585} Right = {A:0.7071068 B:0.7071068 C:0 D:-254.5585} Near = {A:0 B:1 C:0 D:-361} Far = {A:0 B:-1 C:0 D:365} 

当我使用生成的BoundingFrustum来剔除区域以外的区域时,结果如下:

 Pass PositiveX: Drew 3 regions Pass NegativeX: Drew 6 regions Pass PositiveY: Drew 400 regions Pass NegativeY: Drew 36 regions Pass PositiveZ: Drew 3 regions Pass NegativeZ: Drew 6 regions 

只有400个地区可以画画,而灯光就在他们的中心。 正如您所看到的,PositiveY方向正在绘制每个区域。 随着透视matrix的近/远平面设置得如此之小,单个平截头体不可能包含每一个区域。

这不是你的问题的直接答案,但可能是一个可能的select,有一些额外的好处。

你似乎试图生成一个平截头体边框,所以你可以做一些平截头体剔除,然后生成立方体阴影贴图的每个面。 如果要切换到使用双抛物面阴影贴图 ,只需使用2个渲染调用来生成阴影贴图而不是6,就可以获得性能提升。

另一个与问题更为相关的好处是,扑杀是一个检测对象是在后面,在前面还是与划分双抛物面阴影图的两个半球的平面相交的过程。

根据MSDN文档,BoundingFrustum构造函数仅使用左手投影matrix:

http://msdn.microsoft.com/en-us/library/windows/desktop/hh855905(v=vs.85).aspx