베이직 이펙트 라이트

페이지 업데이트 :
페이지 생성 날짜 :

요약

BasicEffect의 조명 부분과 관련된 파라미터를 조작하여 모델이 표시되는 방식을 확인합니다.

운영 환경

필수 구성 요소

지원되는 XNA 버전
  • 4.0
지원되는 플랫폼
  • Windows(XP SP2 이상, Vista, 7)
  • 엑스박스 360
  • 윈도우 폰 7
Windows 필수 버텍스 셰이더 버전 2.0
Windows 필수 픽셀 셰이더 버전 2.0

운영 환경

플랫폼
  • 윈도우 7
  • 엑스박스 360
  • 윈도우 폰 7

샘플로 작업하는 방법

작동 키보드Xbox 360 컨트롤러마우스 터치
변경할 매개 변수를 선택합니다 ↑、↓ 왼쪽 스틱 ↑, ↓ 왼쪽 버튼 -
파라미터 변경 ←、→ 왼쪽 스틱 ←, → ←→ 드래그 -

물질

조명은 물질의 그림자를 나타내는 데 사용됩니다. XNA에서 조명은 환경 설정 중 하나로 설정되지 않고 개별 효과로 설정됩니다.

BasicEffect에서 사용할 수 있는 세 개의 평행 광원이 있으며 각 광원에는 다음과 같은 매개변수가 있습니다.

사용 라이트를 사용할 수 있는지 여부를 설정합니다.
디퓨즈 컬러(DiffuseColor) 조명의 색상입니다. 최종 색상은 물질의 색상과 결합하여 출력됩니다.
스페큘러 컬러(SpecularColor) 반사된 빛의 색상입니다. 그것은 물질의 반사 색상에 영향을 미칩니다.
방향 라이트의 방향입니다.

개별 라이트에 공통적인 속성도 있습니다.

AmbientLightColor (앰비언트 라이트 컬러) 광원과 독립적으로 물질의 밝기를 설정합니다.
픽셀 라이팅 선호(PreferPerPixelLighting) 조명을 픽셀 단위로 계산할지 여부를 지정할 수 있습니다.

빛의 변화 이미지

아래 이미지는 조명의 다양한 값을 보여줍니다. 샘플에서는 세 개의 조명을 모두 사용할 수 있지만 아래 이미지에서는 하나의 조명만 사용하여 표시합니다.

초기 상태

샘플 모델 데이터를 로드한 직후의 상태입니다.

初期状態

확산(빨간색) 1
확산(녹색) 0.96
확산(파란색) 0.80
스페큘러(빨간색) 1
스페큘러(녹색) 0.96
스페큘러(파란색) 0.80
방향 X -0.52
방향 Y -0.57
방향 Z -0.62
AmbientLightColor (레드) 0.05
AmbientLightColor (녹색) 0.09
AmbientLightColor (파랑) 0.18
픽셀 라이팅 선호(PreferPerPixelLighting) 거짓

DiffuseColor 수정

라이트의 DiffuseColor 를 변경합니다. 빨간색과 파란색은 0으로 설정되고 녹색은 1로 설정되었기 때문에 모델의 녹색 부분만 강조 표시됩니다. (빨간색과 파란색도 희미하게 보이지만 이는 주변광 때문입니다.)

DiffuseColor 変更

확산(빨간색) 0
확산(녹색) 1
확산(파란색) 0
스페큘러(빨간색) 1
스페큘러(녹색) 0.96
스페큘러(파란색) 0.80
방향 X -0.52
방향 Y -0.57
방향 Z -0.62
AmbientLightColor (레드) 0.05
AmbientLightColor (녹색) 0.09
AmbientLightColor (파랑) 0.18
픽셀 라이팅 선호(PreferPerPixelLighting) 거짓

SpecularColor 변경

반사된 빛의 색상 변경. 초록색만 설정되어 있기 때문에 반사부의 색은 초록색 요소뿐입니다.

SpecularColor 変更

확산(빨간색) 1
확산(녹색) 0.96
확산(파란색) 0.80
스페큘러(빨간색) 0
스페큘러(녹색) 1
스페큘러(파란색) 0
방향 X -0.52
방향 Y -0.57
방향 Z -0.62
AmbientLightColor (레드) 0.05
AmbientLightColor (녹색) 0.09
AmbientLightColor (파랑) 0.18
픽셀 라이팅 선호(PreferPerPixelLighting) 거짓

