0

I'm a green horn with XNA and I've been trying to get past this issue for several days but every time I try to get it done I get an exception or the application just plain exits and it has been very irritating.

I want to be able to draw a 3D primitive without having to have a model premade for it. I had this code first:

VertexPositionColor[] primitiveList = { new VertexPositionColor(
                    new Vector3(1,1,0), Color.White), new VertexPositionColor(
                    new Vector3(0,1,-1), Color.White) };

short[] lineListIndices = { 0, 1 };

Controller.CurrentGame.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
    PrimitiveType.LineList,
    primitiveList,
    0,  // vertex buffer offset to add to each element of the index buffer
    2,  // number of vertices in pointList
    lineListIndices,  // the index buffer
    0,  // first index element to read
    1   // number of primitives to draw
);

And I get an InvalidOperationException with the following

Message "Both a vertex shader and pixel shader must be set on the device before any draw operations may be performed."

So then I try following the instructions on http://msdn.microsoft.com/en-us/library/bb203926.aspx and end up with the following code:

BasicEffect basicEffect = new BasicEffect(Controller.Graphics.GraphicsDevice);

basicEffect.World = Matrix.Identity;
basicEffect.View = Controller.Cam.view;
basicEffect.Projection = Controller.Cam.projection;

// primitive color
basicEffect.AmbientLightColor = new Vector3(0.1f, 0.1f, 0.1f);
basicEffect.DiffuseColor = new Vector3(1.0f, 1.0f, 1.0f);
basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f);
basicEffect.SpecularPower = 5.0f;
basicEffect.Alpha = 1.0f;

basicEffect.LightingEnabled = true;
if (basicEffect.LightingEnabled)
{
    basicEffect.DirectionalLight0.Enabled = true; // enable each light individually
    if (basicEffect.DirectionalLight0.Enabled)
    {
        // x direction
        basicEffect.DirectionalLight0.DiffuseColor = new Vector3(1, 0, 0); // range is 0 to 1
        basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(-1, 0, 0));
        // points from the light to the origin of the scene
        basicEffect.DirectionalLight0.SpecularColor = Vector3.One;
    }

    basicEffect.DirectionalLight1.Enabled = true;
    if (basicEffect.DirectionalLight1.Enabled)
    {
        // y direction
        basicEffect.DirectionalLight1.DiffuseColor = new Vector3(0, 0.75f, 0);
        basicEffect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(0, -1, 0));
        basicEffect.DirectionalLight1.SpecularColor = Vector3.One;
    }

    basicEffect.DirectionalLight2.Enabled = true;
    if (basicEffect.DirectionalLight2.Enabled)
    {
        // z direction
        basicEffect.DirectionalLight2.DiffuseColor = new Vector3(0, 0, 0.5f);
        basicEffect.DirectionalLight2.Direction = Vector3.Normalize(new Vector3(0, 0, -1));
        basicEffect.DirectionalLight2.SpecularColor = Vector3.One;
    }
}

VertexDeclaration vertexDeclaration = new VertexDeclaration(new VertexElement[]
    {
        new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
        new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
        new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
    }
);

Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f);
Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f);
Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f);
Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f);
Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f);
Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f);
Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f);
Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f);

Vector2 textureTopLeft = new Vector2(0.0f, 0.0f);
Vector2 textureTopRight = new Vector2(1.0f, 0.0f);
Vector2 textureBottomLeft = new Vector2(0.0f, 1.0f);
Vector2 textureBottomRight = new Vector2(1.0f, 1.0f);

Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f);
Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f);
Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f);
Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f);
Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f);
Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f);

VertexPositionNormalTexture[] cubeVertices = new VertexPositionNormalTexture[6];

// Front face.
cubeVertices[0] =
    new VertexPositionNormalTexture(
    topLeftFront, frontNormal, textureTopLeft);
cubeVertices[1] =
    new VertexPositionNormalTexture(
    bottomLeftFront, frontNormal, textureBottomLeft);
cubeVertices[2] =
    new VertexPositionNormalTexture(
    topRightFront, frontNormal, textureTopRight);
cubeVertices[3] =
    new VertexPositionNormalTexture(
    bottomLeftFront, frontNormal, textureBottomLeft);
cubeVertices[4] =
    new VertexPositionNormalTexture(
    bottomRightFront, frontNormal, textureBottomRight);
cubeVertices[5] =
    new VertexPositionNormalTexture(
    topRightFront, frontNormal, textureTopRight);

RasterizerState rasterizerState1 = new RasterizerState();
rasterizerState1.CullMode = CullMode.None;
Controller.Graphics.GraphicsDevice.RasterizerState = rasterizerState1;
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
    pass.Apply();

    Controller.Graphics.GraphicsDevice.DrawPrimitives(
        PrimitiveType.TriangleList,
        0,
        12
    );
}

And I get the following Exception

Message "A valid vertex buffer (and a valid index buffer if you are using indexed primitives) must be set on the device before any draw operations may be performed."

I know I shouldn't have all of this code in the same place, but I just want to be able to get something to draw so I can see how it works but nothing works and I can't seem to load any examples into VS.

As I've said I'm rather new and beyond the question I would also greatly appreciate any kind of reading material that would point in the right direction for 3D XNA. Thank you for reading.

4

1 回答 1

2

在您的第一个示例中,您正确地绘制了一个顶点列表,但正如错误所说,它没有着色器。关于着色器的快速说明:由于 WP7 上没有自定义着色器,这意味着您没有应用任何Effect; WP7 仅限于Effect可以在此处找到的子类。它们本质上包含内置着色器。

在第二个示例中,您设置了一个着色器,但现在您没有从任何列表或缓冲区中绘制。DrawUserIndexedPrimitves采用索引和顶点数组。它使用那些来绘制。DrawPrimitives没有;它依赖于绑定到图形设备的顶点缓冲区。

要么将第二个示例更改为DrawUserIndexedPrimitives并传入您的数组(cubeVertices并且......等等,您没有索引数组,请创建一个),或者VertexBuffer使用相同的信息设置 a 并将其绑定如下:

Controller.Graphics.GraphicsDevice.SetVertexBuffer(vb);

于 2013-04-11T15:27:12.147 回答