我刚刚开始使用XNA,我确信我错过了很简单的东西。我有一架四轮飞机,我画的是地面。在这个平面上,我包裹了一个2D纹理。纹理看起来很近,但是当我移动相机时,我看到整个地方都有一堆白色的文物。当我靠近他们时,他们消失了。我猜这是一个抽样问题或类似的东西,但我被卡住了。
首先,我创建了一个QuadDrawer类来为我绘制平面。它来自DrawableGameComponent。
QuadDrawer:
class QuadDrawer : DrawableGameComponent
{
private string _textureName;
private Texture2D _texture;
private BasicEffect _effect;
private float _size = 100;
private VertexPositionNormalTexture[] _vertices;
private int[] _indices;
public QuadDrawer(Game game, float size, string textureName)
: base(game)
{
this._size = size;
this._textureName = textureName;
}
public override void Initialize()
{
BuildVertices();
base.Initialize();
}
private void BuildVertices()
{
_vertices = new VertexPositionNormalTexture[4];
_indices = new int[6];
_vertices[0].Position = Vector3.Forward + Vector3.Left;
_vertices[0].TextureCoordinate = new Vector2(0.0f, 1.0f);
_vertices[1].Position = Vector3.Backward + Vector3.Left;
_vertices[1].TextureCoordinate = new Vector2(0.0f, 0.0f);
_vertices[2].Position = Vector3.Forward + Vector3.Right;
_vertices[2].TextureCoordinate = new Vector2(1.0f, 1.0f);
_vertices[3].Position = Vector3.Backward + Vector3.Right;
_vertices[3].TextureCoordinate = new Vector2(1.0f, 0.0f);
for (int i = 0; i < _vertices.Length; i++)
{
_vertices[i].Normal = Vector3.Up;
_vertices[i].Position *= _size;
_vertices[i].TextureCoordinate *= _size;
}
_indices[5] = 0; _indices[4] = 1; _indices[3] = 2;
_indices[2] = 2; _indices[1] = 1; _indices[0] = 3;
}
protected override void LoadContent()
{
_texture = this.Game.Content.Load<Texture2D>(_textureName);
_effect = new BasicEffect(this.GraphicsDevice);
_effect.EnableDefaultLighting();
_effect.PreferPerPixelLighting = true;
_effect.SpecularColor = new Vector3(0.1f, 0.1f, 0.1f);
_effect.World = Matrix.Identity;
_effect.TextureEnabled = true;
_effect.Texture = _texture;
base.LoadContent();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
public override void Draw(GameTime gameTime)
{
MyGame game = this.Game as MyGame;
GraphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
_effect.View = game.Camera.ViewMatrix;
_effect.Projection = game.Camera.ProjectionMatrix;
foreach (EffectPass pass in _effect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, _vertices, 0, 4, _indices, 0, 2);
}
base.Draw(gameTime);
}
}
从我的主Game类的Initialize()方法中,我只是实例化这个对象并传入我想要使用的GameObject,Size和Texture名称:
_floor = new QuadDrawer(this, 100.0f, "Textures/checker");
this.Components.Add(_floor);
一旦将对象添加到我的Components集合中,我的QuadDrawer的Draw方法就会被调用,所有这些都应该是好的。这是我所看到的图像。请注意,这应该是纯灰色,浅色线以网格图案运行。当您在相机周围移动相机时,白色瑕疵似乎会移动,但当您靠近时会消失。
这是显示白色文物的图片:
这是近距离显示它应该如何显示:
这是另一张图片,展示了远距离有多糟糕:
这是从远处看它应该是什么样的:
图片不是最好的,但你可以看到我在说什么。当相机移动时,它变得非常糟糕。我已经看到在其他地方使用这种纹理,它工作正常。知道它可能是什么吗?
如果您需要,我很乐意提供更多信息。
谢谢,
-Scott
答案 0 :(得分:6)
首先,您需要为纹理启用mipmap 。如果它只是一个独立的资产,您可以在解决方案资源管理器中选择它,按F4进入属性,展开“内容处理器”节点并将“生成Mipmap”设置为true。
This article by Shawn Hargreaves explains why。看看这篇文章中这两张图片之间的区别:
(看起来很像你的示例图片,不是吗?)
然后,如果你要以这样的倾斜角度观看,你需要启用各向异性过滤(Layoric在他的回答中解释了如何)。来自wikipedia的图像说明了各向异性过滤的用途 - 注意它是如何水平地“钝化”背景(由mipmap引起的)。
http://upload.wikimedia.org/wikipedia/en/c/c0/Anisotropic_compare.png
答案 1 :(得分:2)
它看起来像是一个各向异性过滤问题。我注意到你确实使用了GraphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;
。我建议你看看Shawn Hargreaves article on the topic,特别是以下几行。
device.SamplerStates[0].MinFilter = TextureFilter.Anisotropic;
device.SamplerStates[0].MagFilter = TextureFilter.Linear;
device.SamplerStates[0].MipFilter = TextureFilter.Linear;
device.SamplerStates[0].MaxAnisotropy = <n>;
此外,
确保在正确的时间设置代码,因为Effect.Begin
将重置这些过滤器设置。另一个帮助的代码片段。
// inside draw perform any other required draw code
// Call begin on the basic effect and on the pass to initialize BasicEffect's render settings
basicEffect.Begin();
basicEffect.CurrentTechnique.Passes[0].Begin();
// Set your desired filter settings
GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Anisotropic;
GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Anisotropic;
GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Linear;
GraphicsDevice.SamplerStates[0].MaxAnisotropy = 16;
// Commit the changes to basic effect so it knows you made modifications
basicEffect.CommitChanges();
// Now perform you rendering to see Anisotropic filtering in effect
感谢Jeromy Wash在AppHub forums处的代码段,这是另一个获得XNA大师帮助的好地方:)
HTH
答案 2 :(得分:1)
各向异性过滤无济于事。你最好的解决方案(虽然不便宜)会使用Supersampling,这将解决你的问题,但是相当昂贵,或Multisampling,这将解决你的问题取决于你的方块几何正在使用。
根据我的个人经验,多重采样在任何情况下都可以保留,因为现代显卡确实能够为您提供更多成本,除非您构建的GPU非常重应用程序\游戏。此外,超级采样并非完全不可能,即使它使用起来非常昂贵,出于与上述相同的原因,但测试看你不会有很大的性能损失。