XNA – Skydome

Posted: January 31, 2010 in C#, Game Programming, XNA
Tags: , , ,

xna_logo

Skydome, is a simple sphere that representating virtual sky. Skydome have better realistic looking than skybox but it need advanced texturing. In this article, i’m using simple .x model file (full sphere)  and a sky texture to creating skydome.

First, we need these fields :

GraphicsDevice device;            // our graphics device
ContentManager content;           // content manager for load texture and model
TextureMaterial textureMaterial;  // texture material object
Matrix worldMatrix;               // world matrix for skydome
float rotationY;                  // for rotating shere model
Vector3 position
Model skydomeModel;               // model of full sphere

CullMode cullMode;                // variable that save CullMode value for graphics device
bool depthBufferEnable;           // variable that save depthBufferEnable value for graphics device
bool depthBufferWriteEnable;      // variable that save depthBufferWriteEnable value for graphics device

SetEffectMaterial method that called in Draw() Method


private void SetEffectMaterial(BasicEffect basicEffect, Matrix viewMatrix, Matrix projectionMatrix)
{
    basicEffect.DiffuseColor = Color.White.ToVector3();

    // Texture Material
    basicEffect.Texture = textureMaterial.Texture;
    basicEffect.TextureEnabled = true;

    // Transformation
    basicEffect.World = worldMatrix;
    basicEffect.View = viewMatrix;
    basicEffect.Projection = projectionMatrix;
}

In Update() Method, we set all transformation effect and rotation effect. Oh yeah,  if you decide the skybox center is following camera position, always update position variable.

rotationY += (float)gameTime.ElapsedGameTime.TotalSeconds * 0.05f;

worldMatrix =
    Matrix.CreateScale(80) *
    //Matrix.CreateRotationX(-MathHelper.PiOver2) *
    Matrix.CreateRotationY(rotationY)*
    Matrix.CreateTranslation(position.X, position.Y, position.Y);

Here’s the full code :

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace GameEngine
{
    public class Skydome
    {
        GraphicsDevice device;
        ContentManager content;
        TextureMaterial textureMaterial;
        Matrix worldMatrix;
        float rotationY;
        Vector3 Position
        Model skydomeModel;

        CullMode cullMode;
        bool depthBufferEnable;
        bool depthBufferWriteEnable;

        public Vector3 Position { get { return position; } set { position = value; } }

        public Skydome(GraphicsDevice device, ContentManager content)
        {
            this.device = device;
            this.content = content;
        }

        public void LoadContent()
        {
            skydomeModel = content.Load<Model>(content.RootDirectory + "/" + GameAssetsPath.MODELS + "sphere");
            GetTextureMaterial("sky_dome2", Vector2.One);
        }

        public void LoadContent(string sphereModel, string texture)
        {
            skydomeModel = content.Load<Model>(content.RootDirectory + "/" + GameAssetsPath.MODELS + sphereModel);
            GetTextureMaterial(texture, Vector2.One);
        }

        private void GetTextureMaterial(string textureFilename, Vector2 tile)
        {
            Texture2D texture = content.Load<Texture2D>(content.RootDirectory +
                "/" + GameAssetsPath.TEXTURES +
                textureFilename);
            textureMaterial = new TextureMaterial(texture, tile);
        }

        private void SetEffectMaterial(BasicEffect basicEffect, Matrix viewMatrix, Matrix projectionMatrix)
        {

            basicEffect.DiffuseColor = Color.White.ToVector3();

            // Texture Material
            basicEffect.Texture = textureMaterial.Texture;
            basicEffect.TextureEnabled = true;

            // Transformation
            basicEffect.World = worldMatrix;
            basicEffect.View = viewMatrix;
            basicEffect.Projection = projectionMatrix;
        }

        public void Update(GameTime gameTime, Vector3 camPosition)
        {
            rotationY += (float)gameTime.ElapsedGameTime.TotalSeconds * 0.05f;

            worldMatrix =
                Matrix.CreateScale(80) *
                //Matrix.CreateRotationX(-MathHelper.PiOver2) *
                Matrix.CreateRotationY(rotationY)*
                Matrix.CreateTranslation(position.X, position.Y, position.Z);
        }

        private void SaveGraphicsDeviceState()
        {

            cullMode = device.RenderState.CullMode;
            depthBufferEnable = device.RenderState.DepthBufferEnable;
            depthBufferWriteEnable = device.RenderState.DepthBufferWriteEnable;

        }

        private void RestoreGraphicsDeviceState()
        {

            device.RenderState.CullMode = cullMode;
            device.RenderState.DepthBufferEnable = depthBufferEnable;
            device.RenderState.DepthBufferWriteEnable = depthBufferWriteEnable;
            //device.RenderState.AlphaTestEnable = alphaTestEnable;

        }

        public void Draw(Matrix viewMatrix, Matrix projectionMatrix)
        {
            SaveGraphicsDeviceState();

            device.RenderState.CullMode = CullMode.CullClockwiseFace;
            device.RenderState.DepthBufferEnable = true;
            device.RenderState.DepthBufferWriteEnable = true;

            foreach (ModelMesh modelMesh in skydomeModel.Meshes)
            {
                // We are only rendering models with BasicEffect
                foreach (BasicEffect basicEffect in modelMesh.Effects)
                    SetEffectMaterial(basicEffect, viewMatrix, projectionMatrix);

                modelMesh.Draw();
            }

            device.RenderState.FillMode = FillMode.Solid;
            RestoreGraphicsDeviceState();

        }

    }

    public class TextureMaterial
    {

        Texture2D texture;
        Vector2 uvTile;

        #region Properties
        public Texture2D Texture { get { return texture; } set { texture = value;} }

        public Vector2 UVTile { get { return uvTile; } set { uvTile = value; } }
        #endregion

        public TextureMaterial() { }

        public TextureMaterial(Texture2D texture, Vector2 uvTile)
        {
            this.texture = texture;
            this.uvTile = uvTile;
        }
    }
}

To render skydome in wireframe simply add this line in Draw() method :

device.RenderState.FillMode = FillMode.WireFrame;

Downloadable files which are needed for this acticle :
Skydome Texture
Skydome Source Code
Sphere Model

About these ads
Comments
  1. meblokka says:

    Links to content don’t woks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s