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

参考

Game1.cs
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace XnaHwiMesh
{
    struct VertexPosition : IVertexType
    {
        public Vector3 Position;
 
        public VertexPosition(Vector3 position)
        {
            Position = position;
        }
 
        static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration(
            new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0)
        );
 
        VertexDeclaration IVertexType.VertexDeclaration { get { return VertexDeclaration; } }
    }
 
    class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        Effect effect;
        Model model;
        VertexBuffer instanceDataStream;
        Vector3 CameraPos;
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }
 
        protected override void LoadContent()
        {
            effect = Content.Load<Effect>("CustomEffect");
            model = Content.Load<Model>("Box");
 
            CameraPos = new Vector3(10, 10, 10);
 
            effect.Parameters["World"].SetValue(Matrix.Identity);
            effect.Parameters["View"].SetValue(Matrix.CreateLookAt(
                CameraPos, Vector3.Zero, Vector3.Up));
            effect.Parameters["Projection"].SetValue(Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 1, 100));
            effect.Parameters["LightPos"].SetValue(Vector3.Up);
            effect.Parameters["ambient"].SetValue(new Vector3(0, 0.0543f, 0.526f));
            effect.Parameters["diffuselight"].SetValue(new Vector3(1, 1, 1));
 
            foreach (var mesh in model.Meshes)
            {
                foreach (var mpart in mesh.MeshParts)
                {
                    mpart.Effect = effect;
                }
            }
 
            VertexPosition[] vp = new VertexPosition[2];
            vp[0] = new VertexPosition(Vector3.Zero);
            vp[1] = new VertexPosition(new Vector3(0, 2, 0));
 
            instanceDataStream = new VertexBuffer(GraphicsDevice,
                typeof(VertexPosition), 2, BufferUsage.WriteOnly);
            instanceDataStream.SetData(vp);
 
            base.LoadContent();
        }
 
        protected override void Update(GameTime gameTime)
        {
            KeyboardState state = Keyboard.GetState();
            if (state[Keys.Escape] == KeyState.Down) Exit(); 
 
            base.Update(gameTime);
        }
 
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
 
            foreach (var mesh in model.Meshes)
            {
                MeshDraw(mesh);
            }
            base.Draw(gameTime);
        }
 
        VertexDeclaration CreateVertexDeclaration(VertexElement[] MeshPartElements)
        {
            List<VertexElement> elements = new List<VertexElement>();
            foreach (VertexElement vElement in MeshPartElements)
            {
                elements.Add(vElement);
            }
            elements.Add(new VertexElement(
                1, VertexElementFormat.Vector3, VertexElementUsage.Position, 1));
 
            return new VertexDeclaration(elements.ToArray());
        }
 
        void MeshDraw(ModelMesh mesh)
        {
            foreach (ModelMeshPart mpart in mesh.MeshParts)
            {
                Effect effect = mpart.Effect;
                foreach (var pass in effect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    if (0 < mpart.NumVertices)
                    {
                        VertexBufferBinding[] bindings;
                        bindings = new VertexBufferBinding[2];
                        bindings[0] = new VertexBufferBinding(mpart.VertexBuffer, 0);
                        bindings[1] = new VertexBufferBinding(instanceDataStream, 0, 1);
                        GraphicsDevice.SetVertexBuffers(bindings);
                        GraphicsDevice.Indices = mpart.IndexBuffer;
                        GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                            mpart.NumVertices, mpart.StartIndex, mpart.PrimitiveCount, 2);
                    }
                }
            }
        }
    }
}
 

CustomEffect.fx
float4x4 World;
float4x4 View;
float4x4 Projection;
 
float3 LightPos;
float3 ambient : AMBIENT;
float3 diffuselight : DIFFUSE;
 
struct VertexShaderInput
{
	float4 Position : POSITION0;
	float3 Normal : Normal0;
};
 
struct VertexShaderOutput
{
	float4 Position : POSITION0;
	float3 Normal : Normal0;
};
 
VertexShaderOutput VertexShaderFunction(VertexShaderInput input, float3 transform : POSITION1)
{
	VertexShaderOutput output;
 
	float4 worldPosition = mul(input.Position + float4(transform, 0), World);
	float4 viewPosition = mul(worldPosition, View);
	output.Position = mul(viewPosition, Projection);
 
	output.Normal = mul(float4(input.Normal, 1), World);
	output.Normal = normalize(output.Normal);
 
	return output;
}
 
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	return float4(ambient + diffuselight * saturate(dot(input.Normal, normalize(LightPos))), 1);
}
 
technique Technique1
{
	pass Pass0
	{
		VertexShader = compile vs_3_0 VertexShaderFunction();
		PixelShader = compile ps_3_0 PixelShaderFunction();
	}
}
 
最終更新:2012年12月08日 20:38