방향 변경

방향을 변경하여 조명의 방향을 변경할 수 있습니다. 일반적으로 방향만 사용되므로 벡터가 정규화됩니다.

Direction 変更

확산(빨간색) 1
확산(녹색) 0.96
확산(파란색) 0.80
스페큘러(빨간색) 1
스페큘러(녹색) 0.96
스페큘러(파란색) 0.80
방향 X 0.67
방향 Y 0.54
방향 Z -0.34
AmbientLightColor (레드) 0.05
AmbientLightColor (녹색) 0.09
AmbientLightColor (파랑) 0.18
픽셀 라이팅 선호(PreferPerPixelLighting) 거짓

AmbientLightColor 변경

빨간색과 파란색 주변 조명이 최대화되고 녹색이 0으로 설정됩니다. 빛이 비치지 않는 부분을 보면 녹색, 빨간색, 파란색 음영의 차이를 명확하게 알 수 있습니다.

AmbientLightColor 変更

확산(빨간색) 1
확산(녹색) 0.96
확산(파란색) 0.80
스페큘러(빨간색) 1
스페큘러(녹색) 0.96
스페큘러(파란색) 0.80
방향 X -0.52
방향 Y -0.57
방향 Z -0.62
AmbientLightColor (레드) 1
AmbientLightColor (녹색) 0
AmbientLightColor (파랑) 1
픽셀 라이팅 선호(PreferPerPixelLighting) 거짓

PreferPerPixelLighting 수정

픽셀 단위 조명 계산을 허용하려면 PreferPerPixelLighting을 True로 설정합니다. 그림에서는 잘 보이지 않지만, 꼭짓점 조명의 경우 다각형의 경계가 어떻게든 보이지만, 픽셀 단위 조명의 경우 매우 부드러운 그림자를 표현할 수 있습니다.

그런데 픽셀 셰이더 2.0을 지원하지 않는 경우 PreferPerPixelLighting 속성을 사용할 수 없습니다. 또한 여러 개의 조명을 사용하면 이상하게 보일 수 있습니다.

PreferPerPixelLighting 変更

확산(빨간색) 1
확산(녹색) 0.96
확산(파란색) 0.80
스페큘러(빨간색) 1
스페큘러(녹색) 0.96
스페큘러(파란색) 0.80
방향 X -0.52
방향 Y -0.57
방향 Z -0.62
AmbientLightColor (레드) 0.05
AmbientLightColor (녹색) 0.09
AmbientLightColor (파랑) 0.18
픽셀 라이팅 선호(PreferPerPixelLighting)
Per-vertex lighting픽셀당 조명
頂点単位のライティング ピクセル単位のライティング

조명에 대한 파라미터 클래스 정의(Parameter Class Definitions for Lights)

BasicEffect는 여러 개의 라이트를 가질 수 있기 때문에, 라이트 파라미터를 설정하기 위한 클래스를 만들었습니다. 파라미터는 BasicEffect 라이트(BasicDirectionalLight)에 설정할 수 있는 파라미터와 같습니다.

/// <summary>
/// ライトパラメータ
/// </summary>
public class LightParameter
{
    /// <summary>
    /// ライト有効フラグ
    /// </summary>
    public bool Enabled;

    /// <summary>
    /// ディフューズカラー
    /// </summary>
    public Vector3 DiffuseColor;

    /// <summary>
    /// スペキュラーカラー
    /// </summary>
    public Vector3 SpecularColor;

    /// <summary>
    /// ライトの方向
    /// </summary>
    public Vector3 Direction;
}

라이트를 설정하는 데 필요한 매개변수를 정의합니다. 조명에 대해 3개의 조명을 설정할 수 있으므로 배열의 요소 수도 3개입니다. 다른 필드는 메뉴 조작, 문자 표시 등에 사용되므로 전체 코드를 참조하십시오.

/// <summary>
/// 選択しているライトのインデックス
/// </summary>
private int selectedLightIndex = 0;

/// <summary>
/// ライトのパラメータ
/// </summary>
private LightParameter[] lightParameters = new LightParameter[]
    {
        new LightParameter(),
        new LightParameter(),
        new LightParameter()
    };

/// <summary>
/// アンビエントカラー
/// </summary>
private Vector3 ambientLightColor = Vector3.Zero;

