Skybox issue

Started by
9 comments, last by BlackJoker 9 years, 7 months ago

In my skybox shader I used logarithmic depth buffer to make it always visible at any distance.

But this caused unexpected side effect - one of the cube`s sides always disappearing when looking on it from special angle. When I comment calculation of depth buffer - everything OK.

Here is my skybox effect code:


matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;

float3 CameraPosition;
 
float zNear;
float zFar;
TextureCube skyboxTexture;
SamplerState skyBoxSampler;
 
struct VertexShaderInput
{
    float4 Position : SV_POSITION0;
};
 
struct VertexShaderOutput
{
    float4 Position : SV_POSITION0;
    float3 TextureCoordinate : TEXCOORD0;
};
 
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
 
    float4 worldPosition = mul(input.Position, worldMatrix);
    float4 viewPosition = mul(worldPosition, viewMatrix);
    output.Position = mul(viewPosition, projectionMatrix);
    //this line caused the issue
    output.Position.z = log(zNear*output.Position.z + 1) / log(zNear*zFar + 1) * output.Position.w;
    

	float4 VertexPosition = mul(input.Position, worldMatrix);		  
	output.TextureCoordinate = VertexPosition - CameraPosition;
	

	return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : SV_TARGET
{
	return skyboxTexture.Sample(skyBoxSampler, input.TextureCoordinate);
}

technique Skybox
{
	pass Pass0
	{
		Profile = 11.0;
		VertexShader = VertexShaderFunction;
		PixelShader = PixelShaderFunction;
	}
}

For znear, zfar I use following values:


skyboxEffect.Parameters["zNear"].SetValue(0.01f);
skyboxEffect.Parameters["zFar"].SetValue(16500000000.0f);

This perfectly working with my loaded models, but not working correctly with skybox.

I set size for cube to 1650000.0f.

Does someone know how to fix described issue without disabling logarithmic depth buffer or at least make that when object is far from camera, skybox not disappear.

Advertisement

If you want your skybox to be always visible at any distance...

  • Set up a viewport with MinDepth 1 and MaxDepth 1.
  • Draw it as a 10x10x10 (adjust size to suit your near clipping plane) cube centered on the view origin.

That's really all there is to it. Do it last after all other opaque objects in your scene, of course, so that you'll get the benefit of early-Z rejection. Otherwise this will absolutely guarantee that the skybox will be drawn at the very furthest depth, no matter what values you pick for zNear and zFar, and you don't need to do anything fancy. Just the most basic shaders and you get the desired result.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

To make it always render to the far-plane, you can also put this at the end of your vertex shader (instead of your logarithmic z line).

output.Position.z = output.Position.w;

To make it always render to the far-plane, you can also put this at the end of your vertex shader (instead of your logarithmic z line).

output.Position.z = output.Position.w;

Unfortunately, its not working. Result the same and even worse - skybox began blinking all the time.

I have effect like this:

With Hodgman's suggestion you should also draw at a reduced size - the 10x10x10 cube should be good.

One other thing:


skyboxEffect.Parameters["zNear"].SetValue(0.01f);
skyboxEffect.Parameters["zFar"].SetValue(16500000000.0f);

Are these values going into your projection matrix too?

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Why dont you just disable depth testing when drawing your skybox, and then make it follow your position with a simple translate, that works for me.


Are these values going into your projection matrix too?

No, in projection matrix I set znear = 10 and zfar = 16500000.0f

Why dont you just disable depth testing when drawing your skybox, and then make it follow your position with a simple translate, that works for me.

I just tested - when my model on far plane of the cube, it blinks even if no depth check enabled. So, my solution with logarithmic depth is the best for this, except issue with faces, which I suppose we could solve.


Are these values going into your projection matrix too?

No, in projection matrix I set znear = 10 and zfar = 16500000.0f

This is still too huge for your far clipping plane. With a 24-bit depth buffer, and plugging the figures into the calculator at http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html we see that the smallest resolvable depth separation at the far range is 1477433. Ouch.

You're just getting classic z-fighting owing to limited precision.

Tricksy schemes to work around this is not the solution. Have you tried pulling your far plane nearer and just using one of the solutions provided by Hodgman or myself?

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

OK, guys, I found the problem. My custom logarithmic z-buffer caused cube always be in front of the camera. So, I disable it and set on read depth before skybox drawing and now it works. Thanks everyone for help.

This topic is closed to new replies.

Advertisement