0
votes

I'm having a problem with XNA 4.0 and couldn't even google it. It occurs in my main project as well as in my test project which is very plain version to reduce unnecessary code.

I need to use my own custom vertex declaration and use it to draw textured primitives (or why not models too).

Drawing and texturing works fine with BasicEffect and any built-in vertex declarations (like VertexPositionColorTexture)...but what on earth is wrong that textures aren't drawn properly if I use BasicEffect with my custom vertex declaration? I'd love to keep all combinations of built-in types in one VD. My only idea as a fix is that I should make a new vertex/pixel shader but would it help? And if it would, how should I do it?

I tried to upload images to describe but I'd need at least 10 reputation so I'll explain in words: With my custom VD, textures of my square (and any other shape) object seems to be tiled instead of scaled/fit. Also, textures won't rotate when I rotate the object.

Here's my custom vertex declaration:

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;
  }
}
}

And the game class:

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

1 Answers

0
votes

I found out the problem. I allocated too much memory for a vertex which resulted in weird texturing. It's in this part of the vertex declaration:

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

Size of type Color isn't actually float/int but byte. Therefore I had to put it like this:

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