使用自定义顶点声明对基元进行纹理处理

时间:2014-09-20 18:28:37

标签: c# xna-4.0

我遇到了XNA 4.0的问题,甚至无法谷歌。它发生在我的主项目以及我的测试项目中,这是非常简单的版本,以减少不必要的代码。

我需要使用自己的自定义顶点声明并使用它来绘制纹理基元(或者为什么不是模型)。

使用BasicEffect和任何内置顶点声明(如VertexPositionColorTexture),绘图和纹理都可以正常工作......但是如果我将BasicEffect与自定义顶点声明一起使用,那么纹理未正确绘制到底是错误的呢?我希望在一个VD中保留内置类型的所有组合。我作为修复的唯一想法是我应该制作一个新的顶点/像素着色器,但它会有帮助吗?如果是的话,我应该怎么做?

我尝试上传图片来描述,但我需要至少10个声誉,所以我会用语言解释: 使用我的自定义VD,我的方形(和任何其他形状)对象的纹理似乎是平铺而不是缩放/适合。此外,旋转对象时纹理不会旋转。

这是我的自定义顶点声明:

namespace WindowsGame2
{
  public struct VertexPositionNormalColorTexture : IVertexType
  {
  public Vector3 Position;
  public Vector3 Normal;
  public Color Color;
  public Vector2 TextureCoordinate;

  VertexDeclaration IVertexType.VertexDeclaration
  {
     get { return VertexDeclaration; }
  }

  public readonly static VertexDeclaration VertexDeclaration = 
     new VertexDeclaration(
     new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
     new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
     new VertexElement((sizeof(float) * 3) * 2, VertexElementFormat.Color, VertexElementUsage.Color, 0),
     new VertexElement((sizeof(float) * 3) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
     );

  public VertexPositionNormalColorTexture(Vector3 p)
  {
     Position = p;
     Normal = Vector3.Zero;
     Color = Color.White;
     TextureCoordinate = Vector2.Zero;
  }

  public VertexPositionNormalColorTexture(Vector3 p, Color c)
  {
     Position = p;
     Normal = Vector3.Zero;
     Color = c;
     TextureCoordinate = Vector2.Zero;
  }

  public VertexPositionNormalColorTexture(Vector3 p, Vector2 t)
  {
     Position = p;
     Normal = Vector3.Zero;
     Color = Color.White;
     TextureCoordinate = t;
  }

  public VertexPositionNormalColorTexture(Vector3 p, Color c, Vector2 t)
  {
     Position = p;
     Normal = Vector3.Zero;
     Color = c;
     TextureCoordinate = t;
  }

  public VertexPositionNormalColorTexture(Vector3 p, Vector3 n, Color c)
  {
     Position = p;
     Normal = n;
     Color = c;
     TextureCoordinate = Vector2.Zero;
  }

  public VertexPositionNormalColorTexture(Vector3 p, Vector3 n, Vector2 t)
  {
     Position = p;
     Normal = n;
     Color = Color.White;
     TextureCoordinate = t;
  }

  public VertexPositionNormalColorTexture(Vector3 p, Vector3 n, Color c, Vector2 t)
  {
     Position = p;
     Normal = n;
     Color = c;
     TextureCoordinate = t;
  }
}
}

游戏类:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace WindowsGame2
{
  public class Game1 : Microsoft.Xna.Framework.Game
  {
  GraphicsDeviceManager graphics;
  SpriteBatch spriteBatch;
  ViewerManager viewer;

  List<VertexPositionNormalColorTexture> vertices;
  List<short> indices;
  Texture2D thumbnail;

  VertexBuffer vertexBuf;
  IndexBuffer indexBuf;

  RasterizerState rasterizerState;
  BasicEffect basicEffect;

  Matrix worldMatrix;
  Matrix viewMatrix;
  Matrix projectionMatrix;

  public Game1()
  {
     graphics = new GraphicsDeviceManager(this);
     Content.RootDirectory = "Content";
  }

  protected override void Initialize()
  {
     viewer = new ViewerManager(graphics, new Vector3(0.0f, 0.0f, 5.0f), new Vector3(0.0f, 0.0f, 0.0f), 500);

     vertices = new List<VertexPositionNormalColorTexture>() {

        new VertexPositionNormalColorTexture(new Vector3(-1, -1, 0), Color.Yellow, new Vector2(0, 1)),
        new VertexPositionNormalColorTexture(new Vector3(-1, 1, 0), Color.Yellow, new Vector2(0, 0)),
        new VertexPositionNormalColorTexture(new Vector3(1, 1, 0), Color.Yellow, new Vector2(1, 0)),

        new VertexPositionNormalColorTexture(new Vector3(-1, -1, 0), Color.Yellow, new Vector2(0, 1)),
        new VertexPositionNormalColorTexture(new Vector3(1, 1, 0), Color.Yellow, new Vector2(1, 0)),
        new VertexPositionNormalColorTexture(new Vector3(1, -1, 0), Color.Yellow, new Vector2(1, 1)),
     };
     indices = new List<short>() {
        0, 1, 2, 3, 4, 5
     };

     basicEffect = new BasicEffect(graphics.GraphicsDevice);

     worldMatrix = Matrix.CreateTranslation(0.0f, 0.0f, 0.0f) * Matrix.CreateScale(3);
     viewMatrix = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 5.0f), new Vector3(0.0f, 0.0f, 0.0f), Vector3.Up);
     projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(90), graphics.GraphicsDevice.Viewport.AspectRatio, 1f, 50f);

