|開発環境|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#){{ // XnaTexture2D2 テクスチャ移動 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; Texture2D texture; EffectParameter fxLat; EffectParameter fxLon; float lat = 0; float lon = 0; // fps int sec; int draw = 0; int fps = 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); fxLat = effect.Parameters["lat"]; fxLon = effect.Parameters["lon"]; 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); base.LoadContent(); } protected override void Update(GameTime gameTime) { float deltaLat = 0; float deltaLon = 0; KeyboardState kState = Keyboard.GetState(); if (kState.IsKeyDown(Keys.Escape)) Exit(); if (kState.IsKeyDown(Keys.Up)) deltaLat = -0.005f; if (kState.IsKeyDown(Keys.Down)) deltaLat = 0.005f; if (kState.IsKeyDown(Keys.Left)) deltaLon = -0.005f; if (kState.IsKeyDown(Keys.Right)) deltaLon = 0.005f; if (deltaLat != 0) { lat += deltaLat; if (lat < -1.0f) lat += 2.0f; if (1.0f < lat) lat -= 2.0f; fxLat.SetValue(lat); } if (deltaLon != 0) { lon += deltaLon; fxLon.SetValue(lon); } 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); } // fps draw++; if (gameTime.TotalGameTime.Seconds != sec) { fps = draw; draw = 0; sec = gameTime.TotalGameTime.Seconds; } sprite.Begin(); string text = string.Format("fps={0} lat={1:f2} lon={2:f2}", fps, lat, lon); sprite.DrawString(font, text, new Vector2(0, 0), Color.Red); sprite.End(); base.Draw(gameTime); } } } }} Effect1.fx #highlight(){{ // スクロール texture WorldMap; float lat; float lon; 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 { float2 t; t.x = frac(input.TexCoord.x + lon); // t.y = frac(input.TexCoord.y + lat); t.y = abs(input.TexCoord.y + 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(){{ // モルワイデ風 texture WorldMap; float lat; // 未使用 float lon; 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); if (width < abs(x) || width == 0.0f) { discard; } float2 t; t.x = frac((x / width) * 0.5f + 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(); } } }}