Skip to main content
GameDev.net gamedev.net
🔒 Locked

XNA and BasicEffect trouble

Started by 23yrold3yrold Dec 31, 2009 at 6:48 PM 4 replies 3.6k views
Original Post
23yrold3yrold
23yrold3yrold
I'm building a simple little game engine and a shooter on top of it to get my feet wet with XNA. The functionality of the 'effects' though are kind of throwing me. Permit me to drop some code on you ... I "make" my model; 2 squares for testing:

                vertices = new VertexPositionColor[12];

                // top
                vertices[0].Position = new Vector3(-20f, -20f, 20f);
                vertices[0].Color = Color.Red;
                vertices[1].Position = new Vector3(20f, -20f, 20f);
                vertices[1].Color = Color.Red;
                vertices[2].Position = new Vector3(-20f, 20f, 20f);
                vertices[2].Color = Color.Red;
                vertices[3].Position = new Vector3(20f, -20f, 20f);
                vertices[3].Color = Color.Red;
                vertices[4].Position = new Vector3(20f, 20f, 20f);
                vertices[4].Color = Color.Red;
                vertices[5].Position = new Vector3(-20f, 20f, 20f);
                vertices[5].Color = Color.Red;

                // bottom
                vertices[6].Position = new Vector3(-20f, -20f, -20f);
                vertices[6].Color = Color.Blue;
                vertices[7].Position = new Vector3(20f, -20f, -20f);
                vertices[7].Color = Color.Blue;
                vertices[8].Position = new Vector3(-20f, 20f, -20f);
                vertices[8].Color = Color.Blue;
                vertices[9].Position = new Vector3(20f, -20f, -20f);
                vertices[9].Color = Color.Blue;
                vertices[10].Position = new Vector3(-20f, 20f, -20f);
                vertices[10].Color = Color.Blue;
                vertices[11].Position = new Vector3(20f, 20f, -20f);
                vertices[11].Color = Color.Blue;

                coloredVertexDeclaration = new VertexDeclaration(Game1.device, VertexPositionColor.VertexElements);

I set up an effect object:

                basicEffect = new BasicEffect(Game1.device, null);
                
                basicEffect.Alpha = 1.0f;
                basicEffect.DiffuseColor = new Vector3(0.1f, 0.9f, 0.1f);
                basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f);
                basicEffect.SpecularPower = 1.0f;
                basicEffect.AmbientLightColor = new Vector3(0.75f, 0.75f, 0.75f);

                basicEffect.DirectionalLight0.Enabled = true;
                basicEffect.DirectionalLight0.DiffuseColor = Vector3.One;
                basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f));
                basicEffect.DirectionalLight0.SpecularColor = Vector3.One;

                basicEffect.LightingEnabled = true;

                basicEffect.World = Matrix.Identity;
                basicEffect.View = Matrix.CreateLookAt(new Vector3(0, 0, 200), Vector3.Zero, Vector3.Up);

                Matrix m = new Matrix();
                Matrix.CreateOrthographic(800, 450, 0.1f, 1000, out m);
                basicEffect.Projection = m;

And I try drawing:

            basicEffect.Begin();

            foreach (Powerup e in powerupList)
            {
                basicEffect.World *= Matrix.CreateTranslation(pos.X - camx, pos.Y - camy, 0f);
                foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
                {
                    pass.Begin();

                    Game1.device.VertexDeclaration = coloredVertexDeclaration;
                    Game1.device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, 4);
                    pass.End();
                }
            }
            basicEffect.End();

