diff --git a/articles/getting_to_know/howto/graphics/camera/HowTo_Understand_Different_Camera_Modes.md b/articles/getting_to_know/howto/graphics/camera/HowTo_Understand_Different_Camera_Modes.md new file mode 100644 index 00000000..c87d6a72 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/camera/HowTo_Understand_Different_Camera_Modes.md @@ -0,0 +1,279 @@ +--- +title: Understanding different camera modes +description: Demonstrates Several camera views in a single script. +requireMSLicense: true +--- + +## Overview + +This example is different from most as it is demonstrating several techniques to update a camera's view and position to achieve different camera modes or operations, including: + +- A Fixed Camera. +- A Fixed tracking camera - follows the target. +- A first person camera. +- A third person camera - with spring. +- A top-down fixed camera view. +- A top-down view centered on a target. + +### End result + +These are the kinds of camera modes demonstrated in this sample: + +|Fixed View|Fixed Tracking|First Person View| +|-|-|-| +|![Fixed](../images/HowTo_CameraModes_Fixed.gif)|![Fixed Tracking](../images/HowTo_CameraModes_Tracking.gif)|![First Person](../images/HowTo_CameraModes_FirstPerson.gif)| +|Third Person View|Top Down|Top Down tracking| +|![Third Person](../images/HowTo_CameraModes_ThirdPerson.gif)|![Top-Down](../images/HowTo_CameraModes_TopDownFixed.gif)|![Top Down tracking](../images/HowTo_CameraModes_TopDownTracking.gif)| + +## Sample + +As the sample is quite large and contains several pieces of content for the demonstration, the full source is available here: + +### [Basic Camera Example Source](https://github.com/MonoGame/MonoGame.Samples/tree/3.8.2/Tutorials/BasicCameraExample) + +## Understanding the different camera modes + +To understand how these different camera modes work, the principle is fairly strait forward. + +> [!TIP] +> Please review the [What is Camera](../../../whatis/graphics/WhatIs_Camera.md) guide for more detail on the concepts discussed here. + +### World + +The world that the camera and models are contained in usually static (at least for a single "world" or game level), for simplicity, this is usually kept at the center of the world which is `0,0,0` or `Matrix.Identity`. + +All content is then Transformed / positioned relative to this central world point. + +### Projection + +The project of the view is also normally fixed for any single camera (although you might use different perspectives for different cameras, e.g. a map view). This is defined once in either a Perspective or Orthographic (with or without depth). This is then applied to the drawing methods to define the bounds of what is drawn to the screen. + +> [!TIP] +> Elements drawn outside of the camera view / projection are culled or ignored by the graphics device. However, unless you control what data is sent, you are still paying for the performance to send to the graphics card and consider it for drawing. This is where techniques are used to limit the data sent to the graphics card and ONLY send models and textures that you know will be actually drawn and limiting what is discarded. + +## Camera Views + +The sample separates out the actual work in drawing each camera mode based on what is active at the time in the `Update` loop, as shown here: + +```csharp + switch (currentCameraMode) + { + case CameraMode.Fixed: + UpdateFixedCamera(); + break; + + case CameraMode.Tracking: + UpdateTrackingCamera(); + break; + + case CameraMode.FirstPerson: + UpdateFirstPersonCamera(); + break; + + case CameraMode.ThirdPerson: + UpdateThirdPersonCamera((float)gameTime.ElapsedGameTime.TotalSeconds); + break; + + case CameraMode.TopDownFixed: + UpdateTopDownFixedCamera(); + break; + + case CameraMode.TopDownCentred: + UpdateTopDownCenteredCamera(); + break; + } +``` + +You would not normally do this, it is only done this way for the purposes of the sample. In reality you would only use the mode relevant to the current game view (although a lot of first person games do allow switching between First Person and Third Person), however, as you will see, you are only updating the way the View Matrix is generated along with the camera position, in 3D the content is always drawn the same regardless. + +### The Fixed Camera view + +This is the simplest way of rendering a camera, you just create a `View Matrix` using the Camera's current position and looking at the center of the world (or whatever you want it to look at). For example: + +```csharp + void UpdateCameraView(Vector3 aCameraPosition, Vector3 aCameraTarget) + { + // Update the camera view matrix with the `Matrix.LookAt` method. + currentCameraView = Matrix.CreateLookAt(aCameraPosition, aCameraTarget, Vector3.Up); + } + + // Set the position of the camera in world space, for the fixed camera view matrix. + private Vector3 cameraFixedPosition = new Vector3(0.0f, 1550.0f, 5000.0f); + + void UpdateFixedCamera() + { + // Fixed view, the camera is always in the same position and looking the same way, no updates. + UpdateCameraView(cameraFixedPosition, Vector3.Zero); + } +``` + +### The Tracking Camera + +Giving the camera something to look at is also quite simple, instead of looking at the center of the world (assuming the world is `Matrix.Identity`), we instead "Look at" the model itself, dymanically updated each frame, as follows: + +```csharp + // Set the position of the camera in world space, for the fixed camera view matrix. + private Vector3 cameraFixedPosition = new Vector3(0.0f, 1550.0f, 5000.0f); + + void UpdateTrackingCamera() + { + // Tracking view, the camera is always in the same position but changes the view matrix to "look" towards a target. + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(cameraFixedPosition, modelPosition); + } +``` + +Run once per update, wherever in the world the target ends up, the camera will rotate to `LookAt` the target. + +### The First Person Camera + +There are several ways of achieving a first person view, some use the camera as the player and update the camera position, some (as in this example) take the player position and then transform the camera to it. Either way is fine (although in practice, if you want to use multiple camera views, it is better to keep them separate). + +In this example, we apply all the same transformations to the camera we perform on the "player" model to achieve this effect: + +```csharp + // 1st Person camera position relative to player model + private Vector3 cameraFirstPersonPosition = new Vector3(0.0f, 50.0f, 500.0f); + + void UpdateFirstPersonCamera() + { + // First person view, the camera moves based on the Model's position (which is moved by input) and the view matrix is updated to always look "forward" from the model. + + // Create a rotational matrix based on the current model's heading. + Matrix rotationMatrix = Matrix.CreateRotationY(modelRotation); + + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraFirstPersonPosition, rotationMatrix); + + // Calculate the position the camera is looking from. + currentCameraPosition = transformedReference + modelPosition; + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(currentCameraPosition, modelPosition); + } +``` + +You may want to look at other examples of First Person translation for cameras before deciding what works best for your game. + +### Third Person Camera + +Compared to the first person camera, the Third Person view is a much simpler approach, as the Model/Player and the Camera have to be kept separate. In most scenarios though, you have more considerations that the basic first person view, such as: + +- Wall clipping +- Obscuring by other world objects +- Bad viewing angles + +These are two complex to go into for now, so you may want to do some further reading. + +In this sample we have included a simple physics based "Spring" system, so that the camera's view follows the player in a much smoother way (it also looks REALLY cool when the players ship "jumps" to a new location, try resetting the ships position after moving in the sample in this mode). The code is as follows: + +```csharp + // 3rd Person camera position relative to player model + private Vector3 cameraThirdPersonPosition = new Vector3(0.0f, 1550.0f, 5000.0f); + + void UpdateThirdPersonCamera(float aElapsed) + { + // First person view, the camera is offset behind and above the model and moves with it,the view matrix is updated to always look "forward" from the model. + // It also includes an optional spring physics system to smooth out the camera movement. + + // Create a rotational matrix based on the current model's heading. + Matrix rotationMatrix = Matrix.CreateRotationY(modelRotation); + + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraThirdPersonPosition, rotationMatrix); + + // If camera spring is enabled, update the position and rotation of the camera over several frames + if (cameraSpringEnabled) + { + // Calculate the position where we would like the camera to be looking from. + Vector3 desiredPosition = transformedReference + modelPosition; + + // Calculate spring force + Vector3 stretch = currentCameraPosition - desiredPosition; + Vector3 force = -cameraStiffness * stretch - cameraDamping * cameraVelocity; + + // Apply acceleration + Vector3 acceleration = force / cameraMass; + cameraVelocity += acceleration * aElapsed; + + // Apply velocity + currentCameraPosition += cameraVelocity * aElapsed; + } + // If not, just move the camera without smoothing + else + { + // Calculate the position the camera is looking from. + currentCameraPosition = transformedReference + modelPosition; + } + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(currentCameraPosition, modelPosition); + } +``` + +The main difference between the First Person and Third Person views is that the "Position" of the camera is offset behind and above the center of the player, this is then transformed and added to the players current position before constructing the view. + +### Top Down Camera + +The same as the [Fixed Camera](#the-fixed-camera-view) view, the camera simply has a position and looks at the center of the world, however, it is positioned far above the world so that it is looking down. + +> [!TIP] +> In this sample it has been kept as a Perspective Camera and evaluates depth, however, if you are having a Map camera then it is more likely to use an orthographic projection instead. + +```csharp + // Top Down camera position relative to player model + private Vector3 cameraTopDownPosition = new Vector3(0.0f, 25000.0f, 1.0f); + + void UpdateTopDownFixedCamera() + { + // A Top-Down fixed view, the camera is always in the same position and looking down onto the game scene. + // Note, there are no boundaries to prevent the model from moving out of view. + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(cameraTopDownPosition, Vector3.Zero); + } +``` + +### Top Down Tracked Camera + +To finish off these camera modes, the top-down tracked view is more of a combination of a third person and top-down view, wherein the camera is way above the world and follows only the target on a 2D plane, like the third person view the camera is simply placed above the model/player and then transforms/updates its position based on the movement of the player. + +```csharp + // Top Down camera position relative to player model + private Vector3 cameraTopDownPosition = new Vector3(0.0f, 25000.0f, 1.0f); + + void UpdateTopDownCenteredCamera() + { + // A Top-Down view that moves according to two dimensional position of the model, looking down onto the model. + + // Create a rotational matrix based on the current model's heading. + Matrix rotationMatrix = Matrix.CreateRotationY(modelRotation); + + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraTopDownPosition, rotationMatrix); + + // Calculate the position the camera is looking from. + currentCameraPosition = transformedReference + modelPosition; + + // Set up our world matrix, view matrix and projection matrix. + UpdateCameraView(currentCameraPosition, modelPosition); + } +``` + +## See Also + +- [How to display Multiple Screens with Viewports](../HowTo_UseViewportForSplitscreenGaming.md) + +### Concepts + +- [What Is 3D Rendering?](../../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is a Viewport?](../../../whatis/graphics/WhatIs_Viewport.md) +- [What Is a View Frustum?](../../../whatis/graphics/WhatIs_ViewFrustum.md) +- [What Is a Render Target?](../../../whatis/graphics/WhatIs_Render_Target.md) + +### Reference + +- [GraphicsDevice.Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) \ No newline at end of file diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_FirstPerson.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_FirstPerson.gif new file mode 100644 index 00000000..25594091 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_FirstPerson.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Fixed.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Fixed.gif new file mode 100644 index 00000000..f63b26bc Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Fixed.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_ThirdPerson.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_ThirdPerson.gif new file mode 100644 index 00000000..228ccba3 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_ThirdPerson.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownFixed.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownFixed.gif new file mode 100644 index 00000000..125ee881 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownFixed.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownTracking.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownTracking.gif new file mode 100644 index 00000000..348c5833 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_TopDownTracking.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Tracking.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Tracking.gif new file mode 100644 index 00000000..309b3788 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CameraModes_Tracking.gif differ diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Camera.md b/articles/getting_to_know/whatis/graphics/WhatIs_Camera.md new file mode 100644 index 00000000..cebb2397 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Camera.md @@ -0,0 +1,337 @@ +--- +title: What is A Camera? +description: The basics to understand rendering with a Camera in MonoGame +--- + +In order to render anything to the screen the Graphics device needs to understand what it needs to render and where, in basic terms, it needs a projection in 3D space with objects in view that need to be rendered. + +An easier way to break it down is to compare it to the movies (or movie making), what you need in actuality is a **Camera**. Where the camera points in the movie scene, what actors are in view and the scenery behind them, that is what makes it into the movie and shows on the screen. In Game Development the principle is the same. + +## The [View Frustrum](./WhatIs_ViewFrustum.md) + +The way we describe a camera in 3D terms is to define a [View Frustrum](./WhatIs_ViewFrustum.md), which tells the graphics device: + +- Where is it looking in 3D space. +- What is the closest point at which is should be looking from. (Near Plane) +- What is the furthest point objects can be rendered. (Far Plane) +- And what is the angle of projection. + +The following diagram shows how this looks. + +![A diagram visualization of the View Frustrum](images/frustum.jpg) + +Everything within the "cone of view" is recognized by the graphics pipeline and is rendered into a Texture for displaying on the screen. Everything outside these bounds is ignored (culled) and left on the cutting room floor. + +> [!CAUTION] +> Be aware, that in 3D rendering EVERYTHING is evaluated to determine if it is in "View", EVERYTHING you send to the graphics card that you want to be rendered. So if you send a massive scene and ALL your Models, ALL your textures, etc, then everything is evaluated. Sure, Graphics Processing has evolved considerably over the years and the processes running on Graphics Cards keep getting quicker, but you still want to make that as efficient as possible. + +## What defines a camera + +Beyond the View Frustrum above, a Camera exists in graphical terms as: + +- A position - Where in 3D space is the camera positioned? +- A direction - Which direction is the camera pointing? +- The Target of the camera - What is it looking at? The central point. +- The View Frustrum of the camera - What is in the field of view? +- The World Matrix, where in the world is the camera in relation to the center and other objects? + +You will see this defined in many samples as the `World`, `View` and `Projection` Matrices, as shown below: + +```csharp +// A centered world with no transformation +Matrix worldMatrix = Matrix.Identity; + +// A view pointing at the center of the world from a position 50 units backwards. +Matrix viewMatrix = Matrix.CreateLookAt( + // View Position, where it is viewed FROM + new Vector3(0, 0, 50), + // The world space coordinates it is looking at (0,0,0) + Vector3.Zero, + // The rotation of the view, the direction of the upper edge of the camera. + Vector3.Up); + +// The frustrum of the camera +Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView( + // The width of the camera view. + MathHelper.PiOver4, + // The height of the camera view. + GraphicsDevice.Viewport.AspectRatio, + // The near plane, when to start rendering objects from. + 1.0f, + // The far plane, when to stop rendering objects from. + 300.0f); +``` + +## [2D drawing](../../howto/graphics/HowTo_Draw_A_Sprite.md) + +Now to break one illusion, 2D drawing (without all the camera setup) is still 3D drawing but from a fixed point of view with all content drawn at the same physical depth. + +The [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) class does a very clever job of setting up this fixed view behind the scenes and also provides some basic ordering/laying of content as it is drawn into view. Each batch is sent to the graphics card collectively and then processed in order from first to last, each subsequent draw being on top of the last. + +> [!NOTE] +> Texture / Font drawing is effectively like placing pieces of paper on a table, one on top of another until you are done. What can be seen once all the paper has been placed is the final view. + +An example 2D drawing method: + +```csharp +void DrawTexture(SpriteBatch spriteBatch, Texture2D spriteTexture, Vector2 spritePosition, Color spriteColor) +{ + spriteBatch.Begin(); + spriteBatch.Draw(spriteTexture, spritePosition, spriteColor); + spriteBatch.End(); +} +``` + +> [!NOTE] +> For more on 2D / Sprite rendering, check the [How To](https://docs.monogame.net/articles/getting_to_know/howto/graphics/#2d-sprite-rendering) series for 2D rendering. + +The functionality does provide some techniques to sort what is drawn, provide some additional depth and layers, as well as blending options to effectively merge what is drawn. + +## [3D Drawing](../../howto/graphics/HowTo_RenderModel.md) + +When drawing 3D content in a scene, the Camera's current `View` and `Projection` are what are fed in to an [Effect](xref:Microsoft.Xna.Framework.Graphics.Effect) that draws the 3D content, together with a [Transformational Matrix](../../howto/graphics/HowTo_TransformPoint.md) (`World` position and rotation of the model) multiplied by the same `World` matrix used by the camera (as they are both part of the same world). + +The MonoGame `Model` class has a built in `Draw` Method which performs the basic functions needed in order to render a 3D model into the view, requiring only the `World`, `View`, and `Projection` matrices required to draw it, as follows: + +```csharp + Model myModel; + + protected override void LoadContent() + { + myModel = Content.Load(""); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + // Ground drawn from the center of the scene + myModel.Draw(Matrix.Identity, currentCameraView, currentCameraProjection); + } + +``` + +> [!INFO] +> For information purposes only + +Behind the scenes, the `model.Draw()` method is using a `BasicEffect` and performing the necessary matrix calculations to position and render the model, as follows: + +```csharp +/// +/// Draw the model, a model can have multiple meshes, so loop. +/// +/// The Model to draw. +/// The World matrix from the camera or shared world matrix. +/// The camera view in the world. +/// The camera projection in the world. +void DrawModel(Model aModel, Matrix aWorld, Matrix aView, Matrix aProjection) +{ + //Copy any parent transforms + Matrix[] transforms = new Matrix[ aModel.Bones.Count ]; + aModel.CopyAbsoluteBoneTransformsTo( transforms ); + + //Draw the model, a model can have multiple meshes, so loop + foreach (ModelMesh mesh in aModel.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.PreferPerPixelLighting = true; + effect.World = transforms[ mesh.ParentBone.Index ] * aWorld; + effect.View = aView; + effect.Projection = aProjection; + } + + //Draw the mesh, will use the effects set above. + mesh.Draw( ); + } +} +``` + +## Types of Camera + +Cameras have many roles in games, in certain cases you may even use multiple cameras to render a scene, or render scenes from different angles to a texture to use as a HUD or mini-map. + +Camera types include: + +|Camera Type|Description| +|-|-| +|Fixed|A camera that is locked in place and is not intended to move (e.g. a Security Camera)| +|First Person|A camera that represents a players perspective of the world, moving and looking around.| +|Third Person|A camera that is locked behind a player avatar or model, moving with them as they move, can also rotate around the player for alternate views.| +|Top Down|A fixed view that looks from up on high and down in to the game world, sometimes fixed, sometimes tracking the movement of the main player or avatar.| +|Side View|A side scrolling view, or platformer, again, sometimes fixed, sometimes following the player or avatar| + +These are just the most common examples as everyone has seen in the many games that have come before. Some games use a combination of these modes to achieve the games look and feel. + +Multiple cameras can be used simultaneously for either a [split screen multi-player](../../howto/graphics/HowTo_UseViewportForSplitscreenGaming.md) effect or by showing an alternate view in a window. + +## Views of Cameras + +The projection of the camera can also be made to look different, MonoGame supports the two main modes of projection: + +- [Perspective](xref:Microsoft.Xna.Framework.Matrix#Microsoft_Xna_Framework_Matrix_CreatePerspective_System_Single_System_Single_System_Single_System_Single_) - A realistic 3D view. +- [Orthographic](xref:Microsoft.Xna.Framework.Matrix#Microsoft_Xna_Framework_Matrix_CreateOrthographic_System_Single_System_Single_System_Single_System_Single_) - Provides a flat 2D view. + +Each perspective simply alters the way in which content is rendered into view. + +## Camera Example + +To demonstrate a camera setup, the following class acts as a base camera definition that can then be extended to meet your needs for rendering: + +```csharp +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +public class Camera +{ + private Vector3 position; + private float yaw; + private float pitch; + private int viewportWidth; + private int viewportHeight; + private float nearClip = 10.0f; + private float farClip = 100000.0f; + + public Vector3 Position => position; + + public float Yaw => yaw; + + public float Pitch => pitch; + + public Matrix ViewMatrix + { + get + { + Vector3 cameraDirection = Vector3.Transform(Vector3.Forward, Matrix.CreateFromYawPitchRoll(yaw, pitch, 0)); + Vector3 cameraTarget = position + cameraDirection; + return Matrix.CreateLookAt(position, cameraTarget, Vector3.Up); + } + } + + public Matrix ProjectionMatrix { get; private set; } + + public Camera(Vector3 startPosition, float startYaw, float startPitch, int viewportWidth, int viewportHeight) + { + position = startPosition; + yaw = startYaw; + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.nearClip = nearClip; + this.farClip = farClip; + + ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView( + MathHelper.ToRadians(45), + viewportWidth / (float)viewportHeight, + nearClip, + farClip + ); + } +} +``` + +Using this camera is then as simple as: + +```csharp +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; + +public class MonoGameCameraSample : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private Camera camera; + + private Model myModel; + + public MonoGameCameraSample() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + } + + protected override void Initialize() + { + // Create a new camera with the following parameters: + // 1. Position 50 units Up and 100 units back from the center + // 2. Camera is looking straight forward, no turn. + // 3. Angle the camera down 25 degrees + // 4. Pass in the width and height of the Graphics Device + camera = new Camera( + new Vector3(0, 50, 100), + 0f, + -MathHelper.ToRadians(25f), + GraphicsDevice.Viewport.Width, + GraphicsDevice.Viewport.Height + ); + + base.Initialize(); + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + myModel = Content.Load("Models/p1_wedge"); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + GraphicsDevice.BlendState = BlendState.Opaque; + GraphicsDevice.RasterizerState = RasterizerState.CullNone; + GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap; + GraphicsDevice.DepthStencilState = DepthStencilState.Default; + + // Draw a model using the camera's current View and Projection Matrix + DrawModel(myModel, Matrix.Identity, camera.ViewMatrix, camera.ProjectionMatrix); + + base.Draw(gameTime); + } + + void DrawModel(Model aModel, Matrix aWorld, Matrix aView, Matrix aProjection) + { + //Copy any parent transforms + Matrix[] transforms = new Matrix[aModel.Bones.Count]; + aModel.CopyAbsoluteBoneTransformsTo(transforms); + + //Draw the model, a model can have multiple meshes, so loop + foreach (ModelMesh mesh in aModel.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.PreferPerPixelLighting = true; + effect.World = transforms[mesh.ParentBone.Index] * aWorld; + effect.View = aView; + effect.Projection = aProjection; + } + + //Draw the mesh, will use the effects set above. + mesh.Draw(); + } + } +} +``` + +This is a fixed camera with no movement and only looking in a single direction all the time, it has no movement, input logic or capability to move around the scene. + +## See Also + +- [How to display Multiple Screens with Viewports](../../howto/graphics/HowTo_UseViewportForSplitscreenGaming.md) + +### Concepts + +- [What Is 3D Rendering?](WhatIs_3DRendering.md) +- [What Is a Viewport?](WhatIs_Viewport.md) +- [What Is a View Frustum?](WhatIs_ViewFrustum.md) +- [What Is a Render Target?](WhatIs_Render_Target.md) + +### Reference + +- [GraphicsDevice.Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) diff --git a/external/MonoGame b/external/MonoGame index 584eaa2d..c42673d2 160000 --- a/external/MonoGame +++ b/external/MonoGame @@ -1 +1 @@ -Subproject commit 584eaa2d6d8af2497aab5e6b1171728ec92d1e44 +Subproject commit c42673d2bb4d37664272951e57ad60e5948d387d