「VCS/XnaTexture2D3」の編集履歴(バックアップ)一覧に戻る

VCS/XnaTexture2D3 - (2012/12/19 (水) 16:21:10) のソース

|開発環境|Microsoft Visual C# 2010 Express (SP1)|
|実行環境|Microsoft Windows XP Home Edition (SP3)|
|プロジェクトの種類|Windows Game (4.0)|
|プロジェクト名|XnaTexture2D|

+スクロール
+半球

参考
-[[Planet Earth Texture Maps>http://planetpixelemporium.com/earth.html]]

Game1.cs
#highlight(c#){{
// XnaTexture2D3 緯経修正
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace XnaTexture2D
{
    class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch sprite;
        SpriteFont font;
        VertexBuffer vertexBuffer;
        Effect effect;
        BasicEffect basicEffect;
        Texture2D texture;
        VertexPositionColor[] cross;

        EffectParameter fxLat;
        EffectParameter fxLon;
        EffectParameter fxScale;
        float lat = 0;
        float lon = 135;
        float scale = 1;

        // fps
        int fpsSec;
        int fpsDraw = 0;
        int fpsCount = 0;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }

        protected override void LoadContent()
        {
            sprite = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("SpriteFont1");
            texture = Content.Load<Texture2D>("earthmap1k");

            effect = Content.Load<Effect>("Effect1");
            effect.Parameters["WorldMap"].SetValue(texture);
            effect.Parameters["aspect"].SetValue(GraphicsDevice.Viewport.AspectRatio);
            fxLat = effect.Parameters["lat"];
            fxLon = effect.Parameters["lon"];
            fxScale = effect.Parameters["scale"];
            fxLat.SetValue(lat / 180);
            fxLon.SetValue(lon / 360);
            fxScale.SetValue(scale);

            basicEffect = new BasicEffect(GraphicsDevice);

            // 地図
            VertexPositionTexture[] vertices = new VertexPositionTexture[4];
            vertices[0] = new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 0));
            vertices[1] = new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0));
            vertices[2] = new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1));
            vertices[3] = new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1));

            vertexBuffer = new VertexBuffer(GraphicsDevice,
                typeof(VertexPositionTexture), 4, BufferUsage.WriteOnly);
            vertexBuffer.SetData(vertices);

            // 照準
            cross = new VertexPositionColor[4];
            cross[0] = new VertexPositionColor(new Vector3(-0.05f, 0, 0), Color.White);
            cross[1] = new VertexPositionColor(new Vector3(0.05f, 0, 0), Color.White);
            cross[2] = new VertexPositionColor(new Vector3(0, -0.1f, 0), Color.White);
            cross[3] = new VertexPositionColor(new Vector3(0, 0.1f, 0), Color.White);

            base.LoadContent();
        }

        protected override void Update(GameTime gameTime)
        {
            float deltaLat = 0;
            float deltaLon = 0;
            float deltaScale = 0;

            KeyboardState kState = Keyboard.GetState();
            if (kState.IsKeyDown(Keys.Escape)) Exit();
            if (kState.IsKeyDown(Keys.Up)) deltaLat = 1;
            if (kState.IsKeyDown(Keys.Down)) deltaLat = -1;
            if (kState.IsKeyDown(Keys.Left)) deltaLon = -1;
            if (kState.IsKeyDown(Keys.Right)) deltaLon = 1;
            if (kState.IsKeyDown(Keys.PageUp)) deltaScale = 0.1f;
            if (kState.IsKeyDown(Keys.PageDown)) deltaScale -= 0.1f;

            if (deltaLat != 0)
            {
                lat = MathHelper.Clamp(lat + deltaLat / scale, -89.9f, 89.9f);
                fxLat.SetValue(lat / 180); // -0.5 - 0.5
            }
            if (deltaLon != 0)
            {
                lon += deltaLon / scale;
                if (lon <= -180) lon += 360;
                if (180 < lon) lon -= 360;
                fxLon.SetValue(lon / 360); // -0.5 - 0.5
            }
            if (deltaScale != 0)
            {
                scale = MathHelper.Clamp(scale + deltaScale, 1, 5);
                fxScale.SetValue(scale);
            }

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;

            GraphicsDevice.SetVertexBuffer(vertexBuffer);
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
            }

            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, cross, 0, 2);
            }

            // fps
            fpsDraw++;
            if (gameTime.TotalGameTime.Seconds != fpsSec)
            {
                fpsCount = fpsDraw;
                fpsDraw = 0;
                fpsSec = gameTime.TotalGameTime.Seconds;
            }

            sprite.Begin();
            string text = string.Format("fps={0} lat={1:f1} lon={2:f1} scale={3:f1}",
                fpsCount, lat, lon, scale);
            sprite.DrawString(font, text, new Vector2(0, 0), Color.Red);
            sprite.End();

            base.Draw(gameTime);
        }
    }
}
}}

Effect1.fx
#highlight(){{
// XnaTexture2D3 スクロール
texture WorldMap;
float lat;
float lon;
float aspect; // 未使用
float scale;

sampler TextureSampler = sampler_state
{
	texture = <WorldMap>;
	minfilter = linear;
	magfilter = linear;
};

struct VertexShaderInput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
	VertexShaderOutput output;
	output.Position = input.Position;
	output.TexCoord = input.TexCoord;
	return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	float x = input.TexCoord.x * 2.0f - 1.0f; // -1 - 1
	float y = input.TexCoord.y * 2.0f - 1.0f; // -1 - 1
	float2 t;
	t.x = frac((x / scale + 1.0f) * 0.5f + lon);
	t.y = abs((y / scale + 1.0f) * 0.5f - lat);
	if (1.0f < t.y)
	{
		t.y = 2.0f - t.y;
	}
	return tex2D(TextureSampler, t);
}

technique Technique1
{
	pass Pass1
	{
		VertexShader = compile vs_2_0 VertexShaderFunction();
		PixelShader = compile ps_2_0 PixelShaderFunction();
	}
}
}}

Effect1.fx
#highlight(){{
// XnaTexture2D3 半球
texture WorldMap;
float lat; // 未使用
float lon;
float aspect;
float scale; // 未使用

sampler TextureSampler = sampler_state
{
	texture = <WorldMap>;
	minfilter = linear;
	magfilter = linear;
};

struct VertexShaderInput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
	VertexShaderOutput output;
	output.Position = input.Position;
	output.TexCoord = input.TexCoord;
	return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	float x = input.TexCoord.x * 2.0f - 1.0f; // -1 - 1
	float y = input.TexCoord.y * 2.0f - 1.0f; // -1 - 1
	float width = sqrt(1.0f - y * y);
	x *= aspect;
	if (width < abs(x) || width <= 0.0f)
	{
		discard;
	}
	float2 t;
	t.x = frac((0.5f * x / width + 1.0f) * 0.5f + lon);
	t.y = input.TexCoord.y;
	return tex2D(TextureSampler, t);
}

technique Technique1
{
	pass Pass1
	{
		VertexShader = compile vs_2_0 VertexShaderFunction();
		PixelShader = compile ps_2_0 PixelShaderFunction();
	}
}
}}