I always get 2 very flatly-colored polygons in the basicEffect.DiffuseColor color (green here). Setting VertexColorEnabled to true just turns everything black. Not sure what I'm fouling up here; thoughts?
Jesus saves ... the rest of you take 2d4 fire damage.
MJP
MJP
You can't enable lighting unless you have vertex normals. Otherwise the lighting calculations will get all messed up.
23yrold3yrold
23yrold3yrold
Okay, that makes sense. Any clues on how to initialize that? My array is VertexPositionColored; I see mention of VertexPositionNormalColored online but not in official documentation and my compiler gives me an error on it. Obviously I'm still researching, but if anyone can give me a push in the right direction, that's be nifty.
Jesus saves ... the rest of you take 2d4 fire damage.
MJP
MJP
Yeah the only thing I see in the documentation is VertexPositionNormalTexture, which has normals but no vertex color. No worries, you can just make your own struct and vertex declaration. Something like this should work:
public struct VertexPositionNormalColor{    public Vector3 Position;    public Vector3 Normal;    public Color Color;    public static readonly VertexElement[] VertexElements = new VertexElement[] {                       new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),                       new VertexElement(0, 12, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0),                       new VertexElement(0, 24, VertexElementFormat.Color, VertexElementMethod.Default, VertexElementUsage.Color, 0) }    public static int SizeInBytes    {        get { return 28; }    }}


