How to use VertexPositionTexture correctly?

Hi, I’m trying to manipulate Texture2D objects as triangles, and it seems to me that using VertexPositionTexture objects would be the solution to this. However, when I try to map a red rectangle - as a Texture2D - to a triangle, I don’t see it. My code is this:

`protected override void Draw(GameTime gameTime)
    {
    this.GraphicsDevice.Clear(Color.White);
        if (_basicEffect.Texture == null || _basicEffect.Texture.Width != 50)
        {
            var rectangleColorData = new Color[50 * 50];
            for (int i = 0; i < 50; i++)
            {
                for (int j = 0; j < 50; j++)
                {
                    rectangleColorData[i * 50 + j] = Color.Red;
                }
            }

            var rectangleTexture = new Texture2D(this.GraphicsDevice, 50, 50);
            rectangleTexture.SetData(rectangleColorData);
            _basicEffect.Texture = rectangleTexture;
        }

        var vertices = new VertexPositionTexture[]
        {
            new VertexPositionTexture(new Vector3(-1, 0, 0), new Vector2(0, 0)),
            new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 50)),
            new VertexPositionTexture(new Vector3(0, 0, 0), new Vector2(25F, 25)),
        };

        _basicEffect.World = _basicEffect.View = _basicEffect.Projection = Matrix.Identity;
        _basicEffect.TextureEnabled = true;
        var buffer = new VertexBuffer(this.GraphicsDevice, typeof(VertexPositionTexture), vertices.Length, BufferUsage.WriteOnly);
        buffer.SetData(vertices);
        this.GraphicsDevice.SetVertexBuffer(buffer);
        this.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
        foreach (var pass in _basicEffect.CurrentTechnique.Passes)
        {
            pass.Apply();               
            this.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, 1);
        }
    base.Draw(gameTime);
    }`

And I see this:

What am I doing wong?

You sure you’ve got your UVs right? I think they need to be between 0 and 1. Not sure though.

Also, perhaps try VertexPositionColorTexture and setting the color of each vertex to Color.White?

Honestly, I don’t know. As you can see, I set the World, View and Projection matrices to identity matrices, so that’s nothing special. Beyond that, I just created a rectangle as an in-memory Texture2D - I don’t read it in from the pipeline - and now I’m trying to figure out how to get it working by trial and error, because there is no detailed documentation of this VertexPositionTexture and based on what I found on the net, I couldn’t get it working.

I also tried what you suggested - switching to VertexPositionColorTexture objects - but to no avail. :frowning:

I don’t see anything wrong in your code in the Draw method, unless you have other unusual setting with your _basicEffect somewhere or your emulator is not working properly.

@DexterZ You were right: I had an additional setting: _basicEffect.VertexColorEnabled = true; But I don’t understand how that was a problem? Seems like if you set VertexColorEnabled first to true, and then you later set TextureEnabled to true that messes up the GraphicsDevice? Why?

1 Like

I think it’s not necessary to display the color of vertex if your going put some texture on it anyway, not pretty sure tho.

It blends the vertex color with the texture. In your case I suppose the vertex color defaults to black , and therefore the texture is tinted black.

Oh I see now, I understand it. Thank you guys!

1 Like

Just a little additional note.

You don’t want to do this part in draw you want to move it to a method call it from say load then set the texture to basic effect and call the texture from draw.
The reason im mentioning it, is that the reference to the texture is going out of scope without being disposed each frame if you do this long enough it could potentially cause your card to throw a out of memory exception or cause a memory leak on app exit. Also the data itself is generating massive garbage each second this way. So you want to make it a once shot thing.

    // make it a class scoped texture2d reference
    Texture2D rectangleTexture;

    public CreateTriangle(int size)
    {
    var rectangleColorData = new Color[size* size];
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            rectangleColorData[i * size+ j] = Color.Red;
        }
    }

    // instantiate the reference object
    rectangleTexture = new Texture2D(this.GraphicsDevice, size, size);
    rectangleTexture.SetData(rectangleColorData);
    // move this to draw
    //_basicEffect.Texture = rectangleTexture;
    }

@willmotil

  1. As you can see in my code, I included a guard: if (_basicEffect.Texture == null || _basicEffect.Texture.Width != 50) which prevents the recreation of the texture at every single frame, specifically for this reason. (The _basicEffect is a private field, so its reference is preserved.)

  2. Whatever I wrote here is not the entire game I’m making, just a brief snippet to demonstrate the problem, so yeah, rest assured, the end result will have a well-chiseled architecture.

But thanks, anyway :wink: