忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

かんたんXNA4.0 その15 かんたんなライティング

ここではBasicEffectを使って簡単なライティングを行います。
ライティングというのは光の当たり具合によって明るくしたり暗くしたりすることです。
赤道直下なら太陽の光がもろに当たるため明るくなりますが、
北極や南極はほとんど当たらないため暗くなります。

ここでは、また違った頂点、VertexPositionNormalTextureを使います。
(できればもっとシンプルな"VertexPositionNormalColor"みたいなものを使いたいのですが、
残念ながらXNAには用意されていません。)


これは新たに法線(ノーマル:面に対して垂直な線)のデータを持っています。
跳ね返る光の強さを(内部で)計算して光の効果を出すのに必要だからです。
(法線を忘れてしまったという人のために少し直感的な説明をしておきます。
まずは鏡を用意してください。手鏡でも洗面所の鏡でもかまいません。
そして鏡の中のあなたの目を見てください。
鏡の中の目から鏡の外のあなたの本物の目を結んだ直線がその鏡の法線です。
(そう、別に目でなくても、鏡の中の何かと鏡の外の本物を結べばなんでも法線になります。)
鏡でないものの法線を考えたいときには、その物体が鏡であると考えて同じ事をすると法線が求まります。)


理屈の上では法線(ノーマル)は頂点の座標データから自動的に計算することが出来るのですが、
描画の最中にそんなことをしていてはパフォーマンスが低下してしまいますし、
法線を利用した裏ワザ的なものも出来なくなってしまうので、
最初に手作業で設定してやらなければならないことになっているのでしょう。(多分)

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

class MyGame : Game
{
    GraphicsDeviceManager graphics;
    BasicEffect effect;
    VertexPositionNormalTexture[] vertices = new[]
    { 
        new VertexPositionNormalTexture
        (
            new Vector3(0, 1, 0),
            new Vector3(0, 0, 1),
            new Vector2(0.5f, 0)
        ),
        new VertexPositionNormalTexture
        (
            new Vector3(1, 0, 0),
            new Vector3(0, 0, 1),
            new Vector2(1, 1)
        ),
        new VertexPositionNormalTexture
        (
            new Vector3(-1, 0, 0),
            new Vector3(0, 0, 1),
            new Vector2(0, 1)
        ),
 
    };
    Texture2D texture;

    public MyGame()
    {
        graphics = new GraphicsDeviceManager(this);
    }

    protected override void LoadContent()
    {
        effect = new BasicEffect(GraphicsDevice)
        {
            TextureEnabled = true,
            View = Matrix.CreateLookAt
            (  
                new Vector3(0, 0, 3),   //カメラの位置
                new Vector3(0, 0, 0),   //カメラの見る点
                new Vector3(0, 1, 0)    //カメラの上向きベクトル
            ),
            Projection = Matrix.CreatePerspectiveFieldOfView
            (
                MathHelper.ToRadians(45),   //視野の角度。ここでは45°
                GraphicsDevice.Viewport.AspectRatio,//画面のアスペクト比(=横/縦)
                1,      //カメラからこれより近い物体は画面に映らない
                100     //カメラからこれより遠い物体は画面に映らない
            )
        };
        effect.EnableDefaultLighting();
        texture = Content.Load<Texture2D>("Content/Penguins");
    }

    protected override void UnloadContent()
    {
        effect.Dispose();
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        effect.Texture = texture;

        foreach (var pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            GraphicsDevice.DrawUserPrimitives<VertexPositionNormalTexture>
            (
                PrimitiveType.TriangleList,
                vertices,
                0, 
                vertices.Length / 3
            );
        }
    }
}

xna4.0SimplestLighting.jpg
このサンプルでは各頂点に法線を設定し、ライティングしています。
霞がかって左側が暗くなっています。

参考までにライティング無しだとこうなります。
xna4.0SimplestTexture3D.jpg

BasicEffect.EnableDefaultLightingを忘れないでください。
これを呼ばないと上の図のようにライティングが無しになってしまいます。
このメソッドは自動的にいい感じにライトを設定してくれます。
(いい感じの照明をするのは本当は難しい設定が必要ですが、このメソッドはそれを自動的にしてくれるのです)

拍手[0回]

PR