▼XNA Game Studioメモ▼
頂点ライティング


頂点ライティングにより陰を付けて表示するプログラムを作成する。



リソースの追加
  1. DOGA-L2またはL3でテクスチャ付きボックスを作成。
    DOGA-L2/L3はシェアウェアだがモデルの作成は無償で利用可能。
  2. テクスチャ付ボックスとテクスチャをContentにドラッグ&ドロップし、プロパティのビルドアクションでコンパイルを指定。


エフェクトファイルの追加
エフェクトファイル「light_diffuse.fx」を作成し、Contentにドラッグ&ドロップし、プロパティのビルドアクションでコンパイルを指定。
light_diffuse.fx
// グローバル変数
float4x4 g_world;
float4x4 g_world_inv;
float4x4 g_view;
float4x4 g_proj;
float4   g_color0;
float4   g_color1;
float4   g_light_dir;
texture  g_texture;

//テクスチャサンプラ
sampler TextureSampler= 
sampler_state {
    Texture  =<g_texture>;
    MipFilter=NONE;
    MinFilter=LINEAR;
    MagFilter=LINEAR;
    AddressU=Clamp;
    AddressV=Clamp;
};    

//頂点シェーダ
void BasicVS(
        float3 in_pos   :POSITION,
        float3 in_normal:NORMAL,
        float2 in_tex   :TEXCOORD0,
    out float4 out_pos  :POSITION,
    out float4 out_color:COLOR0,
    out float2 out_tex  :TEXCOORD0) {
    //座標変換
    float4 world_pos;
    world_pos=mul(float4(in_pos,1.0f),g_world);
    out_pos=mul(world_pos,g_view);
    out_pos=mul(out_pos,g_proj);

    //テクスチャ座標
    out_tex=in_tex;
    
    //頂点の色計算
    float4 local_light;
    local_light=normalize(mul(g_light_dir,g_world_inv));
    out_color=saturate(g_color0+g_color1*max(0,dot(local_light,in_normal)));
}

//ピクセルシェーダ
void BasicPS(
        float4  in_color :COLOR0,
        float2  in_tex   :TEXCOORD0,
    out float4  out_color:COLOR0,
        uniform bool b_tex) {
    if (b_tex) {
        out_color=in_color*tex2D(TextureSampler,in_tex);
    } else {
        out_color=in_color;
    }
}

//テクニック宣言
technique BasicTech {
    pass P0 {
        vertexShader=compile vs_3_0 BasicVS();
        pixelShader =compile ps_3_0 BasicPS(true);
    }
}


ソースコードの編集
Game.cs
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace LightDiffuseEx {
    public class Game : Microsoft.Xna.Framework.Game {
        //システム
        private GraphicsDeviceManager graphics;   //グラフィックス
        private float                 aspectRatio;//アスペクト比

        //モデル
        private Model   model;  //モデル
        private Texture texture;//テクスチャ
        private Effect  effect; //エフェクト          
        
        //コンストラクタ
        public Game() {
            graphics=new GraphicsDeviceManager(this);
            Content.RootDirectory="Content";
        }

        //初期化
        protected override void Initialize() {
            base.Initialize();
        }

        //グラフィクスコンテントの読み込み
        protected override void LoadContent() {
            //アスペクト比
            aspectRatio=
                (float)GraphicsDevice.Viewport.Width/
                (float)GraphicsDevice.Viewport.Height;
           
            //エフェクト
            effect=Content.Load<Effect>("light_diffuse");
            effect.CurrentTechnique=effect.Techniques["BasicTech"];            
            
            //モデル
            model=Content.Load<Model>("box");             
            foreach (ModelMesh mesh in model.Meshes) {
                for(int i=0;i<mesh.MeshParts.Count;i++) {
                    mesh.MeshParts[i].Effect=effect;

                }            
            }

            //ワールド変換行列
            Matrix world=
                Matrix.CreateTranslation(new Vector3(0.0f,0.0f,0.0f));//位置
            effect.Parameters["g_world"].SetValue(world);
            effect.Parameters["g_world_inv"].SetValue(Matrix.Invert(world));

            //ビュー変換行列
            Matrix view=Matrix.CreateLookAt(
                new Vector3(5.0f,5.0f,5.0f),
                Vector3.Zero,   
                Vector3.Up             
            );            
            effect.Parameters["g_view"].SetValue(view);

            //射影変換行列
            Matrix projection=Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45.0f),
                aspectRatio,          
                1.0f,                  
                100.0f
            );
            effect.Parameters["g_proj"].SetValue(projection);

            //自発光色
            Vector4 emissive=new Vector4(0.1f,0.1f,0.1f,1.0f);
            effect.Parameters["g_color0"].SetValue(emissive);

            //拡散反射色
            Vector4 diffuse=new Vector4(0.8f,0.8f,0.8f,1.0f);
            effect.Parameters["g_color1"].SetValue(diffuse);

            //ライト
            Vector4 light_dir=new Vector4(0.5f,1.0f,-2.0f,0.0f);
            effect.Parameters["g_light_dir"].SetValue(light_dir);
            
            //テクスチャ
            texture=Content.Load<Texture2D>("mokume2");
            effect.Parameters["g_texture"].SetValue(texture); 

            //コミット
            effect.CommitChanges();      
        }

        //グラフィクスコンテントの解放
        protected override void UnloadContent() {
        }

        //更新
        protected override void Update(GameTime gameTime) {
            base.Update(gameTime);
        }

        //描画
        protected override void Draw(GameTime gameTime) {
            //背景色
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);

            //モデルの描画
            foreach (ModelMesh mesh in model.Meshes) {
                mesh.Draw();
            }          

            //ベースの描画
            base.Draw(gameTime);
        }   
    }
}



−戻る−