2
\$\begingroup\$

I try to create a small and simple 3D games on XNA.

I recently started to add a skyBox after added a sun in my game with the sample by Microsoft here http://xbox.create.msdn.com/en-US/education/catalog/sample/lens_flare . The problem is , after add a skybox . My sun reacts strangely, it is no longer displayed. And occasionally, it bug. Appears and disappears repeatedly. Certainly because the sun is behind my skybox.

Youtube

I upload a video on YouTube of my problem too ;-) : https://www.youtube.com/watch?v=i8mdaibMqA4&feature=youtu.be

Problem identical

My problem is same as this : OcclusionQuery: how to ignore some objects?

Here is my file "SkyBox.fx"

    float4x4 WVP;
    float4 TextureColor;
    float AmountColorMix;


    float Depth;

    TextureCube tex;
    sampler cubeSampler = sampler_state {
        texture = <tex>;
        AddressU = CLAMP;
        AddressV = CLAMP;
    };

    struct VertexShaderInput
    {
        float4 Position : POSITION0;
    };

    struct VertexShaderOutput
    {
        float4 Position : POSITION0;
        float3 PosTex   : TEXCOORD0;
    };

    VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
    {
        VertexShaderOutput output;
        output.Position = mul(input.Position, WVP).xyww;
        output.PosTex = input.Position;

        return output;
    }

    float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    {
        float4 color = texCUBE(cubeSampler,input.PosTex);

        return lerp(color, TextureColor, AmountColorMix);
    }


    technique Technique1
    {
        pass Pass1
        {
            CullMode = None;
            VertexShader = compile vs_3_0 VertexShaderFunction();
            PixelShader = compile ps_3_0 PixelShaderFunction();
        }
    }

Create and Draw the SkyBox (function)

        /* ********************************* */
        // Draw the SkyBox         
        /* ********************************* */
        #region DrawSky
        public void DrawSky()
        {
            arcadia.Game.GraphicsDevice.SetVertexBuffer(skyVertices);
            arcadia.Game.GraphicsDevice.Indices = skyIndices;

            skyEffect.Parameters["WVP"].SetValue(Matrix.CreateTranslation(arcadia.camera.Position) * arcadia.camera.View * arcadia.camera.Projection);
            skyEffect.Parameters["TextureColor"].SetValue(arcadia.lensFlare.ColorSun.ToVector4());
            skyEffect.Parameters["AmountColorMix"].SetValue(0.25f);
            skyEffect.CurrentTechnique.Passes[0].Apply();


            arcadia.Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, number_of_vertices, 0, number_of_indices / 3);

        }
        #endregion

        #region Creating a basic VertexBuffer
        void CreateCubeVertexBuffer()
        {
            Vector3[] cubeVertices = new Vector3[number_of_vertices];

            cubeVertices[0] = new Vector3(-1, -1, -1);
            cubeVertices[1] = new Vector3(-1, -1, 1);
            cubeVertices[2] = new Vector3(1, -1, 1);
            cubeVertices[3] = new Vector3(1, -1, -1);
            cubeVertices[4] = new Vector3(-1, 1, -1);
            cubeVertices[5] = new Vector3(-1, 1, 1);
            cubeVertices[6] = new Vector3(1, 1, 1);
            cubeVertices[7] = new Vector3(1, 1, -1);

            VertexDeclaration VertexPositionDeclaration = new VertexDeclaration
            (
                new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)
            );

            skyVertices = new VertexBuffer(arcadia.Game.GraphicsDevice, VertexPositionDeclaration, number_of_vertices, BufferUsage.WriteOnly);
            skyVertices.SetData<Vector3>(cubeVertices);
        }
        #endregion

        #region Creating a basic IndexBuffer
        void CreateCubeIndexBuffer()
        {
            UInt16[] cubeIndices = new UInt16[number_of_indices];

            //bottom face
            cubeIndices[0] = 0;
            cubeIndices[1] = 2;
            cubeIndices[2] = 3;
            cubeIndices[3] = 0;
            cubeIndices[4] = 1;
            cubeIndices[5] = 2;

            //top face
            cubeIndices[6] = 4;
            cubeIndices[7] = 6;
            cubeIndices[8] = 5;
            cubeIndices[9] = 4;
            cubeIndices[10] = 7;
            cubeIndices[11] = 6;

            //front face
            cubeIndices[12] = 5;
            cubeIndices[13] = 2;
            cubeIndices[14] = 1;
            cubeIndices[15] = 5;
            cubeIndices[16] = 6;
            cubeIndices[17] = 2;

            //back face
            cubeIndices[18] = 0;
            cubeIndices[19] = 7;
            cubeIndices[20] = 4;
            cubeIndices[21] = 0;
            cubeIndices[22] = 3;
            cubeIndices[23] = 7;

            //left face
            cubeIndices[24] = 0;
            cubeIndices[25] = 4;
            cubeIndices[26] = 1;
            cubeIndices[27] = 1;
            cubeIndices[28] = 4;
            cubeIndices[29] = 5;

            //right face
            cubeIndices[30] = 2;
            cubeIndices[31] = 6;
            cubeIndices[32] = 3;
            cubeIndices[33] = 3;
            cubeIndices[34] = 6;
            cubeIndices[35] = 7;

            skyIndices = new IndexBuffer(arcadia.Game.GraphicsDevice, IndexElementSize.SixteenBits, number_of_indices, BufferUsage.WriteOnly);
            skyIndices.SetData<UInt16>(cubeIndices);

        }
        #endregion