     vertexBuf = new VertexBuffer(graphics.GraphicsDevice, VertexPositionNormalColorTexture.VertexDeclaration, 500, BufferUsage.WriteOnly);
     indexBuf = new IndexBuffer(graphics.GraphicsDevice, IndexElementSize.SixteenBits, 500, BufferUsage.WriteOnly);

     rasterizerState = new RasterizerState();
     rasterizerState.CullMode = CullMode.None;

     base.Initialize();
  }

  protected override void LoadContent()
  {
     spriteBatch = new SpriteBatch(GraphicsDevice);
     thumbnail = this.Content.Load<Texture2D>("GameThumbnail");
  }

  protected override void UnloadContent()
  {
     this.Content.Unload();
  }

  protected override void Update(GameTime gameTime)
  {
     if (Keyboard.GetState().IsKeyDown(Keys.Escape))
        this.Exit();

     base.Update(gameTime);
  }

  protected override void Draw(GameTime gameTime)
  {
     GraphicsDevice.Clear(Color.CornflowerBlue);
     graphics.GraphicsDevice.RasterizerState = rasterizerState;

     basicEffect.World = worldMatrix;
     basicEffect.View = viewMatrix;
     basicEffect.Projection = projectionMatrix;

     basicEffect.VertexColorEnabled = true;
     basicEffect.TextureEnabled = true;
     basicEffect.Texture = thumbnail;

     vertexBuf.SetData<VertexPositionNormalColorTexture>(vertices.ToArray());
     indexBuf.SetData<short>(indices.ToArray());

     graphics.GraphicsDevice.SetVertexBuffer(vertexBuf);
     graphics.GraphicsDevice.Indices = indexBuf;

     foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
     {
        pass.Apply();

        graphics.GraphicsDevice.DrawUserIndexedPrimitives(
           PrimitiveType.TriangleList,
           vertices.ToArray(),
           0,
           vertices.Count,
           indices.ToArray(),
           0,
           2,
           VertexPositionNormalColorTexture.VertexDeclaration);
     }
     graphics.GraphicsDevice.Indices = null;
     graphics.GraphicsDevice.SetVertexBuffer(null);

     base.Draw(gameTime);
  }
 }
}

1 个答案:

答案 0 :(得分:0)

我发现了问题。我为顶点分配了太多内存,导致了奇怪的纹理。它位于顶点声明的这一部分:

new VertexElement((sizeof(float) * 3) * 2, VertexElementFormat.Color, VertexElementUsage.Color, 0),
 new VertexElement((sizeof(float) * 3) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)

类型的大小颜色实际上不是浮点数/整数而是字节。所以我不得不这样说:

new VertexElement((sizeof(float) * 3) * 2 + 4, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)