Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Iv started up doing some programming in XNA as Iv been doing C# for several years and would like to start do some 3D work with C# and XNA framework.

Right now Im trying to build a sphere by code. It renders fine, but as soon as I apply some light it looks like it it is drawn twise with and without normals for shading. It gets very flickery, between light-shaded and unshaded.

    basicEffect.EnableDefaultLighting();
    basicEffect.DirectionalLight0.Direction = new Vector3(1, -1, 1);
    basicEffect.DirectionalLight0.Enabled = true;

The code for generating the shpere data looks like this.

    public class Sphere : Component, I3DComponent
{
    float spehereRes = 10.0f;       

    // I3DComponent values
    Vector3 position = Vector3.Zero;
    Matrix rotation = Matrix.Identity;
    Vector3 scale = new Vector3(1, 1, -1);
    BoundingBox boundingBox = new BoundingBox(new Vector3(-1), new Vector3(1));

    public Vector3 Position { get { return position; } set { position = value; } }
    public Vector3 EulerRotation
    {
        get { return MathUtil.MatrixToVector3(Rotation); }
        set { this.Rotation = MathUtil.Vector3ToMatrix(value); }
    }
    public Matrix Rotation { get { return rotation; } set { rotation = value; } }
    public Vector3 Scale { get { return scale; } set { scale = value; } }
    public BoundingBox BoundingBox { get { return boundingBox; } }


    // Effect
    BasicEffect basicEffect;

    //Sphere variables
    short[] indices;       
    int nvertices, nindices;
    VertexPositionColorNormal[] vertices;
    VertexBuffer vbuffer;
    IndexBuffer ibuffer;


    public Sphere(float radius)
        : base()
    {
        basicEffect = new BasicEffect(Engine.GraphicsDevice);
        SetupEffect();
        Setup(radius);
    }

    public Sphere(float radius, GameScreen Parent)
        : base(Parent)
    {
        basicEffect = new BasicEffect(Engine.GraphicsDevice);
        SetupEffect();
    }

    private void Setup(float radius)
    {
        nvertices =Convert.ToInt32( spehereRes) * Convert.ToInt32(spehereRes); // nr of vertices in a circle, nr of circles in a sphere
        nindices = Convert.ToInt32(spehereRes) * Convert.ToInt32(spehereRes) * 6;
        vbuffer = new VertexBuffer(Engine.GraphicsDevice, typeof(VertexPositionNormalTexture), nvertices, BufferUsage.WriteOnly);
        ibuffer = new IndexBuffer(Engine.GraphicsDevice, IndexElementSize.SixteenBits, nindices, BufferUsage.WriteOnly);           
        CreateIndices();
        CreateSphereVertices(radius);
        CalculateNormals();
        vbuffer.SetData<VertexPositionColorNormal>(vertices);
        ibuffer.SetData<short>(indices);



    }


    #region// Setup BasicEffect
    /// <summary>
    /// Setsup basic effect parameters
    /// </summary>
    private void SetupEffect()
    {  
        //basicEffect.VertexColorEnabled = true;      
        //basicEffect.TextureEnabled = true;
        basicEffect.EnableDefaultLighting();
        basicEffect.DirectionalLight0.Direction = new Vector3(1, -1, 1);
        basicEffect.DirectionalLight0.Enabled = true;
        //basicEffect.AmbientLightColor = new Vector3(0.3f, 0.3f, 0.3f);
        //basicEffect.DirectionalLight1.Enabled = false;
        //basicEffect.DirectionalLight2.Enabled = false;
        //basicEffect.SpecularColor = new Vector3(0, 0, 0);
    }
    #endregion