/// <summary>
/// ピクセル単位のライティング
/// </summary>
private bool isPreferPerPixelLighting = false;

기본 쓰기 획득

BasicEffect.EnableDefaultLighting 메서드는 XNA Framework에서 지정한 조명의 매개 변수를 효과로 설정합니다. 이 값을 필드에 한 번 유지하기 위해 가져옵니다. (샘플에서는 여러 번 획득하는 형태이지만, 별도로 획득하는 코드를 작성하면 길어지기 때문에 단순화했습니다.)

// ライトとビュー、プロジェクションはあらかじめ設定しておく
foreach (ModelMesh mesh in this.model.Meshes)
{
    foreach (BasicEffect effect in mesh.Effects)
    {
        // デフォルトのライト適用
        effect.EnableDefaultLighting();

        // ビューマトリックスをあらかじめ設定 ((0, 0, 8) から原点を見る)
        effect.View = Matrix.CreateLookAt(
            new Vector3(0.0f, 0.0f, 8.0f),
            Vector3.Zero,
            Vector3.Up
        );

        // プロジェクションマトリックスをあらかじめ設定
        effect.Projection = Matrix.CreatePerspectiveFieldOfView(
            MathHelper.ToRadians(45.0f),
            (float)this.GraphicsDevice.Viewport.Width /
                (float)this.GraphicsDevice.Viewport.Height,
            1.0f,
            100.0f
        );

        // デフォルトのパラメータを受け取る
        this.lightParameters[0].Enabled = effect.DirectionalLight0.Enabled;
        this.lightParameters[0].DiffuseColor = effect.DirectionalLight0.DiffuseColor;
        this.lightParameters[0].SpecularColor = effect.DirectionalLight0.SpecularColor;
        this.lightParameters[0].Direction = effect.DirectionalLight0.Direction;

        this.lightParameters[1].Enabled = effect.DirectionalLight1.Enabled;
        this.lightParameters[1].DiffuseColor = effect.DirectionalLight1.DiffuseColor;
        this.lightParameters[1].SpecularColor = effect.DirectionalLight1.SpecularColor;
        this.lightParameters[1].Direction = effect.DirectionalLight1.Direction;

        this.lightParameters[2].Enabled = effect.DirectionalLight2.Enabled;
        this.lightParameters[2].DiffuseColor = effect.DirectionalLight2.DiffuseColor;
        this.lightParameters[2].SpecularColor = effect.DirectionalLight2.SpecularColor;
        this.lightParameters[2].Direction = effect.DirectionalLight2.Direction;

        // アンビエントカラー
        this.ambientLightColor = effect.AmbientLightColor;

        // ピクセル単位のライティング
        this.isPreferPerPixelLighting = effect.PreferPerPixelLighting;
    }
}

조명 설정

모델의 BasicEffect에 조명을 설정하고 있습니다. 이 값은 BasicEffect의 light 매개 변수로 설정하기만 하면 됩니다. 라이트 파라미터 변경 작업의 코드는 전체 코드를 별도로 참조하십시오.

foreach (ModelMesh mesh in this.model.Meshes)
{
    foreach (BasicEffect effect in mesh.Effects)
    {
        for (int i = 0; i < this.lightParameters.Length; i++)
        {
            // ライトを取得
            BasicDirectionalLight light = null;

            switch (i)
            {
                case 0:
                    light = effect.DirectionalLight0;
                    break;
                case 1:
                    light = effect.DirectionalLight1;
                    break;
                case 2:
                    light = effect.DirectionalLight2;
                    break;
            }

            // ライト有効フラグ
            light.Enabled = this.lightParameters[i].Enabled;

            // ライトのディフーズカラー
            light.DiffuseColor = this.lightParameters[i].DiffuseColor;

            // ライトのスペキュラーカラー
            light.SpecularColor = this.lightParameters[i].SpecularColor;

            // ライトの方向
            light.Direction = this.lightParameters[i].Direction;
        }

        // アンビエントカラー
        effect.AmbientLightColor = this.ambientLightColor;

        // ピクセル単位のライティング
        effect.PreferPerPixelLighting = this.isPreferPerPixelLighting;

    }
}

BasicEffect.DirectionalLight0 재산

첫 번째 병렬 광원 매개 변수를 가져옵니다. BasicDirectionalLight (기본방향광) 가져오기

BasicEffect.DirectionalLight1 재산

