My Books

My Software

Introduction

In this tutorial, we will be taking an initial look at effects in MonoGame, especially the BasicEffect class. In the Using 3D Models tutorial, we looked at how to draw 3D models. In that tutorial, we actually ran into the BasicEffect class. Here, we will pick up where we left off in that tutorial, and discuss some of the basics of the BasicEffect class. While you don't need to, I would recommend starting from the code that we had made at the end of that tutorial.

Effects in MonoGame

An effect is simply a method of designating how an object should be rendered on the screen. Back in the past, a graphics API would have a list of variables that you could set that would tell the graphics card everything it needed to know, like the position of lights in the scene, the textures to use, and other things. More recently, as graphics programmers wanted more flexibility, and graphics cards became more powerful, it became possible for a person to create a small program that could be run for each vertex that you were handling, and for each pixel that you draw on the screen. With this, the possibilities became limitless, and you can now do anything you want, as long as your graphics card can keep up with it.

These programs are written in a programming language called HLSL, and there will be tutorials later that will discuss how to use this. There is one small problem though. It can be quite a bit of work to create a complete effect from scratch, and so the XNA people provide an easy-to-use but powerful effect for you, which is utilized with the BasicEffect class. In this tutorial, and the next couple of tutorials, we will look at how this class is used.

Some BasicEffect Basics

In the next couple of tutorials, we will take a look at how to do lighting and fog with the BasicEffect class. In this tutorial, we will look at where the BasicEffect class was used earlier in our game, and a few simple things that you can do with it. Recall that in the previous tutorial we created a DrawModel() method that looked like this:

Notice that the inner foreach loop states that we want to look at all of the BasicEffects that are in each mesh of the model. By default, when you load a model, the Content Pipeline prepares the model with a BasicEffect to handle the rendering. Later, we will see that you can replace the BasicEffect class with something of your own, but for now, we will keep this the same. Before, we set the world, view, and projection matrices of the effect to be what we wanted, and the BasicEffect class took care of it from there.

In addition to what we already have here, there are two things that we want to look at. First, you can set a different texture for the BasicEffect. For instance, continuing on with the code from the previous tutorial, I have loaded another texture called "GreenShipTexture.png", which can be downloaded from the Texture Library. You can then put in the other texture with a line of code like the following:

effect.Texture = otherTexture; // otherTexture is of the type "Texture2D"

This gives us something like the image below when we run it:

The second thing we want to do is to try using no texture at all. This can easily be done with the following line of code:

effect.TextureEnabled = false;

When we do this, we get a solid white drawing, like in the image below, because the effect has no other indication of what color should be used.

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingMicrosoft.Xna.Framework;
usingMicrosoft.Xna.Framework.Audio;
usingMicrosoft.Xna.Framework.Content;
usingMicrosoft.Xna.Framework.GamerServices;
usingMicrosoft.Xna.Framework.Graphics;
usingMicrosoft.Xna.Framework.Input;
usingMicrosoft.Xna.Framework.Media;
namespaceUsing3DModels{/// <summary>/// This is the main type for your game/// </summary>publicclassGame1 : Microsoft.Xna.Framework.Game{GraphicsDeviceManagergraphics;
SpriteBatchspriteBatch;
/// <summary>/// Stores the model that we are going to draw./// </summary>privateModelmodel;
/// <summary>/// Stores a second texture that can be applied to the model./// </summary>privateTexture2DotherTexture;
/// <summary>/// Stores the position of the model./// </summary>privateVector3position;
/// <summary>/// Stores the rotation angle of the model. This/// is used as a roll angle. (So changing it will make the/// object roll as it moves forward.)/// </summary>privatefloatangle;
/// <summary>/// Stores the world matrix for the model, which transforms the /// model to be in the correct position, scale, and rotation/// in the game world./// </summary>privateMatrixworld = Matrix.CreateTranslation(newVector3(0, 0, 0));
/// <summary>/// Stores the view matrix for the model, which gets the model/// in the right place, relative to the camera./// </summary>privateMatrixview = Matrix.CreateLookAt(newVector3(0, 0, 10), newVector3(0, 0, 0), Vector3.UnitY);
/// <summary>/// Stores the projection matrix, which gets the model projected/// onto the screen in the correct way. Essentially, this defines the/// properties of the camera you are using./// </summary>privateMatrixprojection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 480f, 0.1f, 100f);
publicGame1(){graphics = newGraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}/// <summary>/// Allows the game to perform any initialization it needs to before starting to run./// This is where it can query for any required services and load any non-graphic/// related content. Calling base.Initialize will enumerate through any components/// and initialize them as well./// </summary>protectedoverridevoidInitialize(){base.Initialize();
}/// <summary>/// LoadContent will be called once per game and is the place to load/// all of your content./// </summary>protectedoverridevoidLoadContent(){// Create a new SpriteBatch, which can be used to draw textures.spriteBatch = newSpriteBatch(GraphicsDevice);
model = Content.Load<Model>("Ship");
otherTexture = Content.Load<Texture2D>("GreenShipTexture");
position = newVector3(0, 0, 0);
angle = 0;
}/// <summary>/// UnloadContent will be called once per game and is the place to unload/// all content./// </summary>protectedoverridevoidUnloadContent(){}/// <summary>/// Allows the game to run logic such as updating the world,/// checking for collisions, gathering input, and playing audio./// </summary>/// <param name="gameTime">Provides a snapshot of timing values.</param>protectedoverridevoidUpdate(GameTimegameTime){// Allows the game to exitif(GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)this.Exit();
// Update the properties of the model hereposition += newVector3(0, 0.001f, 0);
angle += 0.003f;
// This updates the world matrix, so that it reflects the changes to the position// and angle. Remember that this matrix determines where the model will be located// at in the 3D world.world = Matrix.CreateRotationY(angle) * Matrix.CreateTranslation(position);
base.Update(gameTime);
}/// <summary>/// This is called when the game should draw itself./// </summary>/// <param name="gameTime">Provides a snapshot of timing values.</param>protectedoverridevoidDraw(GameTimegameTime){GraphicsDevice.Clear(Color.CornflowerBlue);
DrawModel(model, world, view, projection);
base.Draw(gameTime);
}/// <summary>/// Does the work of drawing a model, given specific world, view, and projection/// matrices./// </summary>/// <param name="model">The model to draw</param>/// <param name="world">The transformation matrix to get the model in the right place in the world.</param>/// <param name="view">The transformation matrix to get the model in the right place, relative to the camera.</param>/// <param name="projection">The transformation matrix to project the model's points onto the screen correctly.</param>privatevoidDrawModel(Modelmodel, Matrixworld, Matrixview, Matrixprojection){foreach(ModelMeshmeshinmodel.Meshes){foreach(BasicEffecteffectinmesh.Effects){effect.Texture = otherTexture;
effect.TextureEnabled = false;
effect.World = world;
effect.View = view;
effect.Projection = projection;
}mesh.Draw();
}}}}

What's Next?

In this tutorial, we got a little bit of an idea of what the BasicEffect class does, and how effects work. The next step is to use a couple of other features of the BasicEffect class, including lighting and fog.