[solved] Color glitch when changing from orthogonal to perspective view

I experience a strange glitch when rendering a color overlay and changing from an orthogonal camera to a perspective one:

Basically, when an item is selected in the application, it gets a shade of red by calling

Color.r = 1.0f;

in the (custom) pixel shader. Otherwise, the color is not touched. The additional blue lines do not influence the results. So far, so good. Now, when I change my view from orthogonal to perspective in the corresponding camera class:

Projection = Matrix.CreateOrthographic(aspectRatio / CZoom, 1 / CZoom, ViewingPlanes[0], ViewingPlanes[1]);

with CZoom the current zoom level, changes to

Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, ViewingPlanes[0], ViewingPlanes[1]);

and the mentioned glitch is displayed, rendering the surfaces uneven. Switching back to orthogonal resolves the issue. Since it is working fine in orthogonal view, I am not sure if this is a problem of the shader or the camera class.

Clarification: I am not rendering the orange/brown box first and then a red box on top. Instead, I am only changing the red color component in the shader to get the “overlay” effect. Sorry, if this caused any misunderstandings.

Looks like a z-fighting problem. You need to apply a “z-bias” (“depth bias”) when rendering the overlay.

Thanks, but I doubt that it is a z-fighting issue: I am not first rendering the shape and the overlay on top. Instead, I am rendering the shape and change the red color component to maximum. Also, shouldn’t z-fighting apply in both cases, the perspective view and the orthogonal view?

I see - calling it “color overlay” may be confusing. :wink:

Z-fighting can occur in both views. But orthogonal and perspective views have a different depth buffer resolution - depending on the settings it may occur in one view, but not the other.

To rule out z-fighting, you can clear the depth buffer before rendering the color overlay.

The fact that we can see the original colours in artifacts that look exactly like z-fighting is a strong indicator to rendering the coloured box directly over the existing uncoloured box, i.e. the colour buffer and depth buffer have not been cleared since the uncoloured box was rendered.

That it happens in one view and not the other might just be down to slightly different values being written to the depth buffer. The accuracy of the depth buffer varies greatly at different depths.

Okay, thanks for the advice, first of all. I am actually clearing the depth buffer and z-buffer before each rendering using

gDevice.Clear(Color.White);
gDevice.DepthStencilState = DepthStencilState.Default;
gDevice.BlendState = BlendState.Opaque;

with gDevice being my graphics device. Again, I am not rendering a red box on top of a gray one, but instead increase the red component in the shader.
Maybe this glitch really stems from the different depth buffer sizes? How would I look those up? Is there a way to increase them?

I am actually rendering to a RenderTarget2D (the engine runs in a WPF application), which is set up as

_renderTarget = new RenderTarget2D(_graphicsDevice, width, height, false, SurfaceFormat.Bgr32, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents, true);

So, for the RenderTarget2D, I use a 24bit depth buffer with 8 bit Stencil Buffer “on top”. Could this cause the problem?

No idea why, but once I started changing the red color component in the vertex shader instead of in the pixel shader, the glitch was gone. I am happy it is working now, even though I am not really understanding why it does. Anyways, thanks for your advice!

I had a sort of scimilar glitch a while ago…

Found out it was in my projection / field of view setup… using pi over 4 doesnt work 100%, it causes some artifacting.
You have to use MathHelper.ToRadians(45f)… I know they should be the same, but for some reason they arent!

This is what works in my code:
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f), graphics.GraphicsDevice.Viewport.AspectRatio, 0.1f, 10000);

1 Like

Thanks, that’s actually been another issue I’ve not yet asked about. Specifically, when going to larger distances, the model had apparent z-fighting issues, which have now been resolved by switching to your proposed code.