    public override void Draw()
    {
        // Look for a camera in the service container
        Camera camera = Engine.Services.GetService<Camera>();
        // Throw an exception if one isn't present
        if (camera == null)
        {
            throw new Exception("Camera not found in engine's"
            + "service container, cannot draw");
        }

        // Set effect values
        basicEffect.World = MathUtil.CreateWorldMatrix(position, rotation, scale);
        basicEffect.View = camera.View;
        basicEffect.Projection = camera.Projection;


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

            // Draw the terrain vertices and indices
            Engine.GraphicsDevice.SetVertexBuffer(vbuffer);
            Engine.GraphicsDevice.Indices = ibuffer;
            Engine.GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, nvertices, indices, 0, indices.Length / 3, VertexPositionColorNormal.VertexDeclaration);
        }
    }

    #region //CreateIndices()
    /// <summary>
    /// Creates Sphere Indices
    /// </summary>
    private void CreateIndices()
    {
        indices = new short[nindices];
        int i = 0;
        for (int x = 0; x < spehereRes; x++)
        {
            for (int y = 0; y < spehereRes; y++)
            {
                int s1 = x == spehereRes-1 ? 0 : x + 1;
                int s2 = y ==spehereRes-1 ? 0 : y + 1;
                short upperLeft = (short)(x * spehereRes + y);
                short upperRight = (short)(s1 * spehereRes + y);
                short lowerLeft = (short)(x * spehereRes + s2);
                short lowerRight = (short)(s1 * spehereRes + s2);

                indices[i++] = upperLeft;
                indices[i++] = upperRight;
                indices[i++] = lowerLeft;
                indices[i++] = lowerLeft;
                indices[i++] = upperRight;
                indices[i++] = lowerRight;
            }
        }
    }
    #endregion

    #region //CreateSphereVertices(float radius)
    /// <summary>
    /// Setup Sphere object
    /// </summary>
    /// <param name="radius"></param>
    void CreateSphereVertices(float radius)
    {
        vertices = new VertexPositionColorNormal[nvertices];
        Vector3 center = new Vector3(0, 0, 0);
        Vector3 rad = new Vector3((float)Math.Abs(radius), 0, 0);
        for (int x = 0; x < spehereRes; x++) //nr of circles, difference between each is 4 degrees
        {
            float difx = 360.0f / spehereRes;
            for (int y = 0; y < spehereRes; y++) //nr of veritces, difference between each is 4 degrees 
            {
                float dify = 360.0f / spehereRes;
                Matrix zrot = Matrix.CreateRotationZ(MathHelper.ToRadians(y * dify)); //rotate vertex around z
                Matrix yrot = Matrix.CreateRotationY(MathHelper.ToRadians(x * difx)); //rotate circle around y
                Vector3 point = Vector3.Transform(Vector3.Transform(rad, zrot), yrot);//transformation

                vertices[x + y * Convert.ToInt32(spehereRes)].Position = point;
                vertices[x + y * Convert.ToInt32(spehereRes)].Color = Color.Black;
            }
        }
    }

    #endregion

    #region //CalculateNormals()
    /// <summary>
    /// Calculates Noramals for vertices
    /// </summary>
    private void CalculateNormals()
    {
        for (int i = 0; i < vertices.Length; i++)
            vertices[i].Normal = new Vector3(0, 0, 0);

        for (int i = 0; i < indices.Length / 3; i++)
        {
            int index1 = indices[i * 3];
            int index2 = indices[i * 3 + 1];
            int index3 = indices[i * 3 + 2];

            Vector3 side1 = vertices[index1].Position - vertices[index3].Position;
            Vector3 side2 = vertices[index1].Position - vertices[index2].Position;
            Vector3 normal = Vector3.Cross(side1, side2);

            vertices[index1].Normal += normal;
            vertices[index2].Normal += normal;
            vertices[index3].Normal += normal;
        }

        for (int i = 0; i < vertices.Length; i++)
            vertices[i].Normal.Normalize();
    }
    #endregion
}

Any ideas about this would be appreciated. I lowered the spheres "resolution" to 10 to try find an answer while doing the drawing but looks kind of tricky.

share|improve this question
    
Hi Jonas! Since you've solved your problem, you should just answer your own question, and accept it (instead of editing the question itself) - nothing prohibits you from answering your own questions, it's even encouraged, and it helps keeping the site Q&A structure. –  Laurent Couvidou Aug 3 '12 at 23:05
    
Ok. ill fix that. –  Jonas Lindahl Aug 4 '12 at 14:23

1 Answer 1

up vote 0 down vote accepted

Solved. Typical... :) Been struggling with this for a while now. and now that I posted for any tips i finally found the solution.

I had theese Rasterizer settings for rendering.

        RasterizerState rs = new RasterizerState();
    rs.CullMode = CullMode.None;
    rs.FillMode = FillMode.Solid;
    Engine.GraphicsDevice.RasterizerState = rs;          

If i removed them and only ran

Engine.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;

It worked as it should. Well if anyone else should have problem with overlapped drawing I hope this helps to check out how the Rastarizer is set.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.