For the VertexElement array, you're basically just describing how data is laid out in your vertex buffer. This way the runtime knows how to pull out the appropriate data in your vertex shader. So basically for each seperate piece of data in a vertex you say what stream it's in (almost always 0), how many bytes there are in the vertex before that data, the format of the data, the tessellation method for that data (always Default), the usage of the data (specifies what the data actually is, like a position or color or texture coordinate), and finally the usage index (this is only non-zero when you have multiple elements with the same usage, for example multiple texture coordinates).
23yrold3yrold
23yrold3yrold
Yeah, I'm still not used to the whole "invent your own type and register it" routine, but I added the normals, initialized by hand (it's just a cube) and mostly good to go. Had to enable the depth buffer (why isn't that enabled by default?!) and play with the values a bit, but I got me some nicely colored spinning cube power-ups in my shooter now, well-lit and everything. It's gonna be real fun making more detailed power-ups; I'll probably just texture the cubes with giant letters, but at least I've got something I can work with. Thanks.
Jesus saves ... the rest of you take 2d4 fire damage.
23yrold3yrold
23yrold3yrold
Okay, I almost have this. I can get the colored polys working, and I moved to textured polys, which is also working, but the lighting isn't anymore. It obeys the color of the light and the ambient; I can adjust variables like that and the graphics respond accordingly. But the lighting is still flat, like I've got no normals, which leads me to believe that I set the normals up wrong or I need to do something extra for textures that I didn't for colored polys, since the old textureless cube that I set up with normals receives light perfectly.

The structure:

    public struct VertexPositionNormalTextured    {        public Vector3 Position;        public Vector2 TextureCoord;        public Vector3 Normal;        public VertexPositionNormalTextured(Vector3 position, Vector2 texCoord, Vector3 normal)        {            this.Position = position;            this.TextureCoord = texCoord;            this.Normal = normal;        }        public static int SizeInBytes = sizeof(float) * (3 + 2 + 3);        public static VertexElement[] VertexElements = new VertexElement[]        {            new VertexElement( 0, sizeof(float) * 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0 ),            new VertexElement( 0, sizeof(float) * 3, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0 ),            new VertexElement( 0, sizeof(float) * 5, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0 ),        };


The new model initialization:

                poweruptexture = Content.Load<Texture2D>("powerup_l");                                vertices2 = new VertexPositionNormalTextured[8];                // top                vertices2[0].Position = new Vector3(-20f, -20f, 20f);                vertices2[0].TextureCoord.X = 0;                vertices2[0].TextureCoord.Y = 0;                vertices2[0].Normal = new Vector3(0f, 0f, 0f);                vertices2[1].Position = new Vector3(20f, -20f, 20f);                vertices2[1].TextureCoord.X = 1;                vertices2[1].TextureCoord.Y = 0;                vertices2[1].Normal = new Vector3(0f, 0f, 0f);                vertices2[2].Position = new Vector3(20f, 20f, 20f);                vertices2[2].TextureCoord.X = 1;                vertices2[2].TextureCoord.Y = 1;                vertices2[2].Normal = new Vector3(0f, 0f, 0f);                vertices2[3].Position = new Vector3(-20f, 20f, 20f);                vertices2[3].TextureCoord.X = 0;                vertices2[3].TextureCoord.Y = 1;                vertices2[3].Normal = new Vector3(0f, 0f, 0f);                // bottom                vertices2[4].Position = new Vector3(-20f, -20f, -20f);                vertices2[4].TextureCoord.X = 0;                vertices2[4].TextureCoord.Y = 0;                vertices2[4].Normal = new Vector3(0f, 0f, -1f);                vertices2[5].Position = new Vector3(20f, -20f, -20f);                vertices2[5].TextureCoord.X = 1;                vertices2[5].TextureCoord.Y = 0;                vertices2[5].Normal = new Vector3(0f, 0f, -1f);                vertices2[6].Position = new Vector3(-20f, 20f, -20f);                vertices2[6].TextureCoord.X = 0;                vertices2[6].TextureCoord.Y = 1;                vertices2[6].Normal = new Vector3(0f, 0f, -1f);                vertices2[7].Position = new Vector3(20f, 20f, -20f);                vertices2[7].TextureCoord.X = 1;                vertices2[7].TextureCoord.Y = 1;                vertices2[7].Normal = new Vector3(0f, 0f, -1f);                texturedVertexDeclaration = new VertexDeclaration(Game1.device, VertexPositionTexture.VertexElements);                indices[0] = 0;                indices[1] = 1;                indices[2] = 3;                indices[3] = 1;                indices[4] = 2;                indices[5] = 3;                indices[6] = 5;                indices[7] = 4;                indices[8] = 6;                indices[9]  = 5;                indices[10] = 6;                indices[11] = 7;


The effect:

                basicEffect = new BasicEffect(Game1.device, null);                                basicEffect.Alpha = 1.0f;                basicEffect.DiffuseColor = new Vector3(1f, 1f, 1f);                basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f);                basicEffect.SpecularPower = 1.0f;                basicEffect.AmbientLightColor = new Vector3(0.5f, 0.5f, 0.5f);                basicEffect.DirectionalLight0.Enabled = true;                basicEffect.DirectionalLight0.DiffuseColor = Vector3.One;                basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(0.5f, 0.5f, -1.0f));                basicEffect.DirectionalLight0.SpecularColor = Vector3.One;                basicEffect.LightingEnabled = true;                basicEffect.Texture = poweruptexture;                basicEffect.TextureEnabled = true;                // set up basic world view projection and the camera                basicEffect.World = Matrix.Identity;                basicEffect.View = Matrix.CreateLookAt(new Vector3(0, 0, 200), Vector3.Zero, Vector3.Up);                Matrix m = new Matrix();                Matrix.CreateOrthographic(800, 450, 0.1f, 1000, out m);                basicEffect.Projection = m;


And finally, the drawing:

            Game1.device.RenderState.CullMode = CullMode.None;            Game1.device.RenderState.DepthBufferEnable = true;            basicEffect.Begin();            foreach (Powerup e in powerupList)            {                foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)                {                    pass.Begin();                    Game1.device.VertexDeclaration = texturedVertexDeclaration;                    Game1.device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices2, 0, vertices2.Length, indices, 0, indices.Length / 3);                    pass.End();                }            }            basicEffect.End();


The texture brightens if I increase ambient, but it remains unaffected by its angle to the light. Again, works fine if I uncomment the colored polys and use that instead, and I don't see what I'm doing different. Thoughts?

EDIT: NM, I'm a 'tard. [embarrass]

                // bad line                texturedVertexDeclaration = new VertexDeclaration(Game1.device, VertexPositionTexture.VertexElements);                // new, gooder line                texturedVertexDeclaration = new VertexDeclaration(Game1.device, VertexPositionNormalTextured.VertexElements);

Um, carry on!

[Edited by - 23yrold3yrold on January 2, 2010 3:25:13 PM]
Jesus saves ... the rest of you take 2d4 fire damage.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.