Search code examples
c#3dxnalighting3d-modelling

XNA - 3D game - Apply a light to all models


I want to make an XNA game with 3D graphics, and one thing has me wondering. Say I have 10 Models in my scene, and I want to draw them all with the same light source, like a directional light. Now I understand that Models have Effects, and Effects have lighting information, among other things. My question is, how would I apply the same light source to all the models in my scene, instead of each model having its own light source? Someone tell me if I am way off base.


Solution

  • If you are using XNA 4.0 to create your game, then you are required to use Effects. Luckily the XNA team included a powerful yet simple Effect called BasicEffect. Unless you specify otherwise, BasicEffect is the default Effect in use when you render your models. BasicEffect has support for up to 3 directional lights. The sample code below should give you an idea on how to manipulate the BasicEffect instance to render using a directional light.

    public void DrawModel( Model myModel, float modelRotation, Vector3 modelPosition,
                           Vector3 cameraPosition
         ) {
        // Copy any parent transforms.
        Matrix[] transforms = new Matrix[myModel.Bones.Count];
        myModel.CopyAbsoluteBoneTransformsTo(transforms);
    
        // Draw the model. A model can have multiple meshes, so loop.
        foreach (ModelMesh mesh in myModel.Meshes)
        {
            // This is where the mesh orientation is set, as well 
            // as our camera and projection.
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms[mesh.ParentBone.Index] * 
                                Matrix.CreateRotationY(modelRotation) *
                                Matrix.CreateTranslation(modelPosition);
                effect.View = Matrix.CreateLookAt(cameraPosition,
                                Vector3.Zero, Vector3.Up);
                effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                                        MathHelper.ToRadians(45.0f), 1.333f, 
                                        1.0f, 10000.0f);
                effect.LightingEnabled = true; // turn on the lighting subsystem.
                effect.DirectionalLight0.DiffuseColor = new Vector3(0.5f, 0, 0); // a red light
                effect.DirectionalLight0.Direction = new Vector3(1, 0, 0);  // coming along the x-axis
                effect.DirectionalLight0.SpecularColor = new Vector3(0, 1, 0); // with green highlights
            }
            // Draw the mesh, using the effects set above.
            mesh.Draw();
        }
    }