Mango Teapot ② Teapot クラス
Mango Teapot は Windows Phone 7.5 の AR アプリケーション サンプルです。ソースコードは MangoTeapot.codeplex.com にあります。
以前 Silverlight 5 (beta) で Teapot を描画したとき、頂点バッファとインデックスバッファを基に Blinn-Phong シェーダーで描画する Teapot クラスを作成しました。そのときの Teapot クラスに以下の変更を加えました。おもに XNA 4.0 への対応とシェーダーから固定機能(BasicEffect)への移行です。
IVertexType
XNA 4.0 ではカスタム頂点フォーマットを定義する際に IVertexType を継承しなければならないので、それに対応しました。
private struct VertexPositionNormal : IVertexType
{
private Vector3 _vertexPosition;
private Vector3 _vertexNormal;
public Vector3 Position
{
get { return _vertexPosition; }
set { _vertexPosition = value; }
}
public Vector3 Normal
{
get { return _vertexNormal; }
set { _vertexNormal = value; }
}
public VertexPositionNormal(
float positionX, float positionY, float positionZ,
float normalX, float normalY, float normalZ)
{
_vertexPosition = new Vector3(positionX, positionY, positionZ);
_vertexNormal = new Vector3(normalX, normalY, normalZ);
}
public static readonly VertexDeclaration VertexDeclaration =
new VertexDeclaration(
new VertexElement(0, VertexElementFormat.Vector3,
VertexElementUsage.Position, 0),
new VertexElement(12, VertexElementFormat.Vector3,
VertexElementUsage.Normal, 0));
VertexDeclaration IVertexType.VertexDeclaration
{
get { return VertexDeclaration; }
}
}
BasicEffect
Silverlight 5 では BasicEffect が使えずカスタム シェーダー エフェクトしか使えなかったのですが、逆に Windows Phone ではカスタム シェーダー エフェクトが使えず BasicEffect しか使えません。BasicEffect のデフォルト設定に(EnableDefaultLighting)、ピクセル単位のシェーディングを有効にしました(PreferPerPixelLighting)。いちばんマンゴー色に似ていたので、ディフューズ色を Color.Goldenrod にしました。
private BasicEffect effect;
// BasicEffect
effect = new BasicEffect(device);
effect.EnableDefaultLighting();
effect.DiffuseColor = Color.Goldenrod.ToVector3();
effect.PreferPerPixelLighting = true;
もちろん World, View, Projection 行列はシェーダー レジスターではなく、BasicEffect オブジェクトの各プロパティに代入します。
// Set BasicEffect parameters
effect.World = this.World;
effect.View = this.View;
effect.Projection = this.Projection;
effect.SpecularPower = this.Shininess;
また、XNA 4.0 から描画時のエフェクトの適用は、Begin(), End() ではなく Apply() メソッドになりました。
foreach (EffectPass p in effect.CurrentTechnique.Passes)
{
p.Apply();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList,
0, 0, numVertices, 0, numElements);
}