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.

I'm rendering textured quads to an orthographic view in XNA through hardware instancing. On Nvidia graphics cards, this all works, tested on 3 machines. On ATI cards, it doesn't work at all, tested on 2 machines.

How come? Culling perhaps?

My orthographic view is set up like this:

Matrix projection = Matrix.CreateOrthographicOffCenter(0, graphicsDevice.Viewport.Width, -graphicsDevice.Viewport.Height, 0, 0, 1);

And my elements are rendered with the Z-coordinate 0.

Edit:

I just figured out something weird.

If I do not call this spritebatch code above doing my textured quad rendering code, then it won't work on Nvidia cards either. Could that be due to culling information or something like that?

        Batch.Instance.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone);
        ...
        spriteBatch.End();

Edit 2:

Here's the full code for my instancing call.

    public void DrawTextures()
    {

        Batch.Instance.SpriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullNone, textureEffect);
        while (texturesToDraw.Count > 0)
        {
            TextureJob texture = texturesToDraw.Dequeue();
            spriteBatch.Draw(texture.Texture, texture.DestinationRectangle, texture.TintingColor);
        }
        spriteBatch.End();

#if !NOTEXTUREINSTANCING
        // no work to do
        if (positionInBufferTextured > 0)
        {

            device.BlendState = BlendState.Opaque;

            textureEffect.CurrentTechnique = textureEffect.Techniques["Technique1"];
            textureEffect.Parameters["Texture"].SetValue(darkTexture);
            textureEffect.CurrentTechnique.Passes[0].Apply();

            if ((textureInstanceBuffer == null) ||
                (positionInBufferTextured > textureInstanceBuffer.VertexCount))
            {
                if (textureInstanceBuffer != null)
                    textureInstanceBuffer.Dispose();

                textureInstanceBuffer = new DynamicVertexBuffer(device, texturedInstanceVertexDeclaration, positionInBufferTextured, BufferUsage.WriteOnly);
            }

            if (positionInBufferTextured > 0)
            {
                textureInstanceBuffer.SetData(texturedInstances, 0, positionInBufferTextured, SetDataOptions.Discard);
            }

            device.Indices = textureIndexBuffer;
            device.SetVertexBuffers(textureGeometryBuffer, new VertexBufferBinding(textureInstanceBuffer, 0, 1));

            device.DrawInstancedPrimitives(PrimitiveType.TriangleStrip, 0, 0, textureGeometryBuffer.VertexCount, 0, 2, positionInBufferTextured);

            // now that we've drawn, it's ok to reset positionInBuffer back to zero,
            // and write over any vertices that may have been set previously.
            positionInBufferTextured = 0;

        }
#endif
    }
share|improve this question
2  
Are your textures powers of 2? –  Tetrad Jun 24 '11 at 4:29
1  
    
Also, if you simply want to use the default values, pass null for that parameter to SpriteBatch.Begin() (works for everything but SpriteSortMode) –  BlueRaja - Danny Pflughoeft Jun 24 '11 at 5:04
    
"I'm rendering textured quads to an orthographic view in XNA through hardware instancing." <- Why not just use SpriteBatch? –  Andrew Russell Jun 24 '11 at 5:13
1  
Andrew - because some of these quads must have the shader applied to it. Some of them doesn't. And I want to draw them in a single call. –  Mathias Lykkegaard Lorenzen Jun 24 '11 at 6:52

2 Answers 2

up vote 4 down vote accepted

SpriteSortMode.Immediate is setting the device state "immediately" you call Begin. You shouldn't use it unless you actually want the Immediate behaviour. Using Immediate turns off batching (slower) but allows you to directly manipulate states on the GraphicsDevice object between sprites. (Prefer Deferred instead.)

You are setting DepthStencilState.Default (depth reads and writes enabled), which is the default for GraphicsDevice, but the default for SpriteBatch is actually None (depth reads and writes disabled).

Now here's the bit where I have to guess (because you haven't provided enough code, and this is a tricky hardware-dependent problem):

You've set your near plane to 0, and you're drawing things at a Z-position of 0, which is right on the border of the valid region of the depth buffer. I would hazard a guess it has something to do with this. You might try moving your near plane back, moving your Z-position forward, and/or disabling the depth buffer.

share|improve this answer
    
The SpriteSortMode thing was quite interesting. However, modifying the Z position didn't work at all. –  Mathias Lykkegaard Lorenzen Jun 24 '11 at 7:28
    
I added more details in the original post. –  Mathias Lykkegaard Lorenzen Jun 24 '11 at 7:42
    
I'm not 100% sure this is exactly right, in XNA4 (as far as I understand) all SpriteBatch.Begin(...) calls immediately set some device states that you might have to reset afterwards. The only thing SpriteSortMode.Immediately changes is if the calls are done immediately on the graphics device or if the calls are batched until SpriteBatch.End() is called. However I know Andrew is quite a lot deeper into XNA than I am, I feel like I had to point this out. –  Roy T. Jun 24 '11 at 8:57
    
The entire state gets set in Begin for Immediate and in End (just before everything is drawn) for every other sort mode. The idea is that you can start filling a (non-immediate) SpriteBatch in parallel with other drawing operations. It basically acts as a buffer. Also SpriteBatch doesn't ever reset state when it's finished (ref). In 3.1, Immediate was draw-lazy (fastest), in 4.0 it's draw-always (slowest, no batching). –  Andrew Russell Jun 24 '11 at 10:27
    
I tried moving the Z coordinate to "5" or "0.5" etc. Still no result! –  Mathias Lykkegaard Lorenzen Jun 24 '11 at 19:08

Be careful, NVIDIA silently upgrades your incorrect set pixelshader/vertexshader versions. ATI will fail. Use the DirectX SDK to check for warnings. My pixelshader was set to 3.0 and my (spriteBatch) Vertex shader to 2.0...

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.