두 번째 평행 광원 파라미터를 구합니다. BasicDirectionalLight (기본방향광) 가져오기

BasicEffect.DirectionalLight2 재산

세 번째 평행 광원 파라미터를 구합니다. BasicDirectionalLight (기본방향광) 가져오기

BasicEffect.AmbientLightColor 재산

주변 조명의 색을 가져오고 설정합니다. X는 빨간색, Y는 녹색, Z는 파란색이며 각 값은 0.0~1.0 범위입니다. 벡터3 get, set

BasicEffect.PreferPerPixelLighting 재산

true로 설정하면 픽셀 단위로 조명 계산을 수행할 수 있습니다. 그러나 이 속성이 true가 되려면 픽셀 셰이더 2.0 이상을 지원해야 합니다. false로 설정하면 조명 계산이 꼭짓점별로 수행됩니다. 부울 get, set

BasicDirectionalLight.Enabled 재산

라이트를 설정하고 비활성화합니다. 부울 get, set

BasicDirectionalLight.DiffuseColor 재산

조명의 확산 색을 가져오고 설정합니다. X는 빨간색, Y는 녹색, Z는 파란색이며 각 값은 0.0~1.0 범위입니다. 벡터3 get, set

BasicDirectionalLight.SpecularColor 재산

조명의 반사색을 가져오고 설정합니다. X는 빨간색, Y는 녹색, Z는 파란색이며 각 값은 0.0~1.0 범위입니다. 벡터3 get, set

BasicDirectionalLight.Direction 재산

조명의 방향을 가져오고 설정합니다. 벡터3 get, set

모든 코드

using System;
using System.Collections.Generic;
using System.Linq;
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.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif

namespace BasicEffectLight
{
    /// <summary>
    /// ゲームメインクラス
    /// </summary>
    public class GameMain : Microsoft.Xna.Framework.Game
    {
        /// <summary>
        /// ライトパラメータ
        /// </summary>
        public class LightParameter
        {
            /// <summary>
            /// ライト有効フラグ
            /// </summary>
            public bool Enabled;

            /// <summary>
            /// ディフューズカラー
            /// </summary>
            public Vector3 DiffuseColor;

            /// <summary>
            /// スペキュラーカラー
            /// </summary>
            public Vector3 SpecularColor;

            /// <summary>
            /// ライトの方向
            /// </summary>
            public Vector3 Direction;
        }

        /// <summary>
        /// グラフィックデバイス管理クラス
        /// </summary>
        private GraphicsDeviceManager graphics = null;

        /// <summary>
        /// スプライトのバッチ化クラス
        /// </summary>
        private SpriteBatch spriteBatch = null;

        /// <summary>
        /// スプライトでテキストを描画するためのフォント
        /// </summary>
        private SpriteFont font = null;

        /// <summary>
        /// 直前のキーボード入力の状態
        /// </summary>
        private KeyboardState oldKeyboardState = new KeyboardState();

        /// <summary>
        /// 直前のマウスの状態
        /// </summary>
        private MouseState oldMouseState = new MouseState();

        /// <summary>
        /// 直前のゲームパッド入力の状態
        /// </summary>
        private GamePadState oldGamePadState = new GamePadState();

        /// <summary>
        /// モデル
        /// </summary>
        private Model model = null;

        /// <summary>
        /// 選択しているメニューのインデックス
        /// </summary>
        private int selectedMenuIndex = 0;

        /// <summary>
        /// 選択しているライトのインデックス
        /// </summary>
        private int selectedLightIndex = 0;

        /// <summary>
        /// ライトのパラメータ
        /// </summary>
        private LightParameter[] lightParameters = new LightParameter[]
            {
                new LightParameter(),
                new LightParameter(),
                new LightParameter()
            };

        /// <summary>
        /// アンビエントカラー
        /// </summary>
        private Vector3 ambientLightColor = Vector3.Zero;

        /// <summary>
        /// ピクセル単位のライティング
        /// </summary>
        private bool isPreferPerPixelLighting = false;

        /// <summary>
        /// パラメータの最大数
        /// </summary>
        private static int MaxParameterCount = 15;

