Instancing Problem - Missing something obvious maybe

Started by
5 comments, last by skyemaidstone 7 years ago

Hi Again,

Here's a youtube video of my problem.

Look at how the hideous cube kinda slides into the terrain and rotates weirdly with the world and from above its vanished into the terrain. None of the other models (not instanced) have that problem.

I'm having trouble getting hardware instancing to work as I need it to. For some reason my instanced models appear to vanish from above.

I thought I was doing something wrong with the instance transforms (which maybe I am). So i ripped out all but the scale and translation for those... same problem.

I thought it might be a depth problem so I just set the depth at 0 and STILL i have the same problem.

I made the simplest model I could with 1 bone and 1 texture. Same problem.

Maybe i'm missing something obvious.

Here's the vertex shader:


VertexShaderOutput VertexShaderCommon(VertexShaderInput input, float4x4 instanceTransform)
{
    VertexShaderOutput output;

    // Apply the world and camera matrices to compute the output position.
    float4 worldPosition = mul(input.Position, instanceTransform);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    // Compute lighting, using a simple Lambert model.
    float3 worldNormal = mul(input.Normal, instanceTransform);
    
    float diffuseAmount = max(-dot(worldNormal, LightDirection), 0);
    
    float3 lightingResult = saturate(diffuseAmount * DiffuseLight + AmbientLight);
    
    output.Color = float4(lightingResult, 1);

    // Copy across the input texture coordinate.
    output.TextureCoordinate = input.TextureCoordinate;

    return output;
}

Please help. I've been stuck on this for a day or two now annoyingly.

Thanks in advance!

Advertisement
Spend some time on getting debug font rendering implemented so you can have realtime visual feedback to the screen that displays the instanced object's world position and/or it's calculated world transform matrix. With a currently static (non dynamic) object, you should observe no value changes. To me, it appears something is affecting the world up position for that object because the vertex shader looks fine.

I'd keep looking at how instanceTransform is calculated, or post that up for us to look at.

Thanks Mark. I do have a debug font rendering various things when i hit a key. I'm not sure why I didn't think of putting the transform in there to look at. I'll try just that.

If it helps the code for making the transforms vertex stream is:


        public static Matrix[] ConvertInstanceGeoDataToTransforms(List<GameClasses.InstancedGeoData> pInstanceGeoData)
        {
            List<Matrix> oTransforms = new List<Matrix>();


            foreach (GameClasses.InstancedGeoData tIGD in pInstanceGeoData)
            {
                //Matrix oNewMatrix = Matrix.CreateScale(tIGD.Scale) * (Matrix.CreateRotationX(MathHelper.ToRadians(tIGD.Yaw)) * Matrix.CreateRotationY(MathHelper.ToRadians(tIGD.Pitch)) * Matrix.CreateRotationZ(MathHelper.ToRadians(tIGD.Yaw))) * Matrix.CreateTranslation(tIGD.Translation);
                Matrix oNewMatrix = Matrix.CreateScale(tIGD.Scale) *  Matrix.CreateTranslation(tIGD.Translation);
            
                oTransforms.Add(oNewMatrix);
            }


            return oTransforms.ToArray();
        }

As you can see I commented out the rotation part incase that was problem (it isn't). This sets _InstanceTransforms.

The actual rendering call is:


 public void DrawModelHardwareInstancing(GraphicsDevice pDevice, Matrix view, Matrix projection)
        {
       

            
                // Transfer the latest instance transform matrices into the instanceVertexBuffer.
                _InstancesVB.SetData(_InstanceTransforms, 0, _InstanceTransforms.Length, SetDataOptions.Discard);

                foreach (ModelMesh mesh in _InstanceModel.XNAModel.Meshes)
                {
                    foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    {
                        // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
                        pDevice.SetVertexBuffers(new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0), new VertexBufferBinding(_InstancesVB, 0, 1));
                        pDevice.Indices = meshPart.IndexBuffer;

                        // Set up the instance rendering effect.
                        //Effect effect = meshPart.Effect;

                        Effect oldEffect = meshPart.Effect;
                        meshPart.Effect = _Effect;
                        Effect EffectToUse = meshPart.Effect;


                        EffectToUse.CurrentTechnique = EffectToUse.Techniques["HardwareInstancing"];

                        EffectToUse.Parameters["World"].SetValue(_instancedModelBones[mesh.ParentBone.Index]);
                        EffectToUse.Parameters["View"].SetValue(view);
                        EffectToUse.Parameters["Projection"].SetValue(projection);
                        EffectToUse.Parameters["Texture"].SetValue(_InstanceModel.Texture);

                        // Draw all the instance copies in a single call.
                        foreach (EffectPass pass in EffectToUse.CurrentTechnique.Passes)
                        {
                            pass.Apply();

                            pDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount, _InstanceTransforms.Length);
                        }

                        meshPart.Effect = oldEffect;
                    }
                }
            
        }

If there was something weird with my view or projection then the rest of the world and non instanced models would be weird to i would think. Baffling.

Thanks for your help. Hopefully that isn't too much code. I hate to throw a wall of code at people when asking for help.

I love XNA or in my case monoGame.
Your environment looks great by the way...

You use what I'd have to say an advanced indexing into your array of matrix transforms that I don't quite understand. I'm not sure how the mesh part knows its position into your custom array. Or I may be way off.

Still, nothing is popping out at me.
I think if I were debugging this with currently the one object, I'd send a hard coded transform to the shader world uniform to start narrowing down the issue and ruling out what it is not.
From the video it looks like the cube is using a slightly different projection matrix to everything else.

Thanks for the idea's. Still trying to track this bug down.

Hodgman you cracked it! I had a bunch of code into between drawing my "entities" (larger complex models that cast shadows) that did the sky, mist, moved the projectiles and set up some other effects... one of which messed with the projection matrix of the camera

Just moving my Instance render call to just after my entity rendering fixed it straight off.

My grass/pebbles etc now look great from any angle and doesn't vanish into the terrain from above.

Thanks for your help guys! :) :)

This topic is closed to new replies.

Advertisement