Troubles with OpenGL ES and instancing

I am attempting to get instancing with models to play nicely with Android/OpenGL ES. The shader and the code do work when I only draw the instanced objects and it renders correctly. However, if I try to render any other 3d models after or before that then everything shows up in “artifacts” and is stretched out and distorted. When I try to draw anything 2D to the game screen it will not show up at all if I have just the 2d things and the instanced models being drawn. However, if I also draw a 3d model, the instanced models, and anything in 2d, then they will all show up but the 3d stuff is still distorted.

I also run into an error with switching render targets when using the instanced code when I do this, nothing shows up in game at all.

I’m a bit confused by this behavior and can’t figure out what is going on. Everything is working fine with windows OpenGL but this is delaying my release for Android so I really hope someone might have an idea of what to do to resolve this issue.

I’ve also included the relevant source code for how I am doing this.

public void Draw(GraphicsDevice graphicsDevice)
        {

            foreach (ModelMesh mesh in cube.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    graphicsDevice.Indices = meshPart.IndexBuffer;

                    effect.CurrentTechnique = effect.Techniques["Instancing"];

                    effect.Parameters["World"].SetValue(Matrix.CreateScale(1f) * Matrix.Identity);
                    effect.Parameters["View"].SetValue(view);
                    effect.Parameters["Projection"].SetValue(projection);

                    effect.Parameters["LightDirection"].SetValue(new Vector3(.5f, 1f, -1f));
                    effect.Parameters["Ambient"].SetValue(1f);
                    effect.Parameters["Color"].SetValue(new Vector4(0.15f, .15f, 0.35f, 1f));
                    effect.Parameters["ModelTexture"].SetValue(texture);

                    effect.CurrentTechnique.Passes[0].Apply();

                    graphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                        new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                        );

                    graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, meshPart.StartIndex, meshPart.PrimitiveCount, positions.Length);

                }
            }

public void Load(GraphicsDevice graphicsDevice, ContentManager content)
{
    Vector3 lookat = new Vector3(0, 0, 100);
    view = Matrix.CreateLookAt(lookat, Vector3.Zero, Vector3.Up);
    projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, graphicsDevice.Viewport.AspectRatio, 1, 3000);

    viewVector = Vector3.Transform(Vector3.Zero - lookat, Matrix.CreateRotationY(0));
    viewVector.Normalize();

    instanceVertexDeclaration = new VertexDeclaration
    (
        new VertexElement(0, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 0),
        new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 1),
        new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 2),
        new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 3)
    );

    instanceVertexBuffer = new DynamicVertexBuffer(graphicsDevice, instanceVertexDeclaration, width * height, BufferUsage.WriteOnly);
    instanceVertexBuffer.SetData(positions, 0, width * height, SetDataOptions.Discard);

    texture = content.Load<Texture2D>("BackDrop/squareOutline");
    effect = content.Load<Effect>("BackDrop/instancing");
    cube = content.Load<Model>("BackDrop/cube");

    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < height; y++)
        {
            positions[x + width * y] = Matrix.CreateTranslation(new Vector3(x * gridSpace - (width * gridSpace / 2), y * gridSpace - (height * gridSpace / 2), 0));
        }
    }

    midpointCircle = new MidPointCircle(31);

    //This is a hackish way to do it. I should determine the size of the cubes by 
    //using the perspective and distance and camera but this is quick and will work for a one off
    EstimatedSquareSize = (Math.Abs(Game1.LeftBoundary - Game1.RightBoundary) / width);
    Console.WriteLine("Estimated Square Size: " + EstimatedSquareSize);
}

what seems to fix it for me is clearing the attribs before drawing with instancing.

1 Like

Looks like this also works for me.

1 Like

Having the same issue! (on MonoGame 3.8)

Instancing is working fine with OpenGL on windows but not on android…

a. Any new insights on this?
(I’d like to stay on the main branch of MG if possible…)

b. Is the _attribsDirty = true; work around hurting performance?

thanks!
(sorry to bump an oldie)