立方体を光源で照らす

立方体を光源で照らして描画します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プログラムの説明

  1. 立方体に法線ベクトルを設定して光源で照らしながら描画します。
    光源で照らして描画するときには、法線ベクトルを設定します。
    法線ベクトルとは、光が最も強く反射する方向で通常は面と直角の方向です。
  2. Game1.cs を編集して、次の領域を宣言して下さい。
    modelRotation はモデルの回転係数を格納する領域です。
    vertexIndices[36] は立方体の頂点座標のインデックス配列で、6面×三角形2個で定義しています。
    他の領域の説明は ポイントプリミティブの描画 を参照して下さい。
        GraphicsDeviceManager   graphics;
        BasicEffect             basicEffect;        // 基本エフェクト
        VertexBuffer            vertexBuffer;       // 頂点バッファ
        IndexBuffer             indexBuffer;        // インデックスバッファ
        VertexDeclaration       vertexDeclaration;  // 頂点データ定義
        float                   modelRotation= 0.0f;// 回転係数
    
        // インデックスバッファの各頂点番号配列
        static readonly Int16[] vertexIndices = new Int16[]
        {   2, 0, 1, 1, 3, 2, 4, 0, 2, 2, 6, 4, 5, 1, 0, 0, 4, 5,
            7, 3, 1, 1, 5, 7, 6, 2, 3, 3, 7, 6, 4, 6, 7, 7, 5, 4
        };
        
  3. LoadContent() で立方体を定義して、描画の準備を整えます。
    vertexDeclaration に頂点データの形式(VertexPositionNormalTexture)を設定します。
    今回は頂点座標と法線ベクトルしか使わないのでテクスチャは不用ですが、これしか見当たりません。
    頂点座標の定義は「ポイントプリミティブの描画」を参照して下さい。
    basicEffect を生成して LightingEnabled を true に設定します。
    basicEffect.EnableDefaultLighting() でデフォルトのライトに設定します。
    スペキュラーと2番目と3番目のライトを無効にします。
    DiffuseColor で物質の基本色を設定します。
    basicEffect.View に View 座標を設定します。
    basicEffect.Projection に Projection を設定します。
    立方体の頂点座標と法線ベクトルを定義する vertices[8] を用意します。
    Texture を使わないので Vector2.Zero を設定しています。
    vertexBuffer を生成して vertices[] に設定された頂点データを書き込みます。
    indexBuffer を生成して頂点インデックスを書き込みます。
        protected override void LoadContent()
        {
            // 頂点定義データを作成
            vertexDeclaration = new VertexDeclaration(
                GraphicsDevice, VertexPositionNormalTexture.VertexElements);
    
            // エフェクトを作成
            basicEffect = new BasicEffect(GraphicsDevice, null);
    
            // エフェクトでライトを有効にする
            basicEffect.LightingEnabled = true;
    
            // デフォルトのライトを使用する
            basicEffect.EnableDefaultLighting();
    
            // スペキュラーを無効
            basicEffect.SpecularColor = Vector3.Zero;
    
            // 2番目と3番目のライトを無効
            basicEffect.DirectionalLight1.Enabled = false;
            basicEffect.DirectionalLight2.Enabled = false;
    
            // 物質の基本色を設定
            basicEffect.DiffuseColor = new Vector3(1.0f, 0.0f, 0.0f); 
     
            // ビューマトリックスをあらかじめ設定
            basicEffect.View = Matrix.CreateLookAt(
                    new Vector3(0.0f, 5.0f, 10.0f), Vector3.Zero, Vector3.Up);
    
            // プロジェクションマトリックスをあらかじめ設定
            basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45.0f),
                    (float)GraphicsDevice.Viewport.Width / (float)GraphicsDevice.Viewport.Height,
                    1.0f, 100.0f);
    
            // 頂点の数
            int vertexCount = 8;
    
            // 頂点バッファ作成
            vertexBuffer = new VertexBuffer(GraphicsDevice,
                VertexPositionNormalTexture.SizeInBytes * vertexCount, BufferUsage.None);
    
            // 頂点データを作成する
            VertexPositionNormalTexture[] vertives = new VertexPositionNormalTexture[vertexCount];
    
            vertives[0] = new VertexPositionNormalTexture(
                new Vector3(-2.0f, 2.0f, -2.0f),
                Vector3.Normalize(new Vector3(-1.0f, 1.0f, -1.0f)), Vector2.Zero);
            vertives[1] = new VertexPositionNormalTexture(
                new Vector3(2.0f, 2.0f, -2.0f),
                Vector3.Normalize(new Vector3(1.0f, 1.0f, -1.0f)), Vector2.Zero);
            vertives[2] = new VertexPositionNormalTexture(
                new Vector3(-2.0f, 2.0f, 2.0f),
                Vector3.Normalize(new Vector3(-1.0f, 1.0f, 1.0f)), Vector2.Zero);
            vertives[3] = new VertexPositionNormalTexture(
                new Vector3(2.0f, 2.0f, 2.0f),
                Vector3.Normalize(new Vector3(1.0f, 1.0f, 1.0f)), Vector2.Zero);
            vertives[4] = new VertexPositionNormalTexture(
                new Vector3(-2.0f, -2.0f, -2.0f),
                Vector3.Normalize(new Vector3(-1.0f, -1.0f, -1.0f)), Vector2.Zero);
            vertives[5] = new VertexPositionNormalTexture(
                new Vector3(2.0f, -2.0f, -2.0f),
                Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)), Vector2.Zero);
            vertives[6] = new VertexPositionNormalTexture(
                new Vector3(-2.0f, -2.0f, 2.0f),
                Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)), Vector2.Zero);
            vertives[7] = new VertexPositionNormalTexture(
                new Vector3(2.0f, -2.0f, 2.0f),
                Vector3.Normalize(new Vector3(1.0f, -1.0f, 1.0f)), Vector2.Zero);
    
            // 頂点データを頂点バッファに書き込む
            vertexBuffer.SetData<VertexPositionNormalTexture>(vertives);
    
            // インデックスバッファを作成
            indexBuffer = new IndexBuffer(GraphicsDevice,
                3 * 12 * sizeof(Int16), BufferUsage.None, IndexElementSize.SixteenBits);
    
            // 頂点インデックスを書き込む
            indexBuffer.SetData<Int16>(vertexIndices);
        }
        
  4. Update() メソッドで、modelRotation に回転係数を設定します。
    回転速度は MathHelper.ToRadians(0.05f) で調整して下さい。
        protected override void Update(GameTime gameTime)
        {
            // Xbox 360 および Windows でゲームの終了を許可します。 
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit();
    
            // Timer で回転係数を設定
            modelRotation += (float)gameTime.ElapsedGameTime.TotalMilliseconds * MathHelper.ToRadians(0.05f);
    
            base.Update( gameTime );    // GameComponent を更新する
        }
        
  5. Draw() メソッドで、TriangleList を使って立方体を描画します。
    GraphicsDevice.VertexDeclaration に頂点データの形式を設定します。
    GraphicsDevice.Vertices[0].SetSource() で vertexBuffer を設定します。
    Matrix.CreateRotationY() でY軸を基点にして回転しながら描画します。
    GraphicsDevice.DrawPrimitives() で TriangleList で立方体(12個の三角形で構成)を描画します。
        protected override void Draw(GameTime gameTime)
        {
            // 画面を指定した色でクリアします
            GraphicsDevice.Clear(Color.CornflowerBlue);
    
            // 描画する頂点データの定義を設定
            GraphicsDevice.VertexDeclaration = vertexDeclaration;
    
            // 描画に使用する頂点バッファをセット
            GraphicsDevice.Vertices[0].SetSource(
                vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);
    
            // インデックスバッファをセット
            GraphicsDevice.Indices = indexBuffer;
    
            // エフェクトの使用を開始します
            basicEffect.Begin();
            basicEffect.World = Matrix.CreateRotationY(modelRotation);
    
            // パスの数だけ繰り替えし描画
            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                // パスの開始
                pass.Begin();
    
                // ボックスを描画する
                GraphicsDevice.DrawIndexedPrimitives(
                    PrimitiveType.TriangleList, 0, 0, 8, 0, 12);
    
                // パスの終了
                pass.End();
            }
    
            // エフェクトの使用を終了する
            basicEffect.End();
    
            // 登録された DrawableGameComponent を描画する
            base.Draw(gameTime);
        }
        

【演習】

  1. 立方体の面の色を変えて描画して下さい。
  2. TriangleStrip を使って同じように描画して下さい。

前田稔(Maeda Minoru)の超初心者のプログラム入門

超初心者のプログラム入門(XNA(C#) game program)