Tuesday, December 4, 2012

7: Skybox System Updated

       

       Welcome back gamers to my next blog post. Recently, I have made significant improvements to the sky-box system in the game engine. Before the sky-box would rotate too much wherever the player looked. Now it stays in place and the visuals have improved since then. I am thinking about creating billboard clouds in the future and hopefully have a day & night cycle system functioning. The Cyclone Engine creates a box and places the textures on each of the sides of the box. So I had to determine which image to use for the top and the sides to make it appear 3D when the player moves around in the world.


How to Add a Skybox
       A skybox is merely nothing more than a mesh. To accompany the mesh, we will need to load some textures to along with it. We will create two variables: one to store the model, and an extra one to store the textures. Add these variables to the top of your code:

Texture2D[] skyboxTextures;
Model skybodModel;


We would normally use the LoadModel method to load our skybox, but we cannot do this since that method doesn't load the textures. We will fix this by overloading that method. We shall create a new version of the method, with the same name, but with different arguments.

private Model LoadModel(string assetName, out Texture2D[] textures)
        {
            Model newModel = Content.Load<Model>(assetName);
            textures = new Texture2D[newModel.Meshes.Count];
            int i = 0;

            foreach (ModelMesh mesh in newModel.Meshes)
            {
                foreach (BasicEffect currentEffect in mesh.Effects)
                {
                    textures[i++] = currentEffect.Texture;
                }
            }

            foreach (ModelMesh mesh in newModel.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    meshPart.Effect = skyEffect.Clone();
                }
            }

            return newModel;
        }


We call this method from within the LoadContent method:

 skyboxModel = LoadModel("skybox", out skyboxTextures);


Now that we have the skybox loading, we need to draw it. The issue with my previous skybox program was that it would move relative to the player's movement when you looked up or down. The skybox should always be at a constant distance from the player. This will make the skybox appear as if it's far away. So as the player moves, the skybox will move according to the camera's position. That way, the player will always remain in the middle of the skybox.

public void DrawSkybox( )
        {
            SamplerState ss = new SamplerState();
            ss.AddressU = TextureAddressMode.Clamp;
            ss.AddressV = TextureAddressMode.Clamp;
            GraphicsDevice.SamplerStates[0] = ss;

            DepthStencilState dss = new DepthStencilState();
            dss.DepthBufferEnable = false;
            GraphicsDevice.DepthStencilState = dss;

            Matrix[] skyboxTransforms = new Matrix[skyBoxModel.Bones.Count];
            skyBoxModel.CopyAbsoluteBoneTransformsTo(skyboxTransforms);
            int i = 0;
            foreach (ModelMesh mesh in skyBoxModel.Meshes)
            {
                foreach (Effect currentEffect in mesh.Effects)
                {
                    Matrix worldMatrix = Matrix.CreateScale(50000f) * skyboxTransforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(camera.Postion + new Vector3(0, 5.2f, 0));
                    currentEffect.CurrentTechnique = currentEffect.Techniques["Sky"];
                    currentEffect.Parameters["xWorld"].SetValue(skyboxTransforms[mesh.ParentBone.Index] * worldMatrix);
                    currentEffect.Parameters["xViewProjection"].SetValue(camera.View * camera.Projection);
                    currentEffect.Parameters["xTexture"].SetValue(skyBoxTextures[i++]);

                }
                mesh.Draw();
            }

        }

After clearing the screen, you need to call this method as the first line in your Draw method:

DrawSkybox( );


See how the skybox turned out in the images below.














No comments:

Post a Comment