        /// <summary>
        /// メニューリスト
        /// </summary>
        private static string[] MenuNameList = new string[]
            {
                "LightIndex",
                "Light Enable",
                "DiffuseColor (Red)",
                "DiffuseColor (Green)",
                "DiffuseColor (Blue)",
                "SpecularColor (Red)",
                "SpecularColor (Green)",
                "SpecularColor (Blue)",
                "Direction X",
                "Direction Y",
                "Direction Z",
                "AmbientLightColor (Red)",
                "AmbientLightColor (Green)",
                "AmbientLightColor (Blue)",
                "PreferPerPixelLighting",
            };

        /// <summary>
        /// パラメータテキストリスト
        /// </summary>
        private string[] parameters = new string[MaxParameterCount];


        /// <summary>
        /// GameMain コンストラクタ
        /// </summary>
        public GameMain()
        {
            // グラフィックデバイス管理クラスの作成
            this.graphics = new GraphicsDeviceManager(this);

            // ゲームコンテンツのルートディレクトリを設定
            this.Content.RootDirectory = "Content";

#if WINDOWS_PHONE
            // Windows Phone のデフォルトのフレームレートは 30 FPS
            this.TargetElapsedTime = TimeSpan.FromTicks(333333);

            // バックバッファサイズの設定
            this.graphics.PreferredBackBufferWidth = 480;
            this.graphics.PreferredBackBufferHeight = 800;

            // フルスクリーン表示
            this.graphics.IsFullScreen = true;
#endif

            // ウインドウ上でマウスのポインタを表示するようにする
            this.IsMouseVisible = true;
        }

        /// <summary>
        /// ゲームが始まる前の初期化処理を行うメソッド
        /// グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
        /// </summary>
        protected override void Initialize()
        {
            // TODO: ここに初期化ロジックを書いてください

            // コンポーネントの初期化などを行います
            base.Initialize();
        }

        /// <summary>
        /// ゲームが始まるときに一回だけ呼ばれ
        /// すべてのゲームコンテンツを読み込みます
        /// </summary>
        protected override void LoadContent()
        {
            // テクスチャーを描画するためのスプライトバッチクラスを作成します
            this.spriteBatch = new SpriteBatch(this.GraphicsDevice);

            // フォントをコンテンツパイプラインから読み込む
            this.font = this.Content.Load<SpriteFont>("Font");

            // モデルを作成
            this.model = this.Content.Load<Model>("Model");

            // ライトとビュー、プロジェクションはあらかじめ設定しておく
            foreach (ModelMesh mesh in this.model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    // デフォルトのライト適用
                    effect.EnableDefaultLighting();

                    // ビューマトリックスをあらかじめ設定 ((0, 0, 8) から原点を見る)
                    effect.View = Matrix.CreateLookAt(
                        new Vector3(0.0f, 0.0f, 8.0f),
                        Vector3.Zero,
                        Vector3.Up
                    );

                    // プロジェクションマトリックスをあらかじめ設定
                    effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                        MathHelper.ToRadians(45.0f),
                        (float)this.GraphicsDevice.Viewport.Width /
                            (float)this.GraphicsDevice.Viewport.Height,
                        1.0f,
                        100.0f
                    );

                    // デフォルトのパラメータを受け取る
                    this.lightParameters[0].Enabled = effect.DirectionalLight0.Enabled;
                    this.lightParameters[0].DiffuseColor = effect.DirectionalLight0.DiffuseColor;
                    this.lightParameters[0].SpecularColor = effect.DirectionalLight0.SpecularColor;
                    this.lightParameters[0].Direction = effect.DirectionalLight0.Direction;

                    this.lightParameters[1].Enabled = effect.DirectionalLight1.Enabled;
                    this.lightParameters[1].DiffuseColor = effect.DirectionalLight1.DiffuseColor;
                    this.lightParameters[1].SpecularColor = effect.DirectionalLight1.SpecularColor;
                    this.lightParameters[1].Direction = effect.DirectionalLight1.Direction;

                    this.lightParameters[2].Enabled = effect.DirectionalLight2.Enabled;
                    this.lightParameters[2].DiffuseColor = effect.DirectionalLight2.DiffuseColor;
                    this.lightParameters[2].SpecularColor = effect.DirectionalLight2.SpecularColor;
                    this.lightParameters[2].Direction = effect.DirectionalLight2.Direction;

                    // アンビエントカラー
                    this.ambientLightColor = effect.AmbientLightColor;

                    // ピクセル単位のライティング
                    this.isPreferPerPixelLighting = effect.PreferPerPixelLighting;
                }
            }
        }

        /// <summary>
        /// ゲームが終了するときに一回だけ呼ばれ
        /// すべてのゲームコンテンツをアンロードします
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: ContentManager で管理されていないコンテンツを
            //       ここでアンロードしてください
        }

        /// <summary>
        /// 描画以外のデータ更新等の処理を行うメソッド
        /// 主に入力処理、衝突判定などの物理計算、オーディオの再生など
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Update(GameTime gameTime)
        {
            // 入力デバイスの状態取得
            KeyboardState keyboardState = Keyboard.GetState();
            MouseState mouseState = Mouse.GetState();
            GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);

            // Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
            // ゲームを終了させます
            if (gamePadState.Buttons.Back == ButtonState.Pressed)
            {
                this.Exit();
            }

            // メニューの選択
            if ((keyboardState.IsKeyDown(Keys.Up) && this.oldKeyboardState.IsKeyUp(Keys.Up)) ||
                (gamePadState.ThumbSticks.Left.Y >= 0.5f &&
                    this.oldGamePadState.ThumbSticks.Left.Y < 0.5f))
            {
                // 選択メニューをひとつ上に移動
                this.selectedMenuIndex =
                    (this.selectedMenuIndex + this.parameters.Length - 1) % this.parameters.Length;
            }
            if ((keyboardState.IsKeyDown(Keys.Down) && this.oldKeyboardState.IsKeyUp(Keys.Down)) ||
                (gamePadState.ThumbSticks.Left.Y <= -0.5f &&
                    this.oldGamePadState.ThumbSticks.Left.Y > -0.5f) ||
                (this.oldMouseState.LeftButton == ButtonState.Pressed &&
                 mouseState.LeftButton == ButtonState.Released))
            {
                // 選択メニューをひとつ下に移動
                this.selectedMenuIndex =
                    (this.selectedMenuIndex + this.parameters.Length + 1) % this.parameters.Length;
            }

            // 各マテリアルの値を操作
            float moveValue = 0.0f;
            if (keyboardState.IsKeyDown(Keys.Left))
            {
                moveValue -= (float)gameTime.ElapsedGameTime.TotalSeconds;
            }
            if (keyboardState.IsKeyDown(Keys.Right))
            {
                moveValue += (float)gameTime.ElapsedGameTime.TotalSeconds;
            }
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                moveValue += (mouseState.X - this.oldMouseState.X) * 0.005f;
            }
            if (gamePadState.IsConnected)
            {
                moveValue += gamePadState.ThumbSticks.Left.X *
                             (float)gameTime.ElapsedGameTime.TotalSeconds;
            }

            if (moveValue != 0.0f)
            {
                LightParameter selectedLight = this.lightParameters[this.selectedLightIndex];

                switch (this.selectedMenuIndex)
                {
                    case 0:
                        // ライトのインデックス
                        if ((keyboardState.IsKeyDown(Keys.Left) &&
                                this.oldKeyboardState.IsKeyUp(Keys.Left)) ||
                            (mouseState.LeftButton == ButtonState.Pressed &&
                                (mouseState.X - this.oldMouseState.X) >= 5) ||
                            (gamePadState.ThumbSticks.Left.X >= 0.5f &&
                                this.oldGamePadState.ThumbSticks.Left.X < 0.5f))
                        {
                            // ライトのインデックスをひとつ減らす
                            this.selectedLightIndex =
                                (this.selectedLightIndex + this.lightParameters.Length - 1) %
                                    this.lightParameters.Length;
                        }
                        if ((keyboardState.IsKeyDown(Keys.Right) &&
                                this.oldKeyboardState.IsKeyUp(Keys.Right)) ||
                            (mouseState.LeftButton == ButtonState.Pressed &&
                                (mouseState.X - this.oldMouseState.X) <= -5) ||
                            (gamePadState.ThumbSticks.Left.X <= -0.5f &&
                                this.oldGamePadState.ThumbSticks.Left.X > -0.5f))
                        {
                            // ライトのインデックスをひとつ増やす
                            this.selectedLightIndex =
                                (this.selectedLightIndex + this.lightParameters.Length + 1) %
                                    this.lightParameters.Length;
                        }
                        if (mouseState.LeftButton == ButtonState.Pressed)
                        {
                            this.selectedLightIndex = (int)(
                                MathHelper.Clamp((float)mouseState.X / this.GraphicsDevice.Viewport.Width * 3, 0, 2));
                        }
                        break;
                    case 1:
                        // ライト有効フラグ
                        selectedLight.Enabled = (moveValue > 0.0f);
                        break;
                    case 2:
                        // ライトのディフーズカラー(赤)
                        Vector3 diffuseX = selectedLight.DiffuseColor;
                        diffuseX.X = MathHelper.Clamp(diffuseX.X + moveValue, 0.0f, 1.0f);
                        selectedLight.DiffuseColor = diffuseX;
                        break;
                    case 3:
                        // ライトのディフーズカラー(緑)
                        Vector3 diffuseY = selectedLight.DiffuseColor;
                        diffuseY.Y = MathHelper.Clamp(diffuseY.Y + moveValue, 0.0f, 1.0f);
                        selectedLight.DiffuseColor = diffuseY;
                        break;
                    case 4:
                        // ライトのディフーズカラー(青)
                        Vector3 diffuseZ = selectedLight.DiffuseColor;
                        diffuseZ.Z = MathHelper.Clamp(diffuseZ.Z + moveValue, 0.0f, 1.0f);
                        selectedLight.DiffuseColor = diffuseZ;
                        break;
                    case 5:
                        // ライトのスペキュラーカラー(赤)
                        Vector3 specularX = selectedLight.SpecularColor;
                        specularX.X = MathHelper.Clamp(specularX.X + moveValue, 0.0f, 1.0f);
                        selectedLight.SpecularColor = specularX;
                        break;
                    case 6:
                        // ライトのスペキュラーカラー(緑)
                        Vector3 specularY = selectedLight.SpecularColor;
                        specularY.Y = MathHelper.Clamp(specularY.Y + moveValue, 0.0f, 1.0f);
                        selectedLight.SpecularColor = specularY;
                        break;
                    case 7:
                        // ライトのスペキュラーカラー(青)
                        Vector3 specularZ = selectedLight.SpecularColor;
                        specularZ.Z = MathHelper.Clamp(specularZ.Z + moveValue, 0.0f, 1.0f);
                        selectedLight.SpecularColor = specularZ;
                        break;
                    case 8:
                        // ライトの方向X
                        Vector3 directionX = selectedLight.Direction;
                        directionX.X += moveValue;
                        selectedLight.Direction = directionX;
                        break;
                    case 9:
                        // ライトの方向Y
                        Vector3 directionY = selectedLight.Direction;
                        directionY.Y += moveValue;
                        selectedLight.Direction = directionY;
                        break;
                    case 10:
                        // ライトの方向Z
                        Vector3 directionZ = selectedLight.Direction;
                        directionZ.Z += moveValue;
                        selectedLight.Direction = directionZ;
                        break;
                    case 11:
                        // アンビエントカラー(赤)
                        this.ambientLightColor.X =
                            MathHelper.Clamp(this.ambientLightColor.X + moveValue, 0.0f, 1.0f);
                        break;
                    case 12:
                        // アンビエントカラー(緑)
                        this.ambientLightColor.Y =
                            MathHelper.Clamp(this.ambientLightColor.Y + moveValue, 0.0f, 1.0f);
                        break;
                    case 13:
                        // アンビエントカラー(青)
                        this.ambientLightColor.Z =
                            MathHelper.Clamp(this.ambientLightColor.Z + moveValue, 0.0f, 1.0f);
                        break;
                    case 14:
                        // ピクセル単位のライティング
                        this.isPreferPerPixelLighting = (moveValue > 0.0f);
                        break;
                }
            }

            // ライトを設定
            foreach (ModelMesh mesh in this.model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    for (int i = 0; i < this.lightParameters.Length; i++)
                    {
                        // ライトを取得
                        DirectionalLight light = null;

                        switch (i)
                        {
                            case 0:
                                light = effect.DirectionalLight0;
                                break;
                            case 1:
                                light = effect.DirectionalLight1;
                                break;
                            case 2:
                                light = effect.DirectionalLight2;
                                break;
                        }

                        // ライト有効フラグ
                        light.Enabled = this.lightParameters[i].Enabled;

                        // ライトのディフーズカラー
                        light.DiffuseColor = this.lightParameters[i].DiffuseColor;

                        // ライトのスペキュラーカラー
                        light.SpecularColor = this.lightParameters[i].SpecularColor;

                        // ライトの方向
                        light.Direction = this.lightParameters[i].Direction;
                    }

                    // アンビエントカラー
                    effect.AmbientLightColor = this.ambientLightColor;

                    // ピクセル単位のライティング
                    effect.PreferPerPixelLighting = this.isPreferPerPixelLighting;

                }
            }

            // 入力情報を記憶
            this.oldKeyboardState = keyboardState;
            this.oldMouseState = mouseState;
            this.oldGamePadState = gamePadState;

            // 登録された GameComponent を更新する
            base.Update(gameTime);
        }

        /// <summary>
        /// 描画処理を行うメソッド
        /// </summary>
        /// <param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
        protected override void Draw(GameTime gameTime)
        {
            // 画面を指定した色でクリアします
            this.GraphicsDevice.Clear(Color.CornflowerBlue);

            // 深度バッファを有効にする
            this.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            // モデルを描画
            foreach (ModelMesh mesh in this.model.Meshes)
            {
#if WINDOWS_PHONE
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = Matrix.CreateRotationZ(-MathHelper.PiOver2);
                }
#endif

                mesh.Draw();
            }

            // スプライトの描画準備
            this.spriteBatch.Begin();

            // 操作
            this.spriteBatch.DrawString(this.font,
                "Up, Down : Select Menu",
                new Vector2(20.0f, 20.0f), Color.White);
            this.spriteBatch.DrawString(this.font,
                "Left, right : Change Value",
                new Vector2(20.0f, 45.0f), Color.White);
            this.spriteBatch.DrawString(this.font,
                "MouseClick & Drag :",
                new Vector2(20.0f, 70.0f), Color.White);
            this.spriteBatch.DrawString(this.font,
                "    Select Menu & Change Value",
                new Vector2(20.0f, 95.0f), Color.White);

            // 各メニュー //
            for (int i = 0; i < MenuNameList.Length; i++)
            {
                this.spriteBatch.DrawString(this.font,
                    MenuNameList[i],
                    new Vector2(40.0f, 120.0f + i * 20.0f), Color.White);
            }

            // 各パラメータ //

            LightParameter selectedLight = this.lightParameters[this.selectedLightIndex];

            // ライトのインデックス
            this.parameters[0] = this.selectedLightIndex.ToString();

            // ライトの有効フラグ
            this.parameters[1] = selectedLight.Enabled.ToString();

            // ライトのディフーズカラー(赤)
            this.parameters[2] = selectedLight.DiffuseColor.X.ToString();

            // ライトのディフーズカラー(緑)
            this.parameters[3] = selectedLight.DiffuseColor.Y.ToString();

            // ライトのディフーズカラー(青)
            this.parameters[4] = selectedLight.DiffuseColor.Z.ToString();

            // ライトのスペキュラーカラー(赤)
            this.parameters[5] = selectedLight.SpecularColor.X.ToString();

            // ライトのスペキュラーカラー(緑)
            this.parameters[6] = selectedLight.SpecularColor.Y.ToString();

            // ライトのスペキュラーカラー(青)
            this.parameters[7] = selectedLight.SpecularColor.Z.ToString();

            // ライトの方向X
            this.parameters[8] = selectedLight.Direction.X.ToString();

            // ライトの方向Y
            this.parameters[9] = selectedLight.Direction.Y.ToString();

            // ライトの方向Z
            this.parameters[10] = selectedLight.Direction.Z.ToString();

            // アンビエントカラー(赤)
            this.parameters[11] = this.ambientLightColor.X.ToString();

            // アンビエントカラー(緑)
            this.parameters[12] = this.ambientLightColor.Y.ToString();

            // アンビエントカラー(青)
            this.parameters[13] = this.ambientLightColor.Z.ToString();

            // ピクセル単位のライティング
            this.parameters[14] = this.isPreferPerPixelLighting.ToString();


            for (int i = 0; i < this.parameters.Length; i++)
            {
                this.spriteBatch.DrawString(this.font,
                    this.parameters[i],
                    new Vector2(300.0f, 120.0f + i * 20.0f), Color.White);
            }

            // 選択インデックス
            this.spriteBatch.DrawString(this.font, "*",
                new Vector2(20.0f, 124.0f + this.selectedMenuIndex * 20.0f), Color.White);

            // スプライトの一括描画
            this.spriteBatch.End();

            // 登録された DrawableGameComponent を描画する
            base.Draw(gameTime);
        }
    }
}