\$\endgroup\$
  • \$\begingroup\$ What do you mean by "depth scale?" It's not clear. \$\endgroup\$ – user1430 Jun 17 '14 at 20:29
  • \$\begingroup\$ I mean Depth Scale , because i have a skybox and a sun in my game. the problem is my sun is outside the skybox. I want make my skybox bigger. My problem is exacly same as this gamedev.stackexchange.com/questions/64624/… . I see the guy answer => You could alternatively achieve the same result by writing a depth of 1.0f from your pixel shader . Do you have some idea ? \$\endgroup\$ – Mehdi Bugnard Jun 17 '14 at 20:33
  • 1
    \$\begingroup\$ It should not be possible to make your skybox bigger. The entire idea behind a skybox is that it cover the bounds of your viewing volume. What you probably want is simply not to depth test your sun against the sky at all. Think of the sun as an object infinitely far away for the purposes of lighting and for this as well. Basically, just stop writing to the depth buffer when you draw your skybox and assign your sun the depth of your far plane and you will be good. \$\endgroup\$ – Andon M. Coleman Jun 18 '14 at 1:00
  • \$\begingroup\$ Hi Andon M. Coleman . Thanks a lot for your answer. I already assign the depth or my far plane to the sun. But i don't know what you mean by "stop writing to the depth buffer" when i draw my skybox. I add now in my description the way , how i draw the skybox. I hope you can show me a example . Thanks again \$\endgroup\$ – Mehdi Bugnard Jun 18 '14 at 8:28
  • \$\begingroup\$ I change the description and add the logic code of my skybox (Create and Draw skybox) and upload a video on YouTube (the link is on the description) . I hope it's more clear like this ;-) \$\endgroup\$ – Mehdi Bugnard Jun 18 '14 at 9:18
2
\$\begingroup\$

Finally i solve and fix the problem by myself .

Add

GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;

before draw the skyBox

And Add

arcadia.Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

after finish draw the skyBox

Full Code:

#region DrawSky
public void DrawSky()
{

    arcadia.Game.GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead;

    arcadia.Game.GraphicsDevice.SetVertexBuffer(skyVertices);
    arcadia.Game.GraphicsDevice.Indices = skyIndices;

    skyEffect.Parameters["WVP"].SetValue(Matrix.CreateTranslation(arcadia.camera.Position) * arcadia.camera.View * arcadia.camera.Projection);
    skyEffect.Parameters["TextureColor"].SetValue(arcadia.lensFlare.ColorSun.ToVector4());
    skyEffect.Parameters["AmountColorMix"].SetValue(0.25f);
    skyEffect.CurrentTechnique.Passes[0].Apply();


    arcadia.Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, number_of_vertices, 0, number_of_indices / 3);


    arcadia.Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
}
#endregion
\$\endgroup\$
1
\$\begingroup\$

One way of handling this is to modify the depth range in your viewport when drawing the skybox.

For XNA you would set both MinDepth and MaxDepth to 1, leaving the other members the same as your main viewport, like so:

Viewport.MinDepth = 1.0f;
Viewport.MaxDepth = 1.0f;

This will ensure that your skybox is always drawn to the back of the scene, and using this technique you don't need to worry about the skybox size at all: you could even draw it as a 10x10x10 cube around the view point and it would still work. This will also work well with any other kind of object you want to add in the sky (birds, etc).

Another way is to output a depth of 1.0f from your pixel shader, but that's generally not recommended as it can interfere with your GPU's early-Z optimizations.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.