diff --git a/articles/getting_to_know/howto/HowTo_CollisionDetectionOverview.md b/articles/getting_to_know/howto/HowTo_CollisionDetectionOverview.md new file mode 100644 index 0000000..e0dfd42 --- /dev/null +++ b/articles/getting_to_know/howto/HowTo_CollisionDetectionOverview.md @@ -0,0 +1,76 @@ +--- +title: How to test collisions with Bounding Volumes +description: A walkthrough what is involved in figuring out if two objects collide for MonoGame! +requireMSLicense: true +--- + +## Overview + +Collision detection determines whether objects in a game world overlap each other. + +The MonoGame Framework provides several classes and methods to speed implementation of collision detection systems in games. + +* [Bounding Volume Classes](#bounding-volume-classes) +* [Non-Bounding Volume Classes](#non-bounding-volume-classes) +* [Contains and Intersects Methods](#contains-and-intersects-methods) +* [Adding New Collision Data Structures](#adding-new-collision-data-structures) + +## Bounding Volume Classes + +The MonoGame Framework has three classes that represent three-dimensional volumes. Use a bounding volume class to approximate the volume occupied by a complex object using a volume that is less complex and faster for performing collision checking. All of the bounding volume classes support intersection and containment tests with each other and the plane and ray classes. + +### Bounding Sphere + +The [BoundingSphere Structure](xref:Microsoft.Xna.Framework.BoundingSphere) represents the space occupied by a sphere. + +There are several benefits of using a bounding sphere for collision detection. + +* Sphere to sphere checks are very fast. To check for collision between two spheres, the distance between the centers of the spheres is compared to the sum of the radii of both spheres. If the distance is less than the combined radii of both spheres, the spheres intersect. +* The [BoundingSphere Structure](xref:Microsoft.Xna.Framework.BoundingSphere) class is compact. It stores only a vector representing its center and its radius. +* Unlike a bounding box, a bounding sphere does not need to be recreated if the model rotates. If the model being bounded rotates, the bounding sphere will still be large enough to contain it. +* Moving a bounding sphere is inexpensive. Just add a value to the center. + +There is one major drawback to using the bounding sphere class for collision detection. + +* Unless the object being approximated is sphere shaped, the bounding sphere will have some empty space, which could result in false positive results. Long narrow objects will have the most empty space in their bounding spheres. + +### Bounding Box + +The [BoundingBox Structure](xref:Microsoft.Xna.Framework.BoundingBox) represents the space occupied by a box. The bounding box class is axis aligned. Each face of the bounding box is perpendicular to the x-axis, the y-axis, or the z-axis. + +There are several benefits of using the bounding box for collision detection. + +* The bounding box class fits rectangular shapes aligned with the axis very well. Compared to the bounding sphere class, the bounding box class provides a much tighter fit for non-rotated rectangular objects. +* Because the bounding box class is axis aligned, you can make certain assumptions that result in collision checks between bounding boxes being quicker than a bounding box that can be rotated. + +There are a few drawbacks of using the bounding box for collision detection. + +* Rotating a bounding box causes it to no longer be axis aligned. Because of this, if you rotate a model being bounded, you will need to recreate the bounding box. Doing so can be slow, since all the points in an object are iterated through to get the bounding box. If the model has not changed orientation, you can translate the bounding box instead of recreating it. +* If the model being bounded is not aligned to the axis, the bounding box will have some empty space. The amount of empty space will be greatest when the object is rotated 45 degrees from an axis. +* Empty space in the bounding box can result in false positives when checking for collision. + +### Bounding Frustum + +Use a [BoundingFrustum Class](xref:Microsoft.Xna.Framework.BoundingFrustum) to create a bounding volume that corresponds to the space visible to the camera. You create a bounding frustum from the combined view and projection matrix that the camera is using currently. If the camera moves or rotates, you need to recreate the bounding frustum. The bounding frustum is not used to determine when two objects collide, but rather when an object intersects with the volume of space viewable by the camera. Objects that do not intersect and are not contained by the bounding frustum are not visible to the camera and do not need to be drawn. For complex models, this can reduce the number of pixels that need to be rendered. + +## Non-Bounding Volume Classes + +### Plane + +The [Plane Structure](xref:Microsoft.Xna.Framework.Plane) describes a 2D plane. The plane is defined by a normal vector (perpendicular to the plane) and a point on the plane. The plane class supports intersection tests with the bounding volume classes. The plane class’s intersection test returns the tested object's position relative to the plane. The return value indicates whether the object intersects the plane. If the object does not intersect the plane, the return value indicates whether the object is on the plane’s front side or back side. + +### Ray + +The [Ray Structure](xref:Microsoft.Xna.Framework.Ray) describes a ray starting at a point in space. The ray structure supports intersection tests with the bounding volume classes. The return value of the ray intersection tests is the distance the intersection occurred at, or null if no intersection occurred. + +### Model + +In addition to the information needed to draw a model, the [Model Class](xref:Microsoft.Xna.Framework.Graphics.Model) contains bounding volumes for its parts. When a model is imported, the content pipeline calculates the bounding sphere for each of the model's parts. To check for collision between two models, you can compare the bounding spheres for one model to all of the bounding spheres of the other model. + +## Contains and Intersects Methods + +Bounding volume classes have methods to support two types of collision tests: intersection tests and containment tests. The intersects methods check whether the two objects being tested overlap in any way. As soon as the test finds that the objects do intersect, it returns without trying to determine the degree of the intersection. The contains methods determine whether the objects simply intersect or whether one of the objects is completely contained by the other. Since the intersects methods need only determine whether an intersection occurred, they tend to be faster than the contains methods. + +## Adding New Collision Data Structures + +When implementing other bounding volume classes and intersection tests, you will probably need to add a custom content pipeline processor. For example, your game might need to use convex hulls for collision detection. You could use a custom processor to determine the convex hull and then place it in the model's tag field. Then, when the model is loaded at run time, the convex hull information would be available in the model. For more information, see [Extending a Standard Content Processor](content_pipeline/HowTo_Extend_Processor.md). diff --git a/articles/getting_to_know/howto/graphics/HowTo_AspectRatio.md b/articles/getting_to_know/howto/graphics/HowTo_AspectRatio.md new file mode 100644 index 0000000..96ed410 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_AspectRatio.md @@ -0,0 +1,131 @@ +--- +title: How to restrict Aspect Ratio on a Graphics Device +description: Demonstrates how to create a custom GraphicsDeviceManager that only selects graphics devices with widescreen aspect ratios in full-screen mode. +requireMSLicense: true +--- + +## Overview + +Certain games require a fixed resolution that is only suitable for Wide-Screen devices (e.g. a TV). The steps below show how to implement a custom `GraphicsDeviceManager` to provide such a restriction. + +## To restrict graphics devices to widescreen aspect ratios in full-screen mode + +1. Create a class that derives from [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager). + + ```csharp + public class CustomGraphicsDeviceManager : GraphicsDeviceManager + { + public CustomGraphicsDeviceManager( Game game ) + : base( game ) + { + } + + } + ``` + +2. Add a **WideScreenOnly** property to the class. + + The property is used to turn on and off the widescreen-only behavior. + + ```csharp + private bool isWideScreenOnly; + public bool IsWideScreenOnly + { + get { return isWideScreenOnly; } + set { isWideScreenOnly = value; } + } + ``` + +3. Determine the minimum desired aspect ratio. + + ```csharp + static float WideScreenRatio = 1.6f; //1.77777779f; + ``` + +4. Override the **RankDevices** method of [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager). + + Note the call to [base.RankDevices](xref:Microsoft.Xna.Framework.GraphicsDeviceManager). This call ensures that the new version of **RankDevices** has an already ranked list of available devices with which to work. + + ```csharp + protected override void RankDevices( + List foundDevices ) + { + base.RankDevices( foundDevices ); + } + ``` + +5. Add a check to see if the **WideScreenOnly** property is **true**. + + ```csharp + if (IsWideScreenOnly) + { + ... + } + ``` + +6. In the **if** block, loop through all found devices, and check whether the [PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters) indicate the device is full-screen. + +7. If the device is full-screen, determine the aspect ratio of the device by dividing the **BackBufferWidth** by the **BackBufferHeight**. + +8. If the aspect ratio is less than the desired aspect ratio, remove the device from the list of found devices. + + ```csharp + for (int i = 0; i < foundDevices.Count; ) + { + PresentationParameters pp = + foundDevices[i].PresentationParameters; + if (pp.IsFullScreen == true) + { + float aspectRatio = (float)(pp.BackBufferWidth) / + (float)(pp.BackBufferHeight); + + // If the device does not have a widescreen aspect + // ratio, remove it. + if (aspectRatio < WideScreenRatio) + { + foundDevices.RemoveAt( i ); + } + else { i++; } + } + else i++; + } + ``` + +9. Replace the default [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) with the derived [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager). +10. To test the new component, set the **WideScreenOnly** and **IsFullScreen** properties to **true**. + + ```csharp + public Game1() + { + graphics = new CustomGraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + + this.graphics.PreferMultiSampling = false; + #if WINDOWS + this.graphics.PreferredBackBufferWidth = 1280; + this.graphics.PreferredBackBufferHeight = 720; + #endif + #if ANDROID + this.graphics.PreferredBackBufferWidth = 400; + this.graphics.PreferredBackBufferHeight = 600; + #endif + + this.graphics.IsFullScreen = true; + this.graphics.IsWideScreenOnly = true; + graphics.ApplyChanges(); + } + ``` + +## See Also + +- [How to articles for the Graphics Pipeline](index.md) + +### Concepts + +- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is a Back Buffer?](../../whatis/graphics/WhatIs_BackBuffer.md) +- [What Is a Viewport?](../../whatis/graphics/WhatIs_Viewport.md) + +### Reference + +- [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Create_a_BasicEffect.md b/articles/getting_to_know/howto/graphics/HowTo_Create_a_BasicEffect.md new file mode 100644 index 0000000..0e63a1e --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Create_a_BasicEffect.md @@ -0,0 +1,145 @@ +--- +title: How to create a Basic Effect +description: Demonstrates how to create and initialize an instance of the BasicEffect class and use it to draw simple geometry. +requireMSLicense: true +--- + +## Overview + +The steps described here apply to effects created with the [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) class using the [Effect](xref:Microsoft.Xna.Framework.Graphics.Effect) class to write a custom effect. + +> [!NOTE] +> The example draws aliased geometry, to see an example that draws smoother edges because it also applies anti-aliasing, see [Enabling Anti-aliasing (Multi-sampling)](HowTo_Enable_Anti_Aliasing.md). + +### End result + +![The output of this tutorial](images/HowTo_BasicEffect_Sample.png) + +## To use BasicEffect + +Using the basic effect class requires a set of `world`, `view`, and `projection` matrices, a `vertex buffer`, a `vertex declaration`, and an instance of the [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) class. + +1. Declare these properties at the beginning of the game class. + + ```csharp + //Matrices for 3D perspective + private Matrix worldMatrix, viewMatrix, projectionMatrix; + + // Vertex data for rendering + private VertexPositionColor[] triangleVertices; + + // A Vertex format structure that contains position, normal data, and one set of texture coordinates + private BasicEffect basicEffect; + ``` + +1. Initialize the world, view, and projection matrices in the `Initialize`. + + Next, create a world matrix using the default `Matrix.Identity` for simplicity. Set the `view matrix` as a `look-at` matrix with a camera position of `(0, 0, 50)`, pointing at the origin. The `projection matrix` is a `perspective` projection matrix based on a a `45-degree` field of view, an aspect ratio equal to the client window, and a set of `near` and `far` planes to render the geometry within in view of the camera. + + ```csharp + protected override void Initialize() + { + // Setup the matrices to look forward + worldMatrix = Matrix.Identity; + viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 50), Vector3.Zero, Vector3.Up); + + projectionMatrix = Matrix.CreatePerspectiveFieldOfView( + MathHelper.PiOver4, + GraphicsDevice.Viewport.AspectRatio, + 1.0f, 300.0f); + + base.Initialize(); + } + ``` + +1. Initialize a [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) with the transformation and light values in the `LoadContent` method. + + ```csharp + protected override void LoadContent() + { + basicEffect = new BasicEffect(_graphics.GraphicsDevice); + + basicEffect.World = worldMatrix; + basicEffect.View = viewMatrix; + basicEffect.Projection = projectionMatrix; + + // primitive color + basicEffect.AmbientLightColor = new Vector3(0.1f, 0.1f, 0.1f); + basicEffect.DiffuseColor = new Vector3(1.0f, 1.0f, 1.0f); + basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f); + basicEffect.SpecularPower = 5.0f; + basicEffect.Alpha = 1.0f; + // The following MUST be enabled if you want to color your vertices + basicEffect.VertexColorEnabled = true; + + // Use the built in 3 lighting mode provided with BasicEffect + basicEffect.EnableDefaultLighting(); + } + ``` + + > [!NOTE] + > If you wish, you can set up the lighting manually through code, as follows: + > [!code-csharp[](./files/basiceffectlighting.cs)] + + +1. Still in `LoadContent`, create the per vertex data using the `VertexPositionColor` format. This example shows the data for the face of a triangle. + + ```csharp + triangleVertices = new VertexPositionColor[3]; + + triangleVertices[0].Position = new Vector3(0f, 0f, 0f); + triangleVertices[0].Color = Color.Red; + triangleVertices[1].Position = new Vector3(10f, 10f, 0f); + triangleVertices[1].Color = Color.Yellow; + triangleVertices[2].Position = new Vector3(10f, 0f, -5f); + triangleVertices[2].Color = Color.Green; + ``` + +1. Finally, in the `Draw` Method, call [GraphicsDevice.Clear](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_Clear_Microsoft_Xna_Framework_Color_) to clear the render target. + +1. Set the rasterizer state to turn off culling using the [RasterizerState](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.RasterizerState) property. + +1. Call [EffectPass.Apply](/api/Microsoft.Xna.Framework.Graphics.EffectPass.html#Microsoft_Xna_Framework_Graphics_EffectPass_Apply) to set the effect state in preparation for rendering. + +1. Draw the geometry by calling [GraphicsDevice.DrawUserPrimitives](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_Microsoft_Xna_Framework_Graphics_VertexDeclaration_). + + ```csharp + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.SteelBlue); + + RasterizerState rasterizerState1 = new RasterizerState(); + rasterizerState1.CullMode = CullMode.None; + GraphicsDevice.RasterizerState = rasterizerState1; + foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) + { + pass.Apply(); + + GraphicsDevice.DrawUserPrimitives( + PrimitiveType.TriangleList, + triangleVertices, + 0, + 1, + VertexPositionColor.VertexDeclaration + ); + } + + base.Draw(gameTime); + } + ``` + +When the sample is run, the basic geometry is rendered using the custom [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect), feel free to play with the position, content or rendering order to enhance the effect. + +## See Also + +- [How to create a State Object](HowTo_Create_a_StateObject.md) + +### Concepts + +- [What Is a Configurable Effect?](../../whatis/graphics/WhatIs_ConfigurableEffect.md) + +### Reference + +- [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) +- [RasterizerState](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.RasterizerState) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Create_a_RenderTarget.md b/articles/getting_to_know/howto/graphics/HowTo_Create_a_RenderTarget.md new file mode 100644 index 0000000..6b66b61 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Create_a_RenderTarget.md @@ -0,0 +1,132 @@ +--- +title: How to create a Render Target +description: Demonstrates how to create a render target using a RenderTarget2D. +requireMSLicense: true +--- + +## Overview + +The example is very basic but the principles are the same, when drawing to a Render Texture we apply the following process. + +1. Set the Graphics Device to output to a texture. +2. Clear the buffer (or not depending on the use case). +3. Draw the full screen contents required in the Render Texture, e.g. a map or camera view. +4. Reset the Graphics device to the back buffer (screen). +5. Draw your game as normal. +6. Draw the Render Texture to the screen in the position we desire (e.g. in the lower corner for a mini-map), most likely on top of your game graphics. + +> [!TIP] +> The technique is very useful, especially if you are doing split-screen gaming and need to draw multiple camera views. + +## Requirements + +This sample uses a `grid` texture (available below) to draw to the [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) before then rendering the contents of the `Render Target` to the screen as a texture. + +![Grid Texture](images/grid.png) + +Download the `Grid` texture and add it to your `Content Project` for this example. (see [How to Add Content](../content_pipeline/HowTo_GameContent_Add.md) for more information on this.) + +## Creating a Render Target + +1. Declare variables for a render target using the [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) class, for this example we will also be using a [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) for the "grid" texture we will output to the `Render Target`. + + ```csharp + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private Texture2D grid; + private RenderTarget2D renderTarget; + ``` + +2. Load the "grid" texture, which contains vertical and horizontal lines. + + ```csharp + protected override void LoadContent() + { + // Create a new SpriteBatch, which can be used to draw textures. + _spriteBatch = new SpriteBatch(GraphicsDevice); + + // using "grid" which matches the NAME of the grid texture in the content project. + grid = Content.Load("grid"); + } + ``` + +3. While still in the `LoadContent` method, create the render target, giving it the same size as either the Texture (shown below) or the display back buffer (if you are rendering full screen), ideally in the [Game.LoadContent](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_LoadContent) method or later. + + ```csharp + renderTarget = new RenderTarget2D( + GraphicsDevice, + grid.Width, + grid.Height); + ``` + +4. Render the "grid" texture to the render target. + + Rendering to a [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) changes the Graphics Device output to write to a `texture` instead of the screen. Once you have finished rendering to the [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) you **MUST** reset the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) Render Target to `null` to return to drawing to the screen / back buffer. + + The example function below, sets the render target on the device, draws the texture (to the render target) using a [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch). When rendering is complete, it then resets the device render target to `null` (which resets the device to the back buffer). + + ```csharp + private void DrawRenderTarget() + { + // Set the device to the render target + GraphicsDevice.SetRenderTarget(renderTarget); + + // Clear the graphics buffer to a solid color + GraphicsDevice.Clear(Color.Black); + + // Draw the "grid" texture to the graphics buffer, currently outputting to the Render Texture. + _spriteBatch.Begin(); + _spriteBatch.Draw(grid, Vector2.Zero, Color.White); + _spriteBatch.End(); + + // Reset the device to the back buffer + GraphicsDevice.SetRenderTarget(null); + } + ``` + +5. Draw the render target texture to the back buffer. + + With the render target populated using the `DrawRenderTarget` function, we can then draw the output to the screen. + + ```csharp + protected override void Draw(GameTime gameTime) + { + // Populate the RenderTarget + DrawRenderTarget(); + + // Clear the screen + GraphicsDevice.Clear(Color.CornflowerBlue); + + // Draw the contents of the Render Target texture + _spriteBatch.Begin(); + _spriteBatch.Draw(renderTarget, + new Vector2(200, 50), // x,y position + new Rectangle(0, 0, 32, 32), // just one grid + Color.White // no color scaling + ); + _spriteBatch.End(); + + base.Draw(gameTime); + } + ``` + +The final output should look like the following: + +![Output](images/HowTo_Create_a_RenderTarget_Final.png) + +Rendering a 32 by 32 square from the RenderTarget texture to a position 200 x 50 on the screen. + + +## See Also + +- [How to create a Basic Effect](HowTo_Create_a_BasicEffect.md) + +### Concepts + +- [What Is a Render Target?](../../whatis/graphics/WhatIs_Render_Target.md) +- [What Is a Back Buffer?](../../whatis/graphics/WhatIs_BackBuffer.md) + +### Reference + +- [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Create_a_StateObject.md b/articles/getting_to_know/howto/graphics/HowTo_Create_a_StateObject.md new file mode 100644 index 0000000..643684c --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Create_a_StateObject.md @@ -0,0 +1,61 @@ +--- +title: How to create a State Object +description: Demonstrates how to create a state object using any of the state object classes. +requireMSLicense: true +--- + +## Overview + +In this example, we will demonstrate how to create a state object using any of the state object classes: [BlendState](xref:Microsoft.Xna.Framework.Graphics.BlendState), [DepthStencilState](xref:Microsoft.Xna.Framework.Graphics.DepthStencilState), [RasterizerState](xref:Microsoft.Xna.Framework.Graphics.RasterizerState), or [SamplerState](xref:Microsoft.Xna.Framework.Graphics.SamplerState). + +## To create a state object + +1. Declare three state object variables as fields in your game. + + This example declares three rasterizer state objects and uses them to change the culling state. + + ```csharp + RasterizerState rsCullNone; + ``` + +2. Create a customizable state object. + + Create a state object from the [RasterizerState](xref:Microsoft.Xna.Framework.Graphics.RasterizerState) class and initialize it by explicitly setting the cull mode. + + ```csharp + rsCullNone = new RasterizerState(); + rsCullNone.CullMode = CullMode.None; + rsCullNone.FillMode = FillMode.WireFrame; + rsCullNone.MultiSampleAntiAlias = false; + ``` + +3. Respond to the user pressing the A key on a gamepad to change the culling mode. + + The application starts with culling turned off; toggle between culling modes by pushing the A key on a gamepad. Unlike a customizable state object, use a built-in state object to create an object with a set of predefined state. + + ```csharp + if (GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Pressed) + { + changeState = true; + } + + if ((changeState) && (GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Released)) + { + if (GraphicsDevice.RasterizerState.CullMode == CullMode.None) + { + GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; + } + else if (GraphicsDevice.RasterizerState.CullMode == CullMode.CullCounterClockwiseFace) + { + GraphicsDevice.RasterizerState = RasterizerState.CullClockwise; + } + else if (GraphicsDevice.RasterizerState.CullMode == CullMode.CullClockwiseFace) + { + GraphicsDevice.RasterizerState = rsCullNone; + } + + changeState = false; + } + ``` + +Try this technique with the [HowTo Create a BasicEffect](./HowTo_Create_a_BasicEffect.md) sample and see what kinds of effects the above functionality applies. diff --git a/articles/getting_to_know/howto/graphics/HowTo_Draw_3D_Primitives.md b/articles/getting_to_know/howto/graphics/HowTo_Draw_3D_Primitives.md new file mode 100644 index 0000000..3e25bc9 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Draw_3D_Primitives.md @@ -0,0 +1,326 @@ +--- +title: Drawing 3D Primitives using Lists or Strips +description: Demonstrates how to draw 3D primitives using lines and triangles arranged as strips or lists. +requireMSLicense: true +--- + +## Overview + +A 3D primitive describes how vertex data is ordered. This example demonstrates line and triangle primitive types that are the basis for all drawing calls in the MonoGame Framework. To render primitives, you need to create a basic effect and transformation matrices. This topic follows the steps described in [Creating a Basic Effect](HowTo_Create_a_BasicEffect.md) to create an instance of [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect). This sample uses orthographic projection, but you can also use perspective projection to render primitives. The vertices used in the sample are of type [VertexPositionColor Structure](xref:Microsoft.Xna.Framework.Graphics.VertexPositionColor) which contains per-vertex position and color. + +### Prerequisites + +This tutorial assumes you are following on from the project created in [How to create a Basic Effect](HowTo_Create_a_BasicEffect.md) + +## Creating Vertices + +The major steps for this example are: + +- Creating Vertices +- Drawing a Line List +- Drawing a Line Strip +- Drawing A Triangle List +- Drawing a Triangle Strip + +## To create vertices + +First we need to setup some data to draw our primitives, essentially a list of points that we will connect together and draw in different ways. + +1. Position the camera and create the required transformations. + + ``` csharp + // Matrix to translate the drawn primitives to the center of the screen. + private Matrix translationMatrix; + + // Number of vertex points to draw the primitive with. + private int points = 8; + + // The length of the primitive lines to draw. + private int lineLength = 100; + + protected override void Initialize() + { + worldMatrix = Matrix.Identity; + + viewMatrix = Matrix.CreateLookAt( + new Vector3(0.0f, 0.0f, 1.0f), + Vector3.Zero, + Vector3.Up + ); + + projectionMatrix = Matrix.CreateOrthographicOffCenter( + 0, + (float)GraphicsDevice.Viewport.Width, + (float)GraphicsDevice.Viewport.Height, + 0, + 1.0f, 1000.0f); + + // Calculate the center of the visible screen using the ViewPort. + Vector2 screenCenter = new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2); + // Calculate the center of the primitives to be drawn. + var primitiveCenter = new Vector2((points / 2 - 1) * lineLength / 2, lineLength / 2); + // Create a translation matrix to position the drawn primitives in the center of the screen and the center of the primitives. + translationMatrix = Matrix.CreateTranslation(screenCenter.X - primitiveCenter.X, screenCenter.Y - primitiveCenter.Y, 0); + + base.Initialize(); + } + ``` + +1. Create a list of vertices in 3D space that represent the points to draw. + + The following code creates eight vertices (determined from the `points` variable) and stores them in an array of type **VertexPositionColor**. + + ``` csharp + // The vertex sata array. + private VertexPositionColor[] primitiveList; + + protected override void LoadContent() + { + ... // <-Existing Load Content from Creating a Basic Effect + + primitiveList = new VertexPositionColor[points]; + + for (int x = 0; x < points / 2; x++) + { + for (int y = 0; y < 2; y++) + { + primitiveList[(x * 2) + y] = new VertexPositionColor( + new Vector3(x * lineLength, y * lineLength, 0), Color.White); + } + } + + // Translate the position of the vertices by the translation matrix calculated earlier. + for (int i = 0; i < primitiveList.Length; i++) + { + primitiveList[i].Position = Vector3.Transform(primitiveList[i].Position, translationMatrix); + } + ``` + + - These eight points form a `triangle strip` consisting of six triangles drawn along the plane `z = 0`, with the first point at `(0, 0, 0)`. + - The camera is positioned at `(0, 0, 1)` looking at `(0, 0, 0)`. + - An orthogonal projection matrix is created with the upper-left point at `(0, 0)` and the lower-right point at the current `GraphicsDevice` screen dimensions. + - In addition, a translation matrix shifts the `primitiveList` point set to the center of the screen. + +1. To make the drawing of lines clearer, also change the `Clear` color in the `Draw` method to `black`. Just makes it easier to see drawn lines. + + ```csharp + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.Black); + ``` + +## Drawing a Line List + +The example in this section uses the sample vertex list created by following step 1 in the `Creating Vertices` steps. + +![Drawing a Line List](images/HowTo_Draw_3D_Primitives_Line_List.png) + +### To draw a line list + +1. Create an index array that indexes into the vertex buffer. + + This identifies a series of lines. + + ``` csharp + private short[] lineListIndices; + + protected override void LoadContent() + { + ... // <-Existing Load Content + + // Initialize an array of indices of type short. + lineListIndices = new short[(points * 2) - 2]; + + // Populate the array with references to indices in the vertex buffer + for (int i = 0; i < points - 1; i++) + { + lineListIndices[i * 2] = (short)(i); + lineListIndices[(i * 2) + 1] = (short)(i + 1); + } + ``` + +2. Render the lines by calling [DrawUserIndexedPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserIndexedPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_System_Int32___System_Int32_System_Int32_), which specifies [PrimitiveType.LineList](xref:Microsoft.Xna.Framework.Graphics.PrimitiveType) to determine how to interpret the data in the vertex array. + + ``` csharp + GraphicsDevice.DrawUserIndexedPrimitives( + PrimitiveType.LineList, + primitiveList, + 0, // vertex buffer offset to add to each element of the index buffer + points, // number of vertices in pointList + lineListIndices, // the index buffer + 0, // first index element to read + points - 1 // number of primitives to draw + ); + ``` + +## Drawing a Line Strip + +The example in this section uses the same point list and renders the same output as the Drawing a Line List procedure. However, it uses a `line strip` primitive type when it identifies the indices of the vertex array to draw. **Fewer indices are stored when you use a line strip.** + +![Drawing a Line List](images/HowTo_Draw_3D_Primitives_Line_List.png) + +### To draw a line strip + +1. Create a list of indices to identify the order in which to draw the points in the specified point list. + + Only half the number of indices used for the line list are needed here because the data consist of a series of connected lines. + + ``` csharp + private short[] lineStripIndices; + + protected override void LoadContent() + { + ... // <-Existing Load Content + + // Initialize an array of indices of type short. + lineStripIndices = new short[points]; + + // Populate the array with references to indices in the vertex buffer. + for (int i = 0; i < points; i++) + { + lineStripIndices[i] = (short)(i); + } + ``` + + > [!NOTE] + > This is equivalent to setting `lineStripIndices` with the following array that consists of a series of **connected** lines between `pointList[0]`, `pointList[1]`, and `pointList[2]`, and so forth. + > + > ``` csharp + > lineStripIndices = new short[8]{ 0, 1, 2, 3, 4, 5, 6, 7 }; + > ``` + +1. Render the line strip by calling [DrawUserIndexedPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserIndexedPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_System_Int32___System_Int32_System_Int32_), which specifies [PrimitiveType.LineStrip](xref:Microsoft.Xna.Framework.Graphics.PrimitiveType) to determine how to interpret the data in the vertex array. + + Fewer vertices are used to render the same number of primitives rendered earlier by the line list. + + ``` csharp + GraphicsDevice.DrawUserIndexedPrimitives( + PrimitiveType.LineList, + primitiveList, + 0, // vertex buffer offset to add to each element of the index buffer + points, // number of vertices in pointList + lineListIndices, // the index buffer + 0, // first index element to read + points - 1 // number of primitives to draw + ); + ``` + +## Drawing A Triangle List + +A triangle list, like a line list, is a primitive type that indicates you need to interpret the vertices in the vertex buffer as a series of separately drawn triangles. + +### To draw a triangle list + +1. Create an array to hold the list of indices that identify a series of triangles to draw from the specified point list. + + ``` csharp + private short[] triangleStripIndices; + private int triangleWidth = 10; + private int triangleHeight = 10; + + protected override void LoadContent() + { + ... // <-Existing Load Content + triangleListIndices = new short[(width - 1) * (height - 1) * 6]; + + for (int x = 0; x < width - 1; x++) + { + for (int y = 0; y < height - 1; y++) + { + triangleListIndices[(x + y * (width - 1)) * 6] = (short)(2 * x); + triangleListIndices[(x + y * (width - 1)) * 6 + 1] = (short)(2 * x + 1); + triangleListIndices[(x + y * (width - 1)) * 6 + 2] = (short)(2 * x + 2); + + triangleListIndices[(x + y * (width - 1)) * 6 + 3] = (short)(2 * x + 2); + triangleListIndices[(x + y * (width - 1)) * 6 + 4] = (short)(2 * x + 1); + triangleListIndices[(x + y * (width - 1)) * 6 + 5] = (short)(2 * x + 3); + } + } + ``` + + > [!NOTE] + > This is equivalent to setting `triangleListIndices` to the following array, which consists of a series of triangles between `pointList[0]`, `pointList[1]`, and `pointList[2]`, and so forth. + > + > ``` csharp + > triangleListIndices = new short[18]{ 0, 1, 2, 2, 1, 3, 2, 3, 4, 4, 3, 5, 4, 5, 6, 6, 5, 7 }; + > ``` + +2. Render the lines by calling [DrawUserIndexedPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserIndexedPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_System_Int32___System_Int32_System_Int32_) + + This specifies [PrimitiveType.TriangleList](xref:Microsoft.Xna.Framework.Graphics.PrimitiveType), which determines how the data in the vertex array is interpreted. + + ``` csharp + GraphicsDevice.DrawUserIndexedPrimitives( + PrimitiveType.TriangleList, + primitiveList, + 0, // vertex buffer offset to add to each element of the index buffer + 8, // number of vertices to draw + triangleListIndices, + 0, // first index element to read + 6 // number of primitives to draw + ); + ``` + +## Drawing a Triangle Strip + +A triangle strip is a set of triangles that share multiple vertices. This example shows you how to render an object that looks the same as the object rendered with a triangle list. However, fewer vertices are needed because the triangles share multiple vertices. + +### To draw a triangle strip + +1. Create an array to hold the list of indices that identify a strip of triangles. + + ``` csharp + private short[] triangleStripIndices; + + protected override void LoadContent() + { + ... // <-Existing Load Content + + // Initialize an array of indices of type short. + triangleStripIndices = new short[points]; + + // Populate the array with references to indices in the vertex buffer. + for (int i = 0; i < points; i++) + { + triangleStripIndices[i] = (short)i; + } + ``` + + > [!NOTE] + > This is equivalent to setting `triangleStripIndices` to the following array, which consists of a series of **connected** triangles between `pointList[0]`, `pointList[1]`, and `pointList[2]`, and so forth. + > + > ``` csharp + > triangleStripIndices = new short[8]{ 0, 1, 2, 3, 4, 5, 6, 7 }; + > ``` + +2. Render the lines by calling [DrawUserIndexedPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserIndexedPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_System_Int32___System_Int32_System_Int32_). + + This specifies [PrimitiveType.TriangleStrip](xref:Microsoft.Xna.Framework.Graphics.PrimitiveType) to determine how to interpret the data in the vertex array. Fewer vertices are used to render the same number of primitives rendered earlier by the triangle list. + + > [!NOTE] + > In the example code, the triangle strip is rendered by a series of red lines instead of the white lines used for the previous triangle list. The color change indicates a different primitive type was used to achieve the same result. + + ``` csharp + GraphicsDevice.DrawUserIndexedPrimitives( + PrimitiveType.TriangleStrip, + primitiveList, + 0, // vertex buffer offset to add to each element of the index buffer + 8, // number of vertices to draw + triangleStripIndices, + 0, // first index element to read + 6 // number of primitives to draw + ); + ``` + +## See Also + +- [How to enable Anti-aliasing](HowTo_Enable_Anti_Aliasing.md) + +### Concepts + +- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) + +### Reference + +- [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [DrawUserIndexedPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserIndexedPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_System_Int32___System_Int32_System_Int32_) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Draw_Text.md b/articles/getting_to_know/howto/graphics/HowTo_Draw_Text.md new file mode 100644 index 0000000..19fa31d --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Draw_Text.md @@ -0,0 +1,126 @@ +--- +title: Drawing Text with a Sprite +description: Demonstrates how to import a SpriteFont into a project and to draw text using DrawString +requireMSLicense: true +--- + +## Overview + +MonoGame provides a quick and easy method for drawing text using any registered Font file installed on the development PC, this is not needed in the final game as the true type font is converted into a texture for rendering, making the process easy and seamless. + +### End result + +![The output of this tutorial](images/HowTo_Draw_Text_Final.png) + +## Adding a Sprite Font and Drawing Text + +1. Open your `Content.mgcb` file using the `MGCB Editor` and click **New Item** Button. + +1. In the **Add New Item** dialog box, select **SpriteFont Description** and set the filename to "**MyMenuFont**" in the edit box at the top of the dialog. + + > [!NOTE] + > You may find it convenient at this point to change the name of the new file from "Spritefont1" to the friendly name of the font you intend to load (keeping the .spritefont file extension). The friendly name identifies the font once it is installed on your computer, for example, `Courier New` or `Times New Roman`. When you reference the font in your code, you must use the friendly name you have assigned it. + Pipeline tool creates a new `.spritefont` file for your font. + +1. Double-click on your new font file in the `MGCB Editor` which will open the `SpriteFont` text file in your default editor. Alternatively, you can **right-click** and select `Open With` to choose a different editor. + +1. By default the font `Arial` will be used by the `SpriteFont` configuration, to change this to another installed font simply type the friendly name of the font to load into the `FontName` element. For the purposes of this tutorial, I have set the Font size to **54** and left the rest of the `SpriteFont` settings as the default. + + > [!IMPORTANT] + > This is not the name of a font file, but rather the name that identifies the font once it is installed on your computer. + > + > You can view the installed fonts on your machine in the `Settings -> Personalization -> Fonts` configuration on your Windows machine (or relevant place on Mac /Linux) or to install new ones. + + The content pipeline supports the same fonts as the [System.Drawing.Font](http://msdn.microsoft.com/en-us/library/system.drawing.font.aspx) class, including TrueType fonts, but not bitmap (.fon) fonts. You may find it convenient to save the new `.spritefont` file using this friendly name. When you reference the font in your code, you must use the friendly name you have assigned it. + + > [!NOTE] + > If you want to use a custom font, you should put the `.ttf` or `.oft` in the same directory as the `.spritefont` file and the build system will pick it up. There is no need to install the font system wide. + +1. If necessary, change the `Size` entry to the point size you desire for your font. + +1. If necessary, change the `Style` entry to the style of font to import. + You can specify **Regular**, **Bold**, **Italic**, or **Bold, Italic**. The **Style** entry is case sensitive. + +1. Specify the character regions to import for this font. + + > [!NOTE] + > Character regions specify which characters in the font are rendered by the [SpriteFont](xref:Microsoft.Xna.Framework.Graphics.SpriteFont). You can specify the start and end of the region by using the characters themselves, or by using their decimal values with an &# prefix. The default character region includes all the characters between the space and tilde characters, inclusive. + +### To draw text on the screen + +1. Add a Sprite Font to your project as described above. + +1. Create a [SpriteFont](xref:Microsoft.Xna.Framework.Graphics.SpriteFont) reference to encapsulate the imported font. + +1. Create a [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) object for drawing the font on the screen. + +1. In your [Game.LoadContent](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_LoadContent) method, call [ContentManager.Load](xref:Microsoft.Xna.Framework.Content.ContentManager#Microsoft_Xna_Framework_Content_ContentManager_Load__1_System_String_), specifying the [SpriteFont](xref:Microsoft.Xna.Framework.Graphics.SpriteFont) class and the asset name of the imported font. + +1. Create your [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) object, passing the current [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice). + + ```csharp + // The Sprite Font reference to draw with + SpriteFont font1; + + // The position to draw the text + Vector2 fontPos; + + protected override void LoadContent() + { + // Create a new SpriteBatch, which can be used to draw textures. + _spriteBatch = new SpriteBatch(GraphicsDevice); + font1 = Content.Load("MyMenuFont"); + Viewport viewport = _graphics.GraphicsDevice.Viewport; + + // TODO: Load your game content here + fontPos = new Vector2(viewport.Width / 2, viewport.Height / 2); + } + ``` + +1. In your [Game.Draw](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Draw_Microsoft_Xna_Framework_GameTime_) method, call [SpriteBatch.Begin](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Begin_Microsoft_Xna_Framework_Graphics_SpriteSortMode_Microsoft_Xna_Framework_Graphics_BlendState_Microsoft_Xna_Framework_Graphics_SamplerState_Microsoft_Xna_Framework_Graphics_DepthStencilState_Microsoft_Xna_Framework_Graphics_RasterizerState_Microsoft_Xna_Framework_Graphics_Effect_System_Nullable_Microsoft_Xna_Framework_Matrix__) on the [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) object. + +1. If necessary, determine the origin (center) of your text. + + If you want to draw your text centered on a point, you can find the center of the text by calling [SpriteFont.MeasureString](xref:Microsoft.Xna.Framework.Graphics.SpriteFont#Microsoft_Xna_Framework_Graphics_SpriteFont_MeasureString_System_String_) and dividing the returned vector by 2. + +1. Call [SpriteBatch.DrawString](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_DrawString_Microsoft_Xna_Framework_Graphics_SpriteFont_System_String_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) to draw your output text, specifying the [SpriteFont](xref:Microsoft.Xna.Framework.Graphics.SpriteFont) object for the font you want to use. + + All other parameters of [SpriteBatch.DrawString](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_DrawString_Microsoft_Xna_Framework_Graphics_SpriteFont_System_String_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) produce the same effects as a call to [SpriteBatch.Draw](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_Draw_Microsoft_Xna_Framework_Graphics_Texture2D_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_). + +1. Call [SpriteBatch.End](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_End) after all text is drawn. + + ```csharp + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(); + + // Draw Hello World + string output = "Hello World"; + + // Find the center of the string + Vector2 FontOrigin = font1.MeasureString(output) / 2; + // Draw the string + _spriteBatch.DrawString(font1, output, fontPos, Color.LightGreen, + 0, FontOrigin, 1.0f, SpriteEffects.None, 0.5f); + + _spriteBatch.End(); + base.Draw(gameTime); + } + ``` + +## See Also + +- [Drawing a Sprite](HowTo_Draw_A_Sprite.md) + +### Concepts + +- [What Is a Sprite?](../../whatis/graphics/WhatIs_Sprite.md) + +### Reference + +- [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) +- [SpriteBatch.DrawString](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch#Microsoft_Xna_Framework_Graphics_SpriteBatch_DrawString_Microsoft_Xna_Framework_Graphics_SpriteFont_System_String_Microsoft_Xna_Framework_Vector2_Microsoft_Xna_Framework_Color_) +- [SpriteFont](xref:Microsoft.Xna.Framework.Graphics.SpriteFont) +- [ContentManager.Load](xref:Microsoft.Xna.Framework.Content.ContentManager#Microsoft_Xna_Framework_Content_ContentManager_Load__1_System_String_) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Draw_Textured_Quad.md b/articles/getting_to_know/howto/graphics/HowTo_Draw_Textured_Quad.md new file mode 100644 index 0000000..995c9e0 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Draw_Textured_Quad.md @@ -0,0 +1,157 @@ +--- +title: Creating a Custom Effect with Texturing +description: Demonstrates how to use a custom effect and a texture to render a 3D object. +requireMSLicense: true +--- + +## Overview + +Drawing a textured quad is a basic technique to have in any Game Developers arsenal, which can be populated by any texture from either the Content Pipeline (loaded from disk) or generated in memory (which we will use here for simplicity). + +> [!NOTE] +> Drawing a texture quad is in effect what a SpriteBatch does under the hood, but while a SpriteBatch natively only draws flat to the screen, a Quad can be positioned in any way you see fit. Either approach has its pros and cons. + +There is a but of setup to draw a quad in MonoGame and there are many ways to achieve it. + +> [!NOTE] +> This example draws from community responses to the same question [here, on the MonoGame Community site](https://community.monogame.net/t/minimal-example-of-drawing-a-quad-into-2d-space/11063/2), with a little clean-up to make it simpler. + +## To use a custom effect with a texture + +1. Create a custom vertex format declaration and a set of indices to indicate the drawing order. + + ``` csharp + // A Vertex format with Texture information + private VertexPositionColorTexture[] drawingQuad; + + // The indices array for drawing a quad + private short[] drawingIndices; + + public void SetupUserIndexedVertexRectangle(Rectangle r) + { + drawingQuad = new VertexPositionColorTexture[4]; + drawingQuad[0] = new VertexPositionColorTexture(new Vector3(r.Left, r.Top, 0f), Color.White, new Vector2(0f, 0f)); + drawingQuad[1] = new VertexPositionColorTexture(new Vector3(r.Left, r.Bottom, 0f), Color.Red, new Vector2(0f, 1f)); + drawingQuad[2] = new VertexPositionColorTexture(new Vector3(r.Right, r.Bottom, 0f), Color.Green, new Vector2(1f, 1f)); + drawingQuad[3] = new VertexPositionColorTexture(new Vector3(r.Right, r.Top, 0f), Color.Blue, new Vector2(1f, 0f)); + + drawingIndices = [0, 2, 1, 2, 0, 3]; + } + ``` + +1. To make setup simpler, we will also define two methods to Set the [Graphics State](HowTo_Create_a_StateObject.md) and [create our basic effect](xref:Microsoft.Xna.Framework.Graphics.Effect). + + ``` csharp + // The basic effect definition + private BasicEffect basicEffect; + + // A Texture2D that we will generate data into + private Texture2D generatedTexture; + + /// + /// Set the states for the graphics device. + /// + private void SetStates() + { + GraphicsDevice.BlendState = BlendState.Opaque; + GraphicsDevice.DepthStencilState = DepthStencilState.Default; + GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap; + GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; + } + + /// + /// Creates a basic effect for drawing a textured quad. + /// + private void SetUpBasicEffect() + { + basicEffect = new BasicEffect(this.GraphicsDevice); + basicEffect.VertexColorEnabled = true; + basicEffect.TextureEnabled = true; + basicEffect.Texture = generatedTexture; + + // set up our matrix to match basic effect. + Viewport viewport = GraphicsDevice.Viewport; + basicEffect.World = Matrix.Identity; + Vector3 cameraUp = Vector3.Transform(Vector3.Down, Matrix.CreateRotationZ(0)); + basicEffect.View = Matrix.CreateLookAt(Vector3.Forward, Vector3.Zero, cameraUp); + basicEffect.Projection = Matrix.CreateScale(1, -1, 1) * Matrix.CreateOrthographicOffCenter(0, viewport.Width, viewport.Height, 0, 0, 1); + } + ``` + + > [!NOTE] + > Note that the basic effect is created with `basicEffect.TextureEnabled = true;` and the texture to draw using `basicEffect.Texture = generatedTexture;`, just stating we are drawing a texture and what it is. + +1. Next, we will generate a Texture to draw as part of the quad, a simple white texture which the effect will also draw a coloured "tint" over thanks to the `basicEffect.VertexColorEnabled = true;` set in the effect. + + ```csharp + private Texture2D GenerateTexture2D() + { + Texture2D t = new Texture2D(this.GraphicsDevice, 250, 250); + var cdata = new Color[250 * 250]; + for (int i = 0; i < 250; i++) + { + for (int j = 0; j < 250; j++) + { + cdata[i * 250 + j] = Color.White; + } + } + t.SetData(cdata); + return t; + } + ``` + + > [!NOTE] + > Alternatively, you can just use a texture loaded from the Content Pipeline, just be sure to change the Vertex format used in Step 1 to `VertexPositionTexture` unless you want the coloured gradient, or simply disable `basicEffect.VertexColorEnabled = false;`. That is unless you want to apply color tints with the vertex declaration. + +1. Putting this together, setup all the relevant artifacts in the `LoadContent` method. + + ```csharp + protected override void LoadContent() + { + // Set render state + SetStates(); + + // Setup basic effect + SetUpBasicEffect(); + + // Create the quad to draw + SetupUserIndexedVertexRectangle(new Rectangle(10, 40, 450, 260)); + + // Generate (or load) the Texture + generatedTexture = GenerateTexture2D(); + } + ``` + +1. Finally, draw the primitive quad to the screen using the BasicEffect and generated data. + + ```csharp + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) + { + pass.Apply(); + GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, drawingQuad, 0, 4, drawingIndices, 0, 2); + } + + base.Draw(gameTime); + } + ``` + +1. Marvel at the wonder of your drawn Textured Quad plus vertex effect. + + ![Final effect](./images/HowTo_DrawTexturedQuad_Final.png) + +## See Also + +- [How to create a Basic Effect](HowTo_Create_a_BasicEffect.md) + +### Concepts + +- [3D Pipeline Basics](../../whatis/graphics/WhatIs_3DRendering.md) + +### Reference + +- [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) diff --git a/articles/getting_to_know/howto/graphics/HowTo_DynamicallyUpdateVertices.md b/articles/getting_to_know/howto/graphics/HowTo_DynamicallyUpdateVertices.md new file mode 100644 index 0000000..14d7dec --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_DynamicallyUpdateVertices.md @@ -0,0 +1,44 @@ +--- +title: How to Dynamically Update Vertex Data +description: Describes techniques for dynamically updating vertex data in an MonoGame game. +requireMSLicense: true +--- + +## Overview + +Geometry in a 3D game is defined by vertex data. Sometimes, a game needs to modify vertex data or even generate new vertex data dynamically (at run time). Here are some solutions for dynamically updating vertex data. + +## Updating a Set of Primitives Dynamically + +The [Primitives Sample](https://github.com/simondarksidej/XNAGameStudio/wiki/Primitives) demonstrates a dynamic vertex buffer that is generated during each rendering frame. The sample renders primitives by first calling `Begin`, adding the necessary vertices, using the `Add` method, and then calling `End`. This forces the buffer to be drawn to the current device. The `Flush` method calls [GraphicsDevice.DrawUserPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_) method when `End` is called or when the buffer has no room for new vertices. If there is no room, the buffer is written to the device, it is reset, and the pending vertices are added. + +## Dynamically Rendering a Persistent Set of Primitives + +The [Particle 3D Sample](https://github.com/simondarksidej/XNAGameStudio/wiki/Particles-3D), implements a dynamic vertex buffer that contains custom vertices with a limited lifespan. The application adds and removes particles into a fixed length buffer. The custom shader of the sample renders the active subset of vertices dynamically. Because particles have a limited lifespan, the `ParticleSystem` class handles all adding, updating, and deleting of the vertex buffer in real time. + +## Generating Geometry Programmatically + +Sometimes, your game needs to generate geometry because the geometry is not known at design-time or it changes at run time. For this scenario, create a dynamic vertex and index buffer, and use [VertexBuffer.SetData](xref:Microsoft.Xna.Framework.Graphics.VertexBuffer) and [IndexBuffer.SetData](xref:Microsoft.Xna.Framework.Graphics.IndexBuffer) to set or change the data at run time. + +## Remarks + +Create a dynamic vertex or index buffer using [DynamicVertexBuffer](xref:Microsoft.Xna.Framework.Graphics.DynamicVertexBuffer) and [DynamicIndexBuffer](xref:Microsoft.Xna.Framework.Graphics.DynamicIndexBuffer) ; create a static vertex or index buffer using [VertexBuffer](xref:Microsoft.Xna.Framework.Graphics.VertexBuffer) and [IndexBuffer](xref:Microsoft.Xna.Framework.Graphics.IndexBuffer). Use a dynamic buffer for vertex data that is updated every render frame, otherwise, use a static buffer. + +The samples are located on the App Hub Web site. For a more advanced solution for dynamic vertex updating, download the [Generated Geometry Sample](http://go.microsoft.com/fwlink/?LinkId=93007). This sample uses the [MeshBuilder](xref:Microsoft.Xna.Framework.Content.Pipeline.Graphics.MeshBuilder) helper class and a custom processor to generate a terrain map from a bitmap loaded by the content manager. Specifically, examine the `Process` method, located in TerrainProcessor.cs, which programmatically creates the terrain geometry based on input from the specified bitmap. + +## See Also + +- [How to articles for the Graphics Pipeline](index.md) + +### Concepts + +- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is a Configurable Effect?](../../whatis/graphics/WhatIs_ConfigurableEffect.md) + +### Reference + +- [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) +- [VertexBuffer](xref:Microsoft.Xna.Framework.Graphics.VertexBuffer) +- [IndexBuffer](xref:Microsoft.Xna.Framework.Graphics.IndexBuffer) +- [DynamicVertexBuffer](xref:Microsoft.Xna.Framework.Graphics.DynamicVertexBuffer) +- [DynamicIndexBuffer](xref:Microsoft.Xna.Framework.Graphics.DynamicIndexBuffer) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Enable_Anti_Aliasing.md b/articles/getting_to_know/howto/graphics/HowTo_Enable_Anti_Aliasing.md new file mode 100644 index 0000000..fb2caaf --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Enable_Anti_Aliasing.md @@ -0,0 +1,70 @@ +--- +title: How to enable anti-aliasing +description: Demonstrates how to enable anti-aliasing for your game. +requireMSLicense: true +--- + +## Overview + +**Figure 1.  Anti-aliasing the edges of a cube: multi-sampling is disabled on the left, and enabled on the right.** + +![Anti-aliasing the edges of a cube: multi-sampling is disabled on the left, and enabled on the right](images/graphics_aa.jpg) + +Anti-aliasing is a technique for minimizing distortion artifacts caused by aliasing when rendering a high-resolution signal (such as a sharp edge) at a low resolution (such as in a [render target](../../whatis/graphics/WhatIs_Render_Target.md) with a fixed number of pixel locations). anti-aliasing smooths sharp edges by partially rendering to neighboring pixels. + +This technique is also called multi-sampling because each pixel value can be the result of multiple samples. + +## To enable anti-aliasing in your game + +1. Render 3D geometry. One way to do this is by creating a BasicEffect using the [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) class. For more detail, see [Creating a Basic Effect](HowTo_Create_a_BasicEffect.md). + +1. Set [PreferMultiSampling](/api/Microsoft.Xna.Framework.GraphicsDeviceManager.html#Microsoft_Xna_Framework_GraphicsDeviceManager_PreferMultiSampling) to **true** in your [Game](xref:Microsoft.Xna.Framework.Game) class constructor. + + ```csharp + graphics.PreferMultiSampling = true; + ``` + +1. Set the **view matrix** to place the camera close to the object so you can more clearly see the smoothed, anti-aliased edges. + + ```csharp + worldMatrix = Matrix.CreateRotationX(tilt) * Matrix.CreateRotationY(tilt); + + viewMatrix = Matrix.CreateLookAt(new Vector3(1.75f, 1.75f, 1.75f), Vector3.Zero, Vector3.Up); + + projectionMatrix = Matrix.CreatePerspectiveFieldOfView( + MathHelper.ToRadians(45), // 45 degree angle + (float)GraphicsDevice.Viewport.Width / + (float)GraphicsDevice.Viewport.Height, + 1.0f, 100.0f); + ``` + +1. Draw the geometry by calling [GraphicsDevice.DrawPrimitives](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawPrimitives_Microsoft_Xna_Framework_Graphics_PrimitiveType_System_Int32_System_Int32_). + + ```csharp + RasterizerState rasterizerState1 = new RasterizerState(); + rasterizerState1.CullMode = CullMode.None; + graphics.GraphicsDevice.RasterizerState = rasterizerState1; + foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) + { + pass.Apply(); + + graphics.GraphicsDevice.DrawPrimitives( + PrimitiveType.TriangleList, + 0, + 12 + ); + } + ``` + +## See Also + +### Concepts + +- [3D Pipeline Basics](../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is anti-aliasing?](../../whatis/graphics/WhatIs_Antialiasing.md) + +### Reference + +- [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) +- [PreparingDeviceSettings](/api/Microsoft.Xna.Framework.GraphicsDeviceManager.html#Microsoft_Xna_Framework_GraphicsDeviceManager_PreparingDeviceSettings) +- [PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters) diff --git a/articles/getting_to_know/howto/graphics/HowTo_FitCameraToScene.md b/articles/getting_to_know/howto/graphics/HowTo_FitCameraToScene.md new file mode 100644 index 0000000..51285b4 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_FitCameraToScene.md @@ -0,0 +1,84 @@ +--- +title: How to position the Camera +description: Demonstrates how to position the camera so that all objects in a scene are within the view frustum while maintaining the camera's original orientation. +requireMSLicense: true +--- + +## Overview + +Managing cameras in a 3D environment can be one of the most challenging tasks for any MonoGame developer, if your camera is looking the wrong way then you will not see anything on screen, or at least not what you were expecting. + +A simple technique to handle this is to create a [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) around your visible game content and then have the camera look at the center of it. + +## To position the camera to view all objects in a scene + +1. Create a [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) class that contains all of the objects in the scene. To create the sphere, loop through all of the objects in the scene, merging the [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) classes that contain them with **CreateMerged**. + +2. If you are not already tracking the [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) classes for collision detection, use **CreateFromBoundingBox** or **CreateFromPoints** to create them from [BoundingBox](xref:Microsoft.Xna.Framework.BoundingBox) classes or points. + + In this example, the [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) classes are created from [BoundingBox](xref:Microsoft.Xna.Framework.BoundingBox) classes. + + ```csharp + BoundingSphere GetSceneSphere() + { + BoundingSphere sceneSphere = + new BoundingSphere(new Vector3(.5f, 1, .5f), 1.5f); + for (int z = 0; z < 5; z++) + { + for (int x = 0; x < 5; x++) + { + BoundingSphere boundingSphere = + sphere.Meshes[0].BoundingSphere; + boundingSphere.Center = new Vector3(x * 3, 0, z * 3); + + sceneSphere = BoundingSphere.CreateMerged( + sceneSphere, boundingSphere); + } + } + + return sceneSphere; + } + ``` + +3. Set the position of the camera to the center of the [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) that contains the scene. + + ```csharp + cameraPosition = sceneSphere.Center; + ``` + +4. Determine the distance from the center of the [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) that the camera needs to be to view the entire scene. + + This distance is equal to the hypotenuse of the triangle formed by the center of the sphere, the desired camera position, and the point where the sphere touches the view frustum. One angle of the triangle is known to be the field of view of the camera divided by two. One leg of the triangle is known to be the radius of the sphere. Given these two measurements, you can calculate the hypotenuse as the radius of the sphere divided by the sine of half the field of view. + + ```csharp + float distanceToCenter = sceneSphere.Radius / (float)Math.Sin(FOV / 2); + ``` + +5. Get the [Backward](xref:Microsoft.Xna.Framework.Matrix.Backward) vector of the view [Matrix](xref:Microsoft.Xna.Framework.Matrix) and flip its X component. + + ```csharp + Vector3 back = view.Backward; + back.X = -back.X; //flip x's sign + ``` + +6. To move the camera backward with respect to its orientation, multiply the desired distance by the adjusted back vector from the previous step. + + The camera is now facing the center of the sphere containing the scene and is far enough back that the sphere fits in the camera's view frustum. + + ```csharp + cameraPosition += (back * distanceToCenter); + ``` + +## See Also + +- [Rotating and Moving the Camera](HowTo_RotateMoveCamera.md) + +### Concepts + +- [What Is a View Frustum?](../../whatis/graphics/WhatIs_ViewFrustum.md) +- [What Is a Viewport?](../../whatis/graphics/WhatIs_Viewport.md) + +### Reference + +- [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) diff --git a/articles/getting_to_know/howto/graphics/HowTo_FullScreen.md b/articles/getting_to_know/howto/graphics/HowTo_FullScreen.md new file mode 100644 index 0000000..cb7151d --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_FullScreen.md @@ -0,0 +1,53 @@ +--- +title: How to create a Full-Screen Game +description: Demonstrates how to start a game in full-screen mode. +requireMSLicense: true +--- + +## Overview + +By default, MonoGame will render in a Window pre-set to the default (800 x 480) resolution. If you instead want to render to the full screen, then is it as simple as flipping a switch and the renderer will use the full dimensions of the targeted display device. + +> [!NOTE] +> Rendering to the full screen does NOT change the resolution that the game will be drawn in, that is something as a game developer you have to control. This is because the resolution the game draws at will have a direct impact on the content you are rendering, so you need to best control what gets drawn and how. + +## To create a full-screen game + +1. Derive a class from [Game](xref:Microsoft.Xna.Framework.Game). + +1. After creating the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager), set its [PreferredBackBufferWidth](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.PreferredBackBufferWidth) and [PreferredBackBufferHeight](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.PreferredBackBufferHeight) to the desired screen height and width. + + > [!NOTE] + > Check the [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) guide on the various ways the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) and [Back Buffer?](../../whatis/graphics/WhatIs_BackBuffer.md) can be initialized. + +1. Set [IsFullScreen](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.IsFullScreen) to **true**. + + ```csharp + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + // Setup up the default resolution for the project + _graphics.PreferredBackBufferWidth = 800; + _graphics.PreferredBackBufferHeight = 480; + + // Runs the game in "full Screen" mode using the set resolution + _graphics.IsFullScreen = true; + + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + ``` + +## See Also + +- [How to articles for the Graphics Pipeline](index.md) + +### Concepts + +- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is a Back Buffer?](../../whatis/graphics/WhatIs_BackBuffer.md) +- [What Is a Viewport?](../../whatis/graphics/WhatIs_Viewport.md) + +### Reference + +- [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) diff --git a/articles/getting_to_know/howto/graphics/HowTo_RenderModel.md b/articles/getting_to_know/howto/graphics/HowTo_RenderModel.md new file mode 100644 index 0000000..4730772 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_RenderModel.md @@ -0,0 +1,183 @@ +--- +title: How to render a Model using a Basic Effect +description: Demonstrates how to load and render a model using the MonoGame Content Pipeline. +requireMSLicense: true +--- + +## Overview + +This example has three main parts: + +- Importing and processing the model +- Drawing the resultant managed object as a model with full lighting effect in the game +- Enabling movement of the model with a game pad. + +## Requirements + +> It is assumed that an existing project is loaded in MonoGame. In this example, the project is called "CPModel". + +## Adding a Model + +Follow the steps in [How to add content](../content_pipeline/HowTo_GameContent_Add.md) in order to add a Model to your project. + +For this example, use the [Fuel Carrier model](https://github.com/MonoGame/MonoGame.Samples/raw/3.8.2/FuelCell/FuelCell.Core/Content/Models/fuelcarrier.fbx) file and its corresponding [diffuse texture](https://github.com/MonoGame/MonoGame.Samples/raw/3.8.2/FuelCell/FuelCell.Core/Content/Models/ShipDiffuse.tga). But you can use any model file you wish, and set the **Content Importer** to `FBX Importer - MonoGame` and the **Content Processor** is `Model - MonoGame` (which should be the default for an FBX) and Save the solution. + +The remaining parts render the model and add some user control of the model. All code modifications for this part occur within the game1.cs file of the game project. + +## Rendering the model + +1. Open the `game1.cs` file. +2. Modify the **Game1** class by adding the following code at the beginning of the declaration. + + ```csharp + private Model gameShip; + ``` + + This member holds the ship model. + +3. Modify the **LoadContent** method by adding the following code. + + ```csharp + gameShip = Content.Load("fuelcarrier"); + ``` + + This code loads the model into the `gameShip` member (using [Load](xref:Microsoft.Xna.Framework.Content.ContentManager)). + +4. Create a new **private** method (called **DrawModel**) in the **Game1** class by adding the following code before the existing [Game.Draw](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Draw_Microsoft_Xna_Framework_GameTime_) method. + + ```csharp + private void DrawModel(Model m) + { + Matrix[] transforms = new Matrix[m.Bones.Count]; + float aspectRatio = GraphicsDevice.Viewport.AspectRatio; + m.CopyAbsoluteBoneTransformsTo(transforms); + Matrix projection = + Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), + aspectRatio, 1.0f, 10000.0f); + Matrix view = Matrix.CreateLookAt(new Vector3(0.0f, 50.0f, zoom), + Vector3.Zero, Vector3.Up); + + foreach (ModelMesh mesh in m.Meshes) + { + foreach (BasicEffect effect in mesh.Effects) + { + effect.EnableDefaultLighting(); + + effect.View = view; + effect.Projection = projection; + effect.World = gameWorldRotation * + transforms[mesh.ParentBone.Index] * + Matrix.CreateTranslation(position); + } + mesh.Draw(); + } + } + ``` + + This code sets up the lighting effects for each sub-mesh of the model. The `gameWorldRotation` and `Zoom` variables are used for player control. This functionality is added later. + + > This render code is designed for only those models with a [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) (set in the `MGCB` editor as the `defaultEffect` property for the model). For custom effects, the inner `for-each` loop should be changed to use the [Effect](xref:Microsoft.Xna.Framework.Graphics.Effect) class instead of the [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) class. In addition, you must use [EffectParameter](xref:Microsoft.Xna.Framework.Graphics.EffectParameter) objects to manually set the world, view, and projection matrices. + +5. Modify the **Game1.Draw** method by replacing the following code `**// TODO: Add your drawing code here` with the following code: + + ```csharp + DrawModel(gameShip); + ``` + + This initializes the model's effects before the model is rendered. + +6. Save the solution. + +At this point, the rendering code for the model is complete, but the user control code still needs implementation. + +> [!IMPORTANT] +> The project will not run as this point as there is more to add. + +## Moving the model + +To begin moving the model, we need to add some controls and User input. + +1. Modify the **Game1** class by adding the following code after the `gameShip` declaration. + + ```csharp + private Vector3 position = Vector3.One; + private float zoom = 2500; + private float rotationY = 0.0f; + private float rotationX = 0.0f; + private Matrix gameWorldRotation; + float speed = 10f; + ``` + + These members store the current position, zoom, and rotation values. In addition, the `gameWorldRotation` is updated by the `UpdateGamePad` method below. + +2. Add a private method (called **UpdateGamePad**) before the call to [Game.Update](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Update_Microsoft_Xna_Framework_GameTime_). + + ```csharp + private void UpdateGamePad() + { + GamePadState gamePadState = GamePad.GetState(PlayerIndex.One); + KeyboardState keyState = Keyboard.GetState(); + + // Gamepad controls + position.X += gamePadState.ThumbSticks.Left.X * speed; + position.Y += gamePadState.ThumbSticks.Left.Y * speed; + zoom += gamePadState.ThumbSticks.Right.Y * speed; + rotationY += gamePadState.ThumbSticks.Right.X * speed; + if (gamePadState.Buttons.RightShoulder == ButtonState.Pressed) + { + rotationX += 1.0f * speed; + } + else if (gamePadState.Buttons.LeftShoulder == ButtonState.Pressed) + { + rotationX -= 1.0f * speed; + } + + // Keyboard controls + if (keyState.IsKeyDown(Keys.A)) { position.X += 1.0f * speed; } + else if (keyState.IsKeyDown(Keys.D)) { position.X -= 1.0f * speed; } + if (keyState.IsKeyDown(Keys.W)) { zoom += 1.0f * speed; } + else if (keyState.IsKeyDown(Keys.S)) { zoom -= 1.0f * speed; } + if (keyState.IsKeyDown(Keys.E)) { rotationY += 1.0f * speed; } + else if (keyState.IsKeyDown(Keys.Q)) { rotationY -= 1.0f * speed; } + + if (keyState.IsKeyDown(Keys.Right)) { position.Y += 1.0f * speed; } + else if (keyState.IsKeyDown(Keys.Left)) { position.Y -= 1.0f * speed; } + if (keyState.IsKeyDown(Keys.Up)) { rotationX += 1.0f * speed; } + else if (keyState.IsKeyDown(Keys.Down)) { rotationX -= 1.0f * speed; } + + gameWorldRotation = + Matrix.CreateRotationX(MathHelper.ToRadians(rotationX)) * + Matrix.CreateRotationY(MathHelper.ToRadians(rotationY)); + } + ``` + + This code implements an exit method for the game (pressing the **A** button on a GamePad), and updates the position members with the current input of the game controller. + +3. Modify the **Update** method by adding a call to `UpdateGamePad`, before the call to [Game.Update](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Update_Microsoft_Xna_Framework_GameTime_). + + ```csharp + UpdateGamePad(); + ``` + + This code updates the state of the position variables with the latest input. + +4. Save the solution. + +Development is complete so you are ready to build and run the game. Control the ship location with the game pad, and exit by pressing the **A** button. + +## See Also + +- [Adding Content to a Game](../content_pipeline/HowTo_GameContent_Add.md) +- [Using Input](../input/index.md) + +### Concepts + +- [What Is a Configurable Effect?](../../whatis/graphics/WhatIs_3DRendering.md) +- [What Is a Configurable Effect?](../../whatis/graphics/WhatIs_ConfigurableEffect.md) + +### Reference + +- [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) +- [GamePadState](xref:Microsoft.Xna.Framework.Input.GamePadState) +- [KeyboardState](xref:Microsoft.Xna.Framework.Input.KeyboardState) diff --git a/articles/getting_to_know/howto/graphics/HowTo_RotateMoveCamera.md b/articles/getting_to_know/howto/graphics/HowTo_RotateMoveCamera.md new file mode 100644 index 0000000..a8483ff --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_RotateMoveCamera.md @@ -0,0 +1,104 @@ +--- +title: How to rotate and move the Camera +description: Demonstrates how to rotate and move a camera in a 3D environment. You can rotate the camera about its y-axis, and move it forward and backward. You control the camera's position and orientation by using the directional keys on your keyboard or by using the D-pad of your gamepad. +requireMSLicense: true +--- + +## Overview + +This sample is based on several assumptions. + +* The camera will move frequently, so the camera view [Matrix](xref:Microsoft.Xna.Framework.Matrix) is created and set every time [Game.Update](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Update_Microsoft_Xna_Framework_GameTime_) is called. +* The projection [Matrix](xref:Microsoft.Xna.Framework.Matrix) may also change frequently for effects such as zooming. +* You have added a model to the project, as shown in [How To Render a Model](HowTo_RenderModel.md) + +For the sake of simplicity, the example limits the camera object to rotation about the y axis (vertical spin) and movement along the z axis (forward and backward). The following steps show you how to render the sample scene. + +### To render the sample scene + +1. Determine the location and orientation of the camera. + + ```csharp + static Vector3 avatarPosition = new Vector3(0, 0, -50); + static Vector3 cameraPosition = avatarPosition; + ``` + +2. Determine the reference [Vector3](xref:Microsoft.Xna.Framework.Vector3) to which the rotation of the camera is relative. + + The direction should not change during the game, and usually it will be (0, 0, 1) or (0, 0, −1). + + ```csharp + // Set the direction the camera points without rotation. + Vector3 cameraReference = new Vector3(0, 0, 1); + ``` + +3. Create a rotation [Matrix](xref:Microsoft.Xna.Framework.Matrix) for the amount of rotation for the camera. + + Because the camera is limited to one axis of rotation, this matrix represents the rotation of the camera around its own y-axis. Use **CreateRotationY** to create a rotation [Matrix](xref:Microsoft.Xna.Framework.Matrix) representing the rotation around the y-axis. + + ```csharp + Matrix rotationMatrix = Matrix.CreateRotationY(avatarYaw); + ``` + +4. Use the [Vector3](xref:Microsoft.Xna.Framework.Vector3) **Transform** and the rotation [Matrix](xref:Microsoft.Xna.Framework.Matrix) to transform the reference [vector](xref:Microsoft.Xna.Framework.Vector3). + + This represents the direction the camera is pointing in transformed (or view) space. + + ```csharp + // Create a vector pointing the direction the camera is facing. + Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix); + ``` + +5. Add the camera's current position to the transformed direction [vector](xref:Microsoft.Xna.Framework.Vector3). + + The result is the position to which the camera is pointing. + + ```csharp + // Calculate the position the camera is looking at. + Vector3 cameraLookat = cameraPosition + transformedReference; + ``` + +6. Create a new view [Matrix](xref:Microsoft.Xna.Framework.Matrix) using **CreateLookAt**. + +7. Use [Matrix.CreateLookAt](xref:Microsoft.Xna.Framework.Matrix) to pass the camera's current position and the transformed direction vector. + + The third parameter of **CreateLookAt** is the up direction of the camera. Typically, it is [Vector3](xref:Microsoft.Xna.Framework.Vector3) **Up** (0, 1, 0). This matrix [Matrix](xref:Microsoft.Xna.Framework.Matrix) controls how world coordinates are transformed to camera coordinates. + + ```csharp + // Set up the view matrix and projection matrix. + view = Matrix.CreateLookAt(cameraPosition, cameraLookat, new Vector3(0.0f, 1.0f, 0.0f)); + ``` + +8. Use **CreatePerspectiveFieldOfView** to create a new projection [Matrix](xref:Microsoft.Xna.Framework.Matrix). + + This [Matrix](xref:Microsoft.Xna.Framework.Matrix) controls how camera coordinate values are transformed to screen coordinates. + + The first parameter is the field of view of the projection [Matrix](xref:Microsoft.Xna.Framework.Matrix) expressed in radians. A typical field of view of 45 degrees would be expressed as π/4 radians. The second parameter is the aspect ratio of the projection [Matrix](xref:Microsoft.Xna.Framework.Matrix); it corrects for the difference in width and height of a viewspace. The third and fourth parameters specify the near and far distances at which the objects will be visible. + + ```csharp + // Set distance from the camera of the near and far clipping planes. + static float nearClip = 1.0f; + static float farClip = 2000.0f; + ``` + +9. Loop through each 3D model to be rendered using the projection matrix and view matrix created above. + + An identity matrix simplifies the code for the world matrix. + + ```csharp + void DrawModel(Model model, Matrix world, Texture2D texture) + { + foreach (ModelMesh mesh in model.Meshes) + { + foreach (BasicEffect effect in mesh.Effects) + { + effect.Projection = proj; + effect.View = view; + effect.World = world; + effect.Texture = texture; + effect.TextureEnabled = true; + } + mesh.Draw(); + } + } + ``` diff --git a/articles/getting_to_know/howto/graphics/HowTo_Select_an_Object_with_a_Mouse.md b/articles/getting_to_know/howto/graphics/HowTo_Select_an_Object_with_a_Mouse.md new file mode 100644 index 0000000..c3a6fcd --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Select_an_Object_with_a_Mouse.md @@ -0,0 +1,107 @@ +--- +title: Selecting an Object with a Mouse +description: Demonstrates how to check whether the mouse is positioned over a 3D object by creating a ray starting at the camera's near clipping plane and ending at its far clipping plane. +requireMSLicense: true +--- + +## Overview + +A common requirement in game development is to select 3D objects in a scene. This example walks through the most common method for achieving this. + +> [!NOTE] +> This example applies only to Desktop or mobile development. The [Mouse](xref:Microsoft.Xna.Framework.Input.Mouse) and [MouseState](xref:Microsoft.Xna.Framework.Input.MouseState) objects are not supported on consoles. +> +> On consoles however the same pattern applies, you simply need to use either a fixed point (where the camera is looking, or screen center) or a cursor controlled by a stick to get the position. + +## Detecting Whether a User Clicked a 3D Object + +1. Get the current state of the mouse by using [GetState](xref:Microsoft.Xna.Framework.Input.Mouse). + + ``` csharp + MouseState mouseState = Mouse.GetState(); + ``` + +2. Get the current screen coordinates of the mouse from [X](xref:Microsoft.Xna.Framework.Input.Mouse) and [Y](xref:Microsoft.Xna.Framework.Input.Mouse). + + ``` csharp + int mouseX = mouseState.X; + int mouseY = mouseState.Y; + ``` + + > [!NOTE] + > Replace mouse position with a virtual cursor or the screen centre for consoles. + +3. Using [Viewport.Unproject](xref:Microsoft.Xna.Framework.Graphics.Viewport#Microsoft_Xna_Framework_Graphics_Viewport_Unproject_Microsoft_Xna_Framework_Vector3_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_), determine points in world space on the near and far clipping planes. For the point on the near plane, pass a source vector with x and y set to the mouse position, and z set to 0. + +4. For the point on the far plane, pass a source vector with x and y set to the position, and z set to 1. + +5. Create a translation matrix for a point that is the origin, (0,0,0). + +6. For both points, pass [Viewport.Unproject](xref:Microsoft.Xna.Framework.Graphics.Viewport#Microsoft_Xna_Framework_Graphics_Viewport_Unproject_Microsoft_Xna_Framework_Vector3_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_) the current projection matrix, the view matrix. + + ``` csharp + // The closest point at which an object can interact. + Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f); + // The furthest point at which an object can interact. + Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f); + + Matrix world = Matrix.CreateTranslation(0, 0, 0); + + // Assuming you have the current Projection and View Matrices available. + Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearsource, + proj, view, world); + + Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farsource, + proj, view, world); + ``` + +7. Create a [Ray](xref:Microsoft.Xna.Framework.Ray) whose origin is at the near point and whose direction points to the far point. + + ``` csharp + // Create a ray from the near clip plane to the far clip plane. + Vector3 direction = farPoint - nearPoint; + direction.Normalize(); + Ray pickRay = new Ray(nearPoint, direction); + ``` + +8. Loop through each object in the scene using the [Intersects](xref:Microsoft.Xna.Framework.Ray) method to check whether the [Ray](xref:Microsoft.Xna.Framework.Ray) intersects each object. If it is hit, store the object and the distance at which it was intersected. + + ```csharp + // Assuming you have an array containing a list of all "hittable" objects in your game + foreach (var obj in objects) + { + float? distance = ray.Intersects(obj.BoundingSphere); + if (distance.HasValue) + { + // A cachable list of all object "HIT" this frame. + intersectedObjects.Add(new Tuple(obj, distance.Value)); + } + } + ``` + +9. Sort the items that have been hit in order of which is closest. + + ```csharp + // Sort the intersected objects by distance + intersectedObjects.Sort((a, b) => a.Item2.CompareTo(b.Item2)); + ``` + +10. When you completely loop through the objects, the last object stored will be the closest object underneath the area the user clicked. + +## See Also + +- [Rotating and Moving the Camera](HowTo_RotateMoveCamera.md) + +### Concepts + +- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) + +### Reference + +- [Ray](xref:Microsoft.Xna.Framework.Ray) +- [Ray.Intersects](xref:Microsoft.Xna.Framework.Ray#Microsoft_Xna_Framework_Ray_Intersects_Microsoft_Xna_Framework_BoundingBox_) +- [Ray.Intersects](xref:Microsoft.Xna.Framework.Ray#Microsoft_Xna_Framework_Ray_Intersects_Microsoft_Xna_Framework_BoundingSphere_) +- - [Ray.Intersects](xref:Microsoft.Xna.Framework.Ray#Microsoft_Xna_Framework_Ray_Intersects_Microsoft_Xna_Framework_Plane_) +- [BoundingBox](xref:Microsoft.Xna.Framework.BoundingBox) +- [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere) +- [Plane](xref:Microsoft.Xna.Framework.Plane) diff --git a/articles/getting_to_know/howto/graphics/HowTo_Test_for_Collisions.md b/articles/getting_to_know/howto/graphics/HowTo_Test_for_Collisions.md new file mode 100644 index 0000000..e075ccf --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_Test_for_Collisions.md @@ -0,0 +1,85 @@ +--- +title: Testing for Collisions +description: Demonstrates how to use the BoundingSphere class to check whether two models are colliding. +requireMSLicense: true +--- + +## Overview + +Collision detection is a crucial part of almost any game where the game needs to know whether or not two objects are touching. Normally, a simple distance ([Vector3.Distance]()) check is sufficient, but when you need to know where they are touching or require more accurate information, that is when collision detection becomes critical. + +## Detecting Whether Two Models Collide + +1. Track the position of a model as it moves about the game world. + + ``` csharp + struct WorldObject + { + public Vector3 position; + public Vector3 velocity; + public Model model; + public Texture2D texture2D; + public Vector3 lastPosition; + public void MoveForward() + { + lastPosition = position; + position += velocity; + } + public void Backup() + { + position -= velocity; + } + public void ReverseVelocity() + { + velocity.X = -velocity.X; + } + } + ``` + +2. Make a nested loop with the first model's meshes as the outer loop and the second model's meshes as the inner loop. + +3. Inside the loop, follow these steps. + + 1. Get the bounding sphere for the current mesh of the first model and the current mesh of the second model. + + 2. Offset the bounding spheres by the current positions of the models. + + 3. Call the [BoundingSphere.Intersects](xref:Microsoft.Xna.Framework.BoundingSphere) method to check the pairs of bounding spheres for collision. + + If the method returns **true**, the objects are colliding. + + 4. If the models are colliding, break out of the loop. + + ``` csharp + static void CheckForCollisions(ref WorldObject c1, ref WorldObject c2) + { + for (int i = 0; i < c1.model.Meshes.Count; i++) + { + // Check whether the bounding boxes of the two cubes intersect. + BoundingSphere c1BoundingSphere = c1.model.Meshes[i].BoundingSphere; + c1BoundingSphere.Center += c1.position; + + for (int j = 0; j < c2.model.Meshes.Count; j++) + { + BoundingSphere c2BoundingSphere = c2.model.Meshes[j].BoundingSphere; + c2BoundingSphere.Center += c2.position; + + if (c1BoundingSphere.Intersects(c2BoundingSphere)) + { + c2.ReverseVelocity(); + c1.Backup(); + c1.ReverseVelocity(); + return; + } + } + } + } + ``` + +## See Also + +- [Rotating and Moving the Camera](HowTo_RotateMoveCamera.md) + +### Concepts + +- [Bounding Volumes and Collisions](../HowTo_CollisionDetectionOverview.md) diff --git a/articles/getting_to_know/howto/graphics/HowTo_TransformPoint.md b/articles/getting_to_know/howto/graphics/HowTo_TransformPoint.md new file mode 100644 index 0000000..431ca34 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_TransformPoint.md @@ -0,0 +1,53 @@ +--- +title: How to transform a Point +description: This example demonstrates how to use the Vector3 and Matrix classes to transform a point. A matrix transform can include scaling, rotating, and translating information. +requireMSLicense: true +--- + +## Overview + +Transformation matrices are the cornerstone of 3D rendering and how we manipulate content to be drawn in a 3D environment. + +> [!NOTE] +> For a great primer on Transformation matrices, check out: +> +> [Transformation Matrix Overview - Geeks for Geeks](https://www.geeksforgeeks.org/transformation-matrix/) + +## Transforming a Point with a Matrix + +In MonoGame, matrices are transformed using the [Vector3.Transform](xref:Microsoft.Xna.Framework.Vector3#Microsoft_Xna_Framework_Vector3_Transform_Microsoft_Xna_Framework_Vector3_Microsoft_Xna_Framework_Matrix_) function with an applied matrix. + +1. Create a [Matrix](xref:Microsoft.Xna.Framework.Matrix) by using **CreateRotationY** or one of the other **Create** methods. + + Create Rotation Y will create a matrix that is rotated a number of radians around its center. + +2. Pass the point and the [Matrix](xref:Microsoft.Xna.Framework.Matrix) to the [Vector3.Transform](xref:Microsoft.Xna.Framework.Vector3#Microsoft_Xna_Framework_Vector3_Transform_Microsoft_Xna_Framework_Vector3_Microsoft_Xna_Framework_Matrix_) method. + +The following code example is a static function that accept a [Vector3](xref:Microsoft.Xna.Framework.Vector3) and translate its position (or rotate it) by the amount of radians (NOT degrees) provided. + +```csharp +static Vector3 RotatePointOnYAxis(Vector3 point, float angle) +{ + // Create a rotation matrix that represents a rotation of angle radians. + Matrix rotationMatrix = Matrix.CreateRotationY(angle); + + // Apply the rotation matrix to the point. + Vector3 rotatedPoint = Vector3.Transform(point, rotationMatrix); + + return rotatedPoint; +} +``` + +## See Also + +* [Drawing 3D Primitives using Lists or Strips](HowTo_Draw_3D_Primitives.md) + +### Matrix Creation Methods + +[Matrix](xref:Microsoft.Xna.Framework.Matrix) + +* CreateRotationX +* CreateRotationY +* CreateRotationZ +* CreateScale +* CreateTranslation diff --git a/articles/getting_to_know/howto/graphics/HowTo_UseACustomVertex.md b/articles/getting_to_know/howto/graphics/HowTo_UseACustomVertex.md new file mode 100644 index 0000000..a131990 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_UseACustomVertex.md @@ -0,0 +1,231 @@ +--- +title: How to create a Custom Vertex Declaration +description: Demonstrates how to create a custom vertex declaration and use it to render a 3D object. +requireMSLicense: true +--- + +## Overview + +MonoGame includes a few predefined classes for common vertex buffer declarations such as [VertexPositionColor](xref:Microsoft.Xna.Framework.Graphics.VertexPositionColor) and [VertexPositionColorTexture](xref:Microsoft.Xna.Framework.Graphics.VertexPositionColorTexture). If you need to create a vertex buffer declaration that includes additional user-defined types, create a custom vertex declaration. + +![Custom Vertex Example](images/graphics_custom_vertex.png) + +A custom vertex declaration is a class that implements fully customizable per-vertex data. Furthermore, if you derive the class from [IVertexType](xref:Microsoft.Xna.Framework.Graphics.IVertexType), you will not need to create a vertex declaration when creating your vertex buffer or drawing the geometry. + +## Requirements + +The following texture will be used to render to the screen. + +![MonoGame Logo](images/logo.png) + +Save it to your content project and name it "**logo**" (this name will used to reference it in the project). Make sure to [add it to your content project](../content_pipeline/HowTo_GameContent_Add.md). + +## Starting from the [Basic Effect](HowTo_Create_a_BasicEffect.md) tutorial + +1. Follow the steps of [How to create a Basic Effect](HowTo_Create_a_BasicEffect.md). + + This gives us a starting project that is rendering a 3D scene with a [Basic Effect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect). + +## Create a custom vertex declaration + +1. Create a new class file called `CustomVertex1.cs` + +1. Add the required `using` statements to the top of the file. + + ```csharp + using Microsoft.Xna.Framework; + using Microsoft.Xna.Framework.Graphics; + ``` + +1. Declare a structure that derives from [IVertexType](xref:Microsoft.Xna.Framework.Graphics.IVertexType). + + ```csharp + public struct CustomVertex1 : IVertexType + ``` + +1. Add members to the struct that describe the per-vertex data. + + This example uses position as a [Vector3 Structure](xref:Microsoft.Xna.Framework.Vector3) type, a texture coordinate using a [Vector2 Structure](xref:Microsoft.Xna.Framework.Vector2) type, and a vertex declaration using the [VertexDeclaration](xref:Microsoft.Xna.Framework.Graphics.VertexDeclaration) type. + + ```csharp + private Vector3 vertexPosition; + private Vector2 vertexTextureCoordinate; + + public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration + ( + new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), + new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0) + ); + ``` + +1. Implement the constructor and public accessor methods. + + ```csharp + //The constructor for the custom vertex. This allows similar + //initialization of custom vertex arrays as compared to arrays of a + //standard vertex type, such as VertexPositionColor. + public CustomVertex1(Vector3 pos, Vector2 textureCoordinate) + { + vertexPosition = pos; + vertexTextureCoordinate = textureCoordinate; + } + + //Public methods for accessing the components of the custom vertex. + public Vector3 Position + { + get { return vertexPosition; } + set { vertexPosition = value; } + } + + public Vector2 TextureCoordinate + { + get { return vertexTextureCoordinate; } + set { vertexTextureCoordinate = value; } + } + ``` + +1. Implement a non-public method for accessing the vertex declaration. + + ```csharp + VertexDeclaration IVertexType.VertexDeclaration + { + get { return VertexDeclaration; } + } + ``` + +## Using the Custom Vertex Buffer + +Using the Custom Vertex buffer, we will render a cube that is textured with the logo texture. + +1. Declare some variables at the top of your Game class. + + ```csharp + private CustomVertex1[] cubeVertices; + private VertexBuffer vertexBuffer; + private Texture2D logoTexture; + ``` + + This gives us the necessary data in order to draw our cube. + +1. Create a new method called `SetupDrawingCube()` and we will start with initializing the vertex buffer, passing in the **typeof(CustomVertex1)** instead of a vertex declaration to describe the vertex buffer data. + + ```csharp + public void SetupDrawingCube() + { + vertexBuffer = new VertexBuffer( + GraphicsDevice, + typeof(CustomVertex1), + 36, + BufferUsage.None + ); + ``` + +1. Create the per-vertex data; this shows a portion of the code. + + [!code-csharp[](./files/cubevertexdata.cs)] + + > For a triangle list, you need three vertices for a triangle and two triangles to make the front face of a cube. + +1. Finally, set the data into the vertex buffer data by calling [VertexBuffer.SetData](xref:Microsoft.Xna.Framework.Graphics.VertexBuffer) and set the vertex buffer to the device by calling [GraphicsDevice.SetVertexBuffer](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice). + + ```csharp + vertexBuffer.SetData(cubeVertices); + + graphics.GraphicsDevice.SetVertexBuffer(vertexBuffer); + } + ``` + +1. In `LoadContent` we need to Load the texture we are going to draw, as well as call the new method we defined to setup the primitive Cube. + + ```csharp + logoTexture = Content.Load("logo"); + SetupDrawingCube(); + ``` + +1. At the moment the `BasicEffect` setup from the previous tutorial only draws Vertex Colors, so we need to change that to pass it the [texture](xref:Microsoft.Xna.Framework.Graphics.BasicEffect#Microsoft_Xna_Framework_Graphics_BasicEffect_Texture) we just loaded, as well as enabling [Texture drawing](xref:Microsoft.Xna.Framework.Graphics.BasicEffect#Microsoft_Xna_Framework_Graphics_BasicEffect_TextureEnabled) + + Replace: + + ```csharp + basicEffect.VertexColorEnabled = true; + ``` + + With the following + + ```csharp + // Enable Texture Drawing - VERY IMPORTANT!! + basicEffect.TextureEnabled = true; + + // Set the texture we loaded (does nothing without the above setting) + basicEffect.Texture = logoTexture; + ``` + +1. Finally, Draw the object by calling [GraphicsDevice.DrawPrimitives](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice). + + ```csharp + foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) + { + pass.Apply(); + + graphics.GraphicsDevice.DrawPrimitives( + PrimitiveType.TriangleList, + 0, // start vertex + 12 // number of primitives to draw, 2 vertexes per side of the cube + ); + } + ``` + +## Extra credit, make it spin + +At the moment all you can see is the front face of the cube, which is not very exciting. Though [Matrix Transforms](HowTo_TransformPoint.md) however, we make our cube spin. + +1. First define a variable to manage the current rotation. + + ```csharp + float rotation = 0f; + ``` + +1. Next, we will update this rotation each frame in the `Update` method. + + ```csharp + // Update rotation angle + float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds; + rotation += deltaTime; + ``` + +1. Then finally, in the `Draw` method, we need to calculate the rotation matrix and the translation matrix to rotate the cube by and then apply that to the basic effect drawing the cube. + + Add the following to the `Draw` call **BEFORE** the effect drawing loop. + + ```csharp + // Create rotation matrices + Matrix rotationMatrix = Matrix.CreateRotationX(rotation) * + Matrix.CreateRotationY(rotation) * + Matrix.CreateRotationZ(rotation); + // Apply rotation to the world matrix + Matrix worldMatrix = rotationMatrix * Matrix.CreateTranslation(new Vector3(0, 0, 0)); + // Update the world matrix in the effect + basicEffect.World = worldMatrix; + ``` + +> [!NOTE] +> This is a very basic example of applying rotation, just for reference. + +With the changes in place, your cube will look a little more snazzy and rotate in the world. + +![Spinning Cube](images/HowTo_CustomVertex_Final.gif) + +## See Also + +- [How to create a Basic Effect](HowTo_Create_a_BasicEffect.md) +- [How to transform a Point](HowTo_TransformPoint.md) + +### Concepts + +- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md) + +### Reference + +- [IVertexType](xref:Microsoft.Xna.Framework.Graphics.IVertexType) +- [VertexDeclaration](xref:Microsoft.Xna.Framework.Graphics.VertexDeclaration) +- [Matrix](xref:Microsoft.Xna.Framework.Matrix) diff --git a/articles/getting_to_know/howto/graphics/HowTo_UseViewportForSplitscreenGaming.md b/articles/getting_to_know/howto/graphics/HowTo_UseViewportForSplitscreenGaming.md new file mode 100644 index 0000000..8098ee2 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/HowTo_UseViewportForSplitscreenGaming.md @@ -0,0 +1,85 @@ +--- +title: How to display Multiple Screens with Viewports +description: Demonstrates how to use viewports to display different scenes simultaneously using two cameras. +requireMSLicense: true +--- + +## Overview + +![A Split screen Example](images/graphics_split_screen.png) + +## To create multiple screens + +1. In your [LoadContent](xref:Microsoft.Xna.Framework.Game) method, create two new [Viewport](xref:Microsoft.Xna.Framework.Graphics.Viewport) objects to define the two new "split" regions of the screen. + + > In this example, the screen is split in half vertically. + + ```csharp + Viewport defaultViewport; + Viewport leftViewport; + Viewport rightViewport; + Matrix projectionMatrix; + Matrix halfprojectionMatrix; + + protected override void LoadContent() + { + // Create a new SpriteBatch, which can be used to draw textures. + spriteBatch = new SpriteBatch(GraphicsDevice); + + defaultViewport = GraphicsDevice.Viewport; + leftViewport = defaultViewport; + rightViewport = defaultViewport; + leftViewport.Width = leftViewport.Width / 2; + rightViewport.Width = rightViewport.Width / 2; + rightViewport.X = leftViewport.Width; + ``` + +2. Create a projection matrix to fit each new viewport. + + In this case, because the screen is split in half, only one new projection matrix is necessary. It has the same settings as the 4:3 full screen projection matrix, except the aspect ratio is now 2:3. + + ```csharp + projectionMatrix = Matrix.CreatePerspectiveFieldOfView( + MathHelper.PiOver4, 4.0f / 3.0f, 1.0f, 10000f); + + halfprojectionMatrix = Matrix.CreatePerspectiveFieldOfView( + MathHelper.PiOver4, 2.0f / 3.0f, 1.0f, 10000f); + } + ``` + +3. In your Game [Game.Draw](xref:Microsoft.Xna.Framework.Game#Microsoft_Xna_Framework_Game_Draw_Microsoft_Xna_Framework_GameTime_) method, assign one of the viewports to draw as the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice)[Viewport](xref:Microsoft.Xna.Framework.Graphics.Viewport). + +4. Draw your scene as normal, using the camera (or view matrix) associated with this perspective along with the proper projection matrix. + + ```csharp + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Viewport = defaultViewport; + GraphicsDevice.Clear(Color.CornflowerBlue); + + GraphicsDevice.Viewport = leftViewport; + DrawScene(gameTime, Camera1.ViewMatrix, halfprojectionMatrix); + ``` + +5. After drawing the first scene, assign the other viewport to the [Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.Viewport) property. + +6. Draw your scene again with the associated camera or view matrix, and the proper projection matrix. + + ```csharp + GraphicsDevice.Viewport = rightViewport; + DrawScene(gameTime, Camera2.ViewMatrix, halfprojectionMatrix); + + base.Draw(gameTime); + } + ``` + +## See Also + +### Concepts + +- [What Is a Viewport?](../../whatis/graphics/WhatIs_Viewport.md) + +### Reference + +- [GraphicsDevice.Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) +- [Viewport Structure](xref:Microsoft.Xna.Framework.Graphics.Viewport) diff --git a/articles/getting_to_know/howto/graphics/files/cubevertexdata.cs b/articles/getting_to_know/howto/graphics/files/cubevertexdata.cs new file mode 100644 index 0000000..8c589c8 --- /dev/null +++ b/articles/getting_to_know/howto/graphics/files/cubevertexdata.cs @@ -0,0 +1,63 @@ + Vector3 LeftTopFront = new Vector3(-1.0f, 1.0f, 1.0f); + Vector3 LeftBottomFront = new Vector3(-1.0f, -1.0f, 1.0f); + Vector3 LeftTopBack = new Vector3(-1.0f, 1.0f, -1.0f); + Vector3 LeftBottomBack = new Vector3(-1.0f, -1.0f, -1.0f); + + Vector3 RightTopFront = new Vector3(1.0f, 1.0f, 1.0f); + Vector3 RightBottomFront = new Vector3(1.0f, -1.0f, 1.0f); + Vector3 RightTopBack = new Vector3(1.0f, 1.0f, -1.0f); + Vector3 RightBottomBack = new Vector3(1.0f, -1.0f, -1.0f); + + Vector2 textureLeftTop = new Vector2(0.0f, 0.0f); + Vector2 textureLeftBottom = new Vector2(0.0f, 1.0f); + Vector2 textureRightTop = new Vector2(1.0f, 0.0f); + Vector2 textureRightBottom = new Vector2(1.0f, 1.0f); + + // Front face. + cubeVertices = new CustomVertex1[36]; + cubeVertices[0] = new CustomVertex1(LeftTopFront, textureLeftTop); + cubeVertices[1] = new CustomVertex1(LeftBottomFront, textureLeftBottom); + cubeVertices[2] = new CustomVertex1(RightTopFront, textureRightTop); + cubeVertices[3] = new CustomVertex1(LeftBottomFront, textureLeftBottom); + cubeVertices[4] = new CustomVertex1(RightBottomFront, textureRightBottom); + cubeVertices[5] = new CustomVertex1(RightTopFront, textureRightTop); + + // Add the vertices for the BACK face. + cubeVertices[6] = new CustomVertex1(LeftTopBack, textureRightTop); + cubeVertices[7] = new CustomVertex1(RightTopBack, textureLeftTop); + cubeVertices[8] = new CustomVertex1(LeftBottomBack, textureRightBottom); + cubeVertices[9] = new CustomVertex1(LeftBottomBack, textureRightBottom); + cubeVertices[10] = new CustomVertex1(RightTopBack, textureLeftTop); + cubeVertices[11] = new CustomVertex1(RightBottomBack, textureLeftBottom); + + // Add the vertices for the TOP face. + cubeVertices[12] = new CustomVertex1(LeftTopFront, textureLeftBottom); + cubeVertices[13] = new CustomVertex1(RightTopBack, textureRightTop); + cubeVertices[14] = new CustomVertex1(LeftTopBack, textureLeftTop); + cubeVertices[15] = new CustomVertex1(LeftTopFront, textureLeftBottom); + cubeVertices[16] = new CustomVertex1(RightTopFront, textureRightBottom); + cubeVertices[17] = new CustomVertex1(RightTopBack, textureRightTop); + + // Add the vertices for the BOTTOM face. + cubeVertices[18] = new CustomVertex1(LeftBottomFront, textureLeftTop); + cubeVertices[19] = new CustomVertex1(LeftBottomBack, textureLeftBottom); + cubeVertices[20] = new CustomVertex1(RightBottomBack, textureRightBottom); + cubeVertices[21] = new CustomVertex1(LeftBottomFront, textureLeftTop); + cubeVertices[22] = new CustomVertex1(RightBottomBack, textureRightBottom); + cubeVertices[23] = new CustomVertex1(RightBottomFront, textureRightTop); + + // Add the vertices for the LEFT face. + cubeVertices[24] = new CustomVertex1(LeftTopFront, textureRightTop); + cubeVertices[25] = new CustomVertex1(LeftBottomBack, textureLeftBottom); + cubeVertices[26] = new CustomVertex1(LeftBottomFront, textureRightBottom); + cubeVertices[27] = new CustomVertex1(LeftTopBack, textureLeftTop); + cubeVertices[28] = new CustomVertex1(LeftBottomBack, textureLeftBottom); + cubeVertices[29] = new CustomVertex1(LeftTopFront, textureRightTop); + + // Add the vertices for the RIGHT face. + cubeVertices[30] = new CustomVertex1(RightTopFront, textureLeftTop); + cubeVertices[31] = new CustomVertex1(RightBottomFront, textureLeftBottom); + cubeVertices[32] = new CustomVertex1(RightBottomBack, textureRightBottom); + cubeVertices[33] = new CustomVertex1(RightTopBack, textureRightTop); + cubeVertices[34] = new CustomVertex1(RightTopFront, textureLeftTop); + cubeVertices[35] = new CustomVertex1(RightBottomBack, textureRightBottom); \ No newline at end of file diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_BasicEffect_Sample.png b/articles/getting_to_know/howto/graphics/images/HowTo_BasicEffect_Sample.png new file mode 100644 index 0000000..15b4b63 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_BasicEffect_Sample.png differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_Create_a_RenderTarget_Final.png b/articles/getting_to_know/howto/graphics/images/HowTo_Create_a_RenderTarget_Final.png new file mode 100644 index 0000000..7684b4c Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_Create_a_RenderTarget_Final.png differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_CustomVertex_Final.gif b/articles/getting_to_know/howto/graphics/images/HowTo_CustomVertex_Final.gif new file mode 100644 index 0000000..46f4544 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_CustomVertex_Final.gif differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_DrawTexturedQuad_Final.png b/articles/getting_to_know/howto/graphics/images/HowTo_DrawTexturedQuad_Final.png new file mode 100644 index 0000000..2c46a2d Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_DrawTexturedQuad_Final.png differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_Draw_3D_Primitives_Line_List.png b/articles/getting_to_know/howto/graphics/images/HowTo_Draw_3D_Primitives_Line_List.png new file mode 100644 index 0000000..34845bb Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_Draw_3D_Primitives_Line_List.png differ diff --git a/articles/getting_to_know/howto/graphics/images/HowTo_Draw_Text_Final.png b/articles/getting_to_know/howto/graphics/images/HowTo_Draw_Text_Final.png new file mode 100644 index 0000000..f3493e6 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/HowTo_Draw_Text_Final.png differ diff --git a/articles/getting_to_know/howto/graphics/images/graphics_aa.jpg b/articles/getting_to_know/howto/graphics/images/graphics_aa.jpg new file mode 100644 index 0000000..a29ea75 Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/graphics_aa.jpg differ diff --git a/articles/getting_to_know/howto/graphics/images/graphics_custom_vertex.png b/articles/getting_to_know/howto/graphics/images/graphics_custom_vertex.png new file mode 100644 index 0000000..fd2647f Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/graphics_custom_vertex.png differ diff --git a/articles/getting_to_know/howto/graphics/images/graphics_split_screen.png b/articles/getting_to_know/howto/graphics/images/graphics_split_screen.png new file mode 100644 index 0000000..d80315c Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/graphics_split_screen.png differ diff --git a/articles/getting_to_know/howto/graphics/images/grid.png b/articles/getting_to_know/howto/graphics/images/grid.png new file mode 100644 index 0000000..e41ac4a Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/grid.png differ diff --git a/articles/getting_to_know/howto/graphics/images/logo.png b/articles/getting_to_know/howto/graphics/images/logo.png new file mode 100644 index 0000000..9b2932d Binary files /dev/null and b/articles/getting_to_know/howto/graphics/images/logo.png differ diff --git a/articles/getting_to_know/howto/graphics/index.md b/articles/getting_to_know/howto/graphics/index.md index 98fa0ba..0e0c16e 100644 --- a/articles/getting_to_know/howto/graphics/index.md +++ b/articles/getting_to_know/howto/graphics/index.md @@ -49,6 +49,10 @@ This section walks through several core concepts related to sprite rendering, in Demonstrates how to draw a sprite repeatedly in the x and y directions in one Draw call. +- [How To Draw Text](HowTo_Draw_Text.md) + + Demonstrates how to import a SpriteFont into a project and to draw text using the DrawString method. + - [How To Animate A Sprite](HowTo_Animate_Sprite.md) Demonstrates how to animate a sprite from a texture using a custom class. @@ -57,16 +61,82 @@ This section walks through several core concepts related to sprite rendering, in Demonstrates how to draw a scrolling background sprite using the SpriteBatch class. -> More Coming soon - ### Cameras -> Coming soon +- [Rotating and Moving the Camera](HowTo_RotateMoveCamera.md) + + Demonstrates how to rotate and move a camera in a 3D environment. You can rotate the camera about its y-axis, and move it forward and backward. You control the camera's position and orientation by using the directional keys on your keyboard or by using the D-pad of your gamepad. + +- [How to position the Camera](HowTo_FitCameraToScene.md) + + Demonstrates how to position the camera so that all objects in a scene are within the view frustum while maintaining the camera's original orientation. + +- [How to create a Render Target](HowTo_Create_a_RenderTarget.md) + + Demonstrates how to create a render target using the RenderTarget2D class. + +- [How to create a Full-Screen Game](HowTo_FullScreen.md) + + Demonstrates how to start a game in full-screen mode. + +- [How to restrict Aspect Ratio on a Graphics Device](HowTo_AspectRatio.md) + + Demonstrates how to create a custom GraphicsDeviceManager that only selects graphics devices with widescreen aspect ratios in full-screen mode. + +- [How to display Multiple Screens with Viewports](HowTo_UseViewportForSplitscreenGaming.md) + + Demonstrates how to use viewports to display different scenes simultaneously using two cameras. ### 3D Rendering -> Coming soon +This section walks through several core concepts related 3D rendering and math practices with MonoGame. + +- [How to transform a Point](HowTo_TransformPoint.md) + + This example demonstrates how to use the Vector3 and Matrix classes to transform a point. A matrix transform can include scaling, rotating, and translating information. + +- [How to create a Basic Effect](HowTo_Create_a_BasicEffect.md) + + Demonstrates how to create and initialize an instance of the BasicEffect class and use it to draw simple geometry. + +- [Using a Basic Effect with Texturing](HowTo_Draw_Textured_Quad.md) + + Demonstrates how to create and draw a simple quad—two triangles that form a rectangle or square—using **DrawUserIndexedPrimitives**. + +- [How to create a State Object](HowTo_Create_a_StateObject.md) + + Demonstrates how to create a state object using any of the state object classes: BlendState, DepthStencilState, RasterizerState, or SamplerState. + +- [Drawing 3D Primitives using Lists or Strips](HowTo_Draw_3D_Primitives.md) + + Demonstrates how to draw 3D primitives using lines and triangles arranged as strips or lists. + +- [How to render a Model using a Basic Effect](HowTo_RenderModel.md) + + Demonstrates how to load and render a model using the MonoGame Content Pipeline. It is assumed that an existing Windows game project is loaded in MonoGame. + +- [How to enable Anti-aliasing](HowTo_Enable_Anti_Aliasing.md) + + Demonstrates how to enable anti-aliasing for your game. + +- [How to create a Custom Vertex Declaration](HowTo_UseACustomVertex.md) + + Demonstrates how to create a custom vertex declaration and use it to render a 3D object. + +- [How to Dynamically Update Vertex Data](HowTo_DynamicallyUpdateVertices.md) + + Geometry in a 3D game is defined by vertex data. Sometimes, a game needs to modify vertex data or even generate new vertex data dynamically (at run time). Here are some solutions for dynamically updating vertex data. ### 3D Collisions -> Coming soon +[Bounding Volumes and Collisions](../HowTo_CollisionDetectionOverview.md) + +Collision detection determines whether objects in a game world overlap each other. + +[Selecting an Object with a Mouse](HowTo_Select_an_Object_with_a_Mouse.md) + +Demonstrates how to check whether the mouse is positioned over a 3D object by creating a ray starting at the camera's near clipping plane and ending at its far clipping plane. + +[Testing for Collisions](HowTo_Test_for_Collisions.md) + +Demonstrates how to use the BoundingSphere class to check whether two models are colliding. diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_3DRendering.md b/articles/getting_to_know/whatis/graphics/WhatIs_3DRendering.md new file mode 100644 index 0000000..2fa1196 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_3DRendering.md @@ -0,0 +1,141 @@ +--- +title: What is 3D Rendering? +description: The basics of the 3D rendering pipeline for MonoGame! +requireMSLicense: true +--- + +The 3D graphics pipeline uses a `graphics device` (the current display device rendering to the screen) to load resources and render a 3D scene using an [Effect](xref:Microsoft.Xna.Framework.Graphics.Effect). + +In general, the 3D pipeline requires the following state information for initialization: + +* World, view, and projection matrices to transform 3D vertices into a 2D space. +* A vertex buffer which contains the geometry to render. +* An effect that sets the render state necessary for drawing the geometry. + +> [!NOTE] +> For a more detailed explanation of World, View and Projection matrices , check out this [GameFromScratch - beginning 3D](https://gamefromscratch.com/monogame-tutorial-beginning-3d-programming/) article. + +As you become comfortable with these ideas, you may want to learn more about the following: + +* Manipulating vertices +* Creating your own effects +* Applying textures +* Improving performance by using index buffers. + +The MonoGame Framework uses a shader-driven programmable pipeline and requires a graphics card capable of at least Shader Model 2.0. A class called [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) encapsulates most of these common operations. + +> ![IMPORTANT] +> Shader requirements depend on the platform being targeted, the majority of MonoGame titles these days require Shader Model 3.0 as a minimum. You can use [this guide](https://www.lifewire.com/determine-directx-version-and-shader-model-812997) as a reference. +> MonoGame automatically converts all shaders to their appropriate platform based on the "shader level" defined. + +## The Graphics Device + +When you create a game with MonoGame, the framework initializes a graphics device for you. + +The [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) initializes the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice). + +Before [Initialize](xref:Microsoft.Xna.Framework.Game.Initialize) is called, there are three ways to change the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) settings: + +1. Set the appropriate properties such as the [PreferredBackBufferHeight](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.PreferredBackBufferHeight) and [PreferredBackBufferWidth](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.PreferredBackBufferWidth) on the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) in your game's constructor. + + ```csharp + _graphics.PreferredBackBufferHeight = 768; + _graphics.PreferredBackBufferWidth = 1024; + _graphics.ApplyChanges(); + ``` + +1. Handle the `PreparingDeviceSettings` event on the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager), and change the [PreparingDeviceSettingsEventArgs.GraphicsDeviceInformation.PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters) member properties. + + ```csharp + _graphics.PreparingDeviceSettings += OnPreparingDeviceSettings; + private void OnPreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e) + { + e.GraphicsDeviceInformation.PresentationParameters.BackBufferWidth = 1024; + e.GraphicsDeviceInformation.PresentationParameters.BackBufferHeight = 768; + } + ``` + + > [!WARNING] + > Any changes made to the [PreparingDeviceSettingsEventArgs](xref:Microsoft.Xna.Framework.PreparingDeviceSettingsEventArgs) will override the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) preferred settings. + +1. Handle the `DeviceCreated` event on the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager), and change the [PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.PresentationParameters) of the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) directly. + + ```csharp + IGraphicsDeviceService graphicsDeviceService = (IGraphicsDeviceService) + Game.Services.GetService(typeof(IGraphicsDeviceService)); + + if (graphicsDeviceService != null) + { + graphicsDeviceService.DeviceCreated += OnDeviceCreated; + } + + private void OnDeviceCreated(object sender, EventArgs e) + { + // Handle updating Graphics Device Presentation Parameters + } + ``` + +When you call [Game.Initialize](xref:Microsoft.Xna.Framework.Game.Initialize) the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) creates and configures [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice). You can then safely access [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) settings such as the backbuffer, depth/stencil buffer, viewport, and render states in the [Initialize](xref:Microsoft.Xna.Framework.Game.Initialize) method. + +> [!IMPORTANT] +> After you call [Game.Initialize](xref:Microsoft.Xna.Framework.Game.Initialize), changes to the [PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.PresentationParameters) of the [GraphicsDevice](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice) will not take effect until you call [GraphicsDeviceManager.ApplyChanges](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.ApplyChanges). Other changes, such as render states, will take effect immediately. + +## Resources + +A graphics resource is a collection of data stored in memory that can be accessed by either the CPU or GPU. The types of resources that an application might use include: + +* [Render targets](./WhatIs_Render_Target.md) +* [Vertex buffers](xref:Microsoft.Xna.Framework.Graphics.VertexBuffer) +* [Index buffers](xref:Microsoft.Xna.Framework.Graphics.IndexBuffer) +* [Textures](xref:Microsoft.Xna.Framework.Graphics.Texture) + +> ![NOTE] +> FOr a more detailed understanding in the use of these terms, check out [Riemers 3D series](https://github.com/simondarksidej/XNAGameStudio/wiki/Riemers3DXNA1Terrainoverview) on the XNAGameStudio Archive. + +Based on the resource management mode that was used when a resource is created, it should be reloaded when the device is reset. For more information, see [Loading Resources](../../howto/content_pipeline/HowTo_LoadContentLibrary.md). + +### Vertex and Index Buffers + +A vertex buffer contains a list of 3D vertices to be streamed to the graphics device. Each vertex in a vertex buffer may contain data about not only the 3D coordinate of the vertex but also other information describing the vertex, such as the vertex normal, color, or texture coordinate. Which you should use will depend on your usage and the needs of the vertex information you are drawing with, [for example](https://stackoverflow.com/questions/4702150/difference-between-using-vertexpositionnormaltexture-and-vertexpositiontexture.) + +The MonoGame Framework contains several classes to describe common vertex declaration types, such as: + +* [VertexPositionColor](xref:Microsoft.Xna.Framework.Graphics.VertexPositionColor) + + Vertex Declaration containing Position and Color of a vertex. + +* [VertexPositionColorTexture](xref:Microsoft.Xna.Framework.Graphics.VertexPositionColorTexture) + + Vertex Declaration containing Position, Color and Texture of a vertex. + +* [VertexPositionNormalTexture](xref:Microsoft.Xna.Framework.Graphics.VertexPositionNormalTexture) + + Vertex Declaration containing Position, Normal and Texture of a vertex. + +* [VertexPositionTexture](xref:Microsoft.Xna.Framework.Graphics.VertexPositionTexture). + + Vertex Declaration containing Position and Texture of a vertex. + +> [!NOTE] +> Use the [VertexElement](xref:Microsoft.Xna.Framework.Graphics.VertexElement) class to compose custom vertex types. + +Vertex buffers can contain indexed or non-indexed vertex data. + +> [!NOTE] +> If a **Vertex Buffer** is not indexed, all of the vertices are placed in the vertex buffer in the order they are to be rendered. Because 3D line lists or triangle lists often reference the same vertices multiple times, this can result in a large amount of redundant data. +> +> **Index buffers** allow you to list each vertex only once in the vertex buffer. An index buffer is a list of indices into the vertex buffer, given in the order that you want the vertices to render. + +### Render a non-indexed vertex buffer + +To render a non-indexed vertex buffer, call the [GraphicsDevice.DrawPrimitives](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawPrimitives_Microsoft_Xna_Framework_Graphics_PrimitiveType_System_Int32_System_Int32_) or [GraphicsDevice.DrawUserPrimitives](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_) Methods. + +### Render an indexed vertex buffer + +To render an indexed buffer, call the [GraphicsDevice.DrawIndexedPrimitives](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawIndexedPrimitives_Microsoft_Xna_Framework_Graphics_PrimitiveType_System_Int32_System_Int32_System_Int32_) or [GraphicsDevice.DrawUserIndexedPrimitives](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_DrawUserIndexedPrimitives__1_Microsoft_Xna_Framework_Graphics_PrimitiveType___0___System_Int32_System_Int32_System_Int16___System_Int32_System_Int32_) Methods. + +### Textures + +A texture resource is a structured collection of texture data. The data in a texture resource is made up of one or more sub-resources that are organized into arrays and mipmap chains. Textures are filtered by a texture sampler as they are read. The type of texture influences how the texture is filtered. + +You can apply textures by using the [Texture](xref:Microsoft.Xna.Framework.Graphics.BasicEffect.Texture) property of the [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) class, or choose to write your own effect methods to apply textures. diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Antialiasing.md b/articles/getting_to_know/whatis/graphics/WhatIs_Antialiasing.md new file mode 100644 index 0000000..a30532d --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Antialiasing.md @@ -0,0 +1,24 @@ +--- +title: What is Antialiasing? +description: The definition of Antialsing for MonoGame! +requireMSLicense: true +--- + +Antialiasing is a technique for softening or blurring sharp edges so they appear less jagged when rendered. + +Antialiasing is accomplished by multi-sampling each pixel at multiple pixel locations and combining the samples to generate a final pixel color. Increasing the number of samples per pixel increases the amount of antialiasing which generates a smoother edge: + +* 4x multisampling requires four samples per pixel. +* 2x multisampling requires two sampler per pixel. +* And so on. + +Use the [MultiSampleCount](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters.MultiSampleCount) property of the [PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters) class to set the number of samples for the back buffer. + +Set the [PreferMultiSampling](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.PreferMultiSampling) property on the [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) class to **true** to enable multi-sampling for the back buffer. + +> [!IMPORTANT] +> This will be ignored if the hardware does not support multi-sampling. + +## See Also + +[Enabling Anti-aliasing (Multi-sampling)](../../howto/graphics/HowTo_Enable_Anti_Aliasing.md) diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_BackBuffer.md b/articles/getting_to_know/whatis/graphics/WhatIs_BackBuffer.md new file mode 100644 index 0000000..58f9d20 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_BackBuffer.md @@ -0,0 +1,23 @@ +--- +title: What Is a Back Buffer? +description: The definition of a Back Buffer for MonoGame! +requireMSLicense: true +--- + +A back buffer is a [render target](./WhatIs_Render_Target.md) whose contents will be sent to the device when [GraphicsDevice.Present](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.Present) is called. + +The graphics pipeline renders to a render target, the particular render target that the device presents to the display is called the back buffer. Use the [BackBufferWidth](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters.BackBufferWidth) and [BackBufferHeight](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters.BackBufferHeight) properties to get the back buffer dimensions. Render directly to the back buffer or to a render target by configuring the device using [GraphicsDevice.SetRenderTarget](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_SetRenderTarget_Microsoft_Xna_Framework_Graphics_RenderTarget2D_) and [GraphicsDevice.SetRenderTargets](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_SetRenderTargets_Microsoft_Xna_Framework_Graphics_RenderTargetBinding___). + +* For Windows, the back buffer is created to match the dimensions of the [ClientBounds](xref:Microsoft.Xna.Framework.GameWindow.ClientBounds) by default. +* For Consoles, the back buffer is created with the dimensions that have been specified by the user. When going into full-screen mode on Windows. +* On Mobile, it is recommended to set the BackBuffer dimensions to the expected resolution based on the desired orientation of the device (Portrait or Landscape). + +It is often desirable to set the back buffer dimensions to match the [DisplayMode](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.DisplayMode) dimensions so that the game ("display") resolution does not change when it goes into the full-screen mode. + +The back buffer created for consoles is not necessarily the same size as the final resolution on a television connected for display. Consoles automatically scale output to the television resolution selected by the user in the System. If the aspect ratio of the back buffer is different from the aspect ratio of the television display mode, the console will automatically add black bars (also called letter-boxing) if the user's display is not widescreen. + +In addition, if you request a back-buffer resolution that is not supported by the output device, the MonoGame framework automatically selects the highest resolution supported by the output device. For example, if you create a back-buffer with a resolution of 1920x1080 (for example, 1080p or 1080i) and display it on a device with 480i resolution, the back-buffer is resized to 480i automatically. + +## See Also + +[Viewport](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.Viewport) diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_BlendState.md b/articles/getting_to_know/whatis/graphics/WhatIs_BlendState.md new file mode 100644 index 0000000..0a689a1 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_BlendState.md @@ -0,0 +1,21 @@ +--- +title: What Is Blend State? +description: The definition for the Blend State for MonoGame! +requireMSLicense: true +--- + +The Blend state controls how color and alpha values are blended when combining rendered data with existing render target data. + +The blend state class, [BlendState](xref:Microsoft.Xna.Framework.Graphics.BlendState), contains state that controls how colors are blended. Each time you render, the pixel data you generate (call it source data) is stored in a render target. The render target might be empty or it might already contain data (call it destination data). Blending occurs each time you combine source and destination data. + +You have a lot of control over how you blend the source and the destination data. + +For example: + +* You can choose to overwrite the destination with the source data by setting [BlendState.Opaque](xref:Microsoft.Xna.Framework.Graphics.BlendState) +* Combine the data by adding them together using [BlendState.Additive](xref:Microsoft.Xna.Framework.Graphics.BlendState). + +You can blend only the color data or the alpha data, or both, by setting up the blending functions [ColorBlendFunction](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorBlendFunction) and [AlphaBlendFunction](xref:Microsoft.Xna.Framework.Graphics.BlendState.AlphaBlendFunction). You can even limit your blending operation to one or more colors (or channels) using [ColorWriteChannels](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorWriteChannels). + +> [!NOTE] +> For an example that creates and uses a state object, see [Creating a State Object](../../howto/graphics/HowTo_Create_a_StateObject.md). diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_ColorBlending.md b/articles/getting_to_know/whatis/graphics/WhatIs_ColorBlending.md new file mode 100644 index 0000000..d5c4a1c --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_ColorBlending.md @@ -0,0 +1,85 @@ +--- +title: What Is Color Blending? +description: The definition for Color Blending for MonoGame! +requireMSLicense: true +--- + +Color blending mixes two colors together to produce a third color. + +* The first color is called the `source color` which is the new color being added. +* The second color is called the `destination color` which is the color that already exists (in a render target, for example). + +Each color has a separate blend factor that determines how much of each color is combined into the final product. Once the source and destination colors have been multiplied by their blend factors, the results are combined according to the specified blend function. The normal blend function is simple addition. + +The blend formula looks like this: + +```csharp +(source * sourceBlendFactor) blendFunction (destination*destinationBlendFactor) +``` + +* The source blend factor is specified by the [ColorSourceBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorSourceBlend) property +* The destination blend factor is specified by the [ColorDestinationBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorDestinationBlend) property. +* The [ColorBlendFunction](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorBlendFunction) property specifies the blend function to use, normally [BlendFunction.Add](/api/Microsoft.Xna.Framework.Graphics.BlendFunction.html). + +In which case the formula reduces to this: + +```csharp +(source * sourceBlendFactor) + (destination * destinationBlendFactor) +``` + +> [!NOTE] +> When no blending is done, a source pixel overwrites a destination pixel. + +When blending, you can create a lot of special effects using the blending properties: + +* Blend type. +* Blend settings. + +## Alpha Blending + +```csharp +(_source_ × [Blend.SourceAlpha](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) \+ (_destination_ × [Blend.InvSourceAlpha](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) +``` + +## Additive Blending + +```csharp +(_source_ × [Blend.One](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) \+ (_destination_ × [Blend.One](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) +``` + +## Multiplicative Blending + +```csharp +(_source_ × [Blend.Zero](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) \+ (_destination_ × [Blend.SourceColor](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) +``` + +## 2X Multiplicative Blending + +```csharp +(_source_ × [Blend.DestinationColor](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) \+ (_destination_ × [Blend.SourceColor](/api/Microsoft.Xna.Framework.Graphics.Blend.html)) +``` + +![This picture illustrates four common blend modes](images/blends.jpg) + +**Figure 1.  This picture illustrates four common blend modes. From left to right: Alpha blending, Additive blending, Multiplicative blending, and 2X Multiplicative blending. The top image in each column is the source image and below, it's effect when added to the destination.** + +Alpha blending uses the alpha channel of the source color to create a transparency effect so that the destination color appears through the source color. + +For example: + +* If you clear your backbuffer to [Color.Gray](/api/Microsoft.Xna.Framework.Color.html), it will be colored (0.5,0.5,0.5,1). +* If you then take a white color with a partial alpha value (1,1,1,0.4), the result will be 60 percent of the destination color and 40 percent of the source: (0.5 x 0.6) + (1 x 0.4). + +The resulting color will be (0.7,0.7,0.7, 1). The alpha values are multiplied as well - (.6 x 1) + .4 gives us an alpha value of 1. + +> [!NOTE] +> When drawing a sprite using the [SpriteBatch](xref:Microsoft.Xna.Framework.Graphics.SpriteBatch) class, choose [BlendState.AlphaBlend](/api/Microsoft.Xna.Framework.Graphics.BlendState.html) to configure alpha blending. + +By default, the alpha channel is blended along with the **red**, **green**, and **blue** channels using the [ColorSourceBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorSourceBlend) and [ColorDestinationBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState.ColorDestinationBlend) properties. You can choose to customize the blending for just the alpha channel by using the [AlphaSourceBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState.AlphaSourceBlend) and [AlphaDestinationBlend](xref:Microsoft.Xna.Framework.Graphics.BlendState.AlphaDestinationBlend) properties. + +## See Also + +### Concepts + +[What Is a Sprite?](WhatIs_Sprite.md) +[3D Pipeline Basics](WhatIs_3DRendering.md) diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_ConfigurableEffect.md b/articles/getting_to_know/whatis/graphics/WhatIs_ConfigurableEffect.md new file mode 100644 index 0000000..aad067f --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_ConfigurableEffect.md @@ -0,0 +1,71 @@ +--- +title: What Is a Configurable Effect? +description: The definition for a Configurable Effect for MonoGame! +requireMSLicense: true +--- + +A configurable effect is an optimized rendering effect designed for use with MonoGame. A configurable effect is created using a built-in object with options for user configuration. + +An effect initializes the graphics pipeline for performing transforms, lighting, applying textures, and adding per-pixel visual effects such as a glow or a lens flare. Under the covers, an effect implements at least one shader for processing vertices and at least one shader for processing pixels. + +During rendering, the graphics pipeline transforms 3D geometry to a 2D surface, giving you the option of adding lighting, texturing and many other per-vertex or per-pixel visual effects. An effect initializes the pipeline to render 3D geometry using vertex and pixel shaders, although you can also render a 2D sprite with an effect. + +Although more advanced programmable effects are available on Windows and other platforms. There are several built-in configurable effects which have been designed to run efficiently on mobile GPU hardware, and which are appropriate to the Reach [profile](WhatIs_GraphicsProfile.md) used for mobile games. + +Use one of the following configurable effects to implement these rendering effects: + +* [Basic Lighting and Fog](#basic-lighting-and-fog) +* [Character Animation](#character-animation) +* [More Sophisticated Lighting with a Light Map](#more-sophisticated-lighting-with-a-light-map) +* [Billboards and Imposters](#billboards-and-imposters) +* [Lighting Highlights Using an Environment Map](#lighting-highlights-using-an-environment-map) + +## Basic Lighting and Fog + +Use the [BasicEffect](xref:Microsoft.Xna.Framework.Graphics.BasicEffect) configurable effect to implement general purpose functionality, including the following: + +* Transformations. +* Lighting with three directional lights +* Material colors using ambient, diffuse, and specular properties. +* A single texture. +* Fog. + +> [!NOTE] +> To improve speed, fog calculations are based on depth instead of distance from the camera. + +When you choose a basic effect, you can improve the performance of your game if you do not use any fog or if you only use one of the three available directional lights. + +For an example, see [Creating a Basic Effect](../../howto/graphics/HowTo_Create_a_BasicEffect.md). + +## Character Animation + +Use the [SkinnedEffect](xref:Microsoft.Xna.Framework.Graphics.SkinnedEffect) configurable effect to animate a character. This effect uses bones and weights to transform a mesh (an object is made up of several meshes). To use this effect, set up a set of bones for a model when you create content and then transform the bones during the render loop. You can also use this class for hardware instancing by setting **WeightsPerVertex** to one, and replicating the geometry data with an additional bone index channel. This is similar to the way the shader instancing technique works in the instancing sample. + +## More Sophisticated Lighting with a Light Map + +Use the [DualTextureEffect](xref:Microsoft.Xna.Framework.Graphics.DualTextureEffect) configurable effect with a pre-baked radiosity lightmap to add more sophisticated lighting to a scene. This effect uses two textures, the base texture with the texture detail and an overlay texture with the pre-baked lighting. + +The two textures are combined using a fixed modulate2X blend formula as shown here: + +```csharp + result.rgb = x.rgb * y.rgb * 2; + result.a = x.a * y.a; +``` + +## Billboards and Imposters + +Use the [AlphaTestEffect](xref:Microsoft.Xna.Framework.Graphics.AlphaTestEffect) configurable effect to use alpha data to test whether to draw a pixel. The effect uses a **CompareFunction** to compare the alpha value for a pixel against the **ReferenceAlpha** value to determine whether to draw the pixel. This functionality is used for drawing a billboard (a 2D sprite that faces the camera) and an imposter (a 2D sprite that is integrated into a larger scene). + +## Lighting Highlights Using an Environment Map + +Use the [EnvironmentMapEffect](xref:Microsoft.Xna.Framework.Graphics.EnvironmentMapEffect) configurable effect to generate fast, specular highlights that add shininess to an object. The effect uses two textures, a base texture with the texture detail and a cubemap whose six sides reflect the environment onto the object. Use **EnvironmentMapAmount** to control the amount of the environment map to add to the object. Also, use **FresnelFactor** to control how much the edge of an object reflects specular lighting. + +Pseudo code for the lighting calculations looks similar to this: + +```csharp + viewAngle = dot(eyeToVertexVector, vertexNormal); + fresnel = saturate(pow(1 – abs(viewAngle), FresnelFactor); + amount = fresnel * EnvironmentMapAmount; + result.rgb = lerp(diffuseTexture.rgb, cubeTexture.rgb, amount); + result.rgb += cubeTexture.a * EnvironmentMapSpecular +``` diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_DepthBuffer.md b/articles/getting_to_know/whatis/graphics/WhatIs_DepthBuffer.md new file mode 100644 index 0000000..23bb59f --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_DepthBuffer.md @@ -0,0 +1,17 @@ +--- +title: What Is a Depth Buffer? +description: The definition for a Depth Buffer for MonoGame! +requireMSLicense: true +--- + +A depth buffer contains per-pixel floating-point data for the z depth of each pixel rendered. A depth buffer may also contain stencil data which can be used to do more complex rendering such as simple shadows or outlines. + +When a pixel is rendered, color data as well as depth data can be stored. If a pixel is rendered a second time - such as when two objects overlap - depth testing determines which pixel is closer to the camera. The depth function determines what to do with the test result. For example, if [CompareFunction.LessEqual](/api/Microsoft.Xna.Framework.Graphics.CompareFunction.html) is the current depth function, if the current pixel depth is less than or equal to the previous pixel depth, the current pixel depth is written to the depth buffer. Values that fail the depth test are discarded. + +The depth of a pixel, which ranges between 0.0 and 1.0, is determined based on the view and projection matrices. A pixel that touches the near plane has depth 0, a pixel that touches the far plane has depth 1. As each object in the scene is rendered, normally the pixels that are closest to the camera are kept, as those objects block the view of the objects behind them. + +A depth buffer may also contain stencil bits - for this reason it's often called a _depth-stencil buffer_. The depth format describes the data format of the depth buffer. The depth buffer is always 32 bits, but those bits can be arranged in different ways, similar to how texture formats can vary. A common depth format is [DepthFormat.Depth24Stencil8](/api/Microsoft.Xna.Framework.Graphics.DepthFormat.html), where 24 bits are used for the depth data and 8 bits are used for the stencil data. [DepthFormat.Depth24Stencil8Single](/api/Microsoft.Xna.Framework.Graphics.DepthFormat.html) is a more unusual format where the 24 bits for the depth buffer are arranged as a floating point value. Use [DepthFormat.None](/api/Microsoft.Xna.Framework.Graphics.DepthFormat.html) if you don't want to create a depth buffer. + +Use [DepthStencilState.DepthBufferEnable](xref:Microsoft.Xna.Framework.Graphics.DepthStencilState.DepthBufferEnable) to enable or disable depth buffering. Use the [DepthStencilState.DepthBufferFunction](xref:Microsoft.Xna.Framework.Graphics.DepthStencilState.DepthBufferFunction) to change the comparison function used for the depth test. Clear the depth buffer by passing [ClearOptions.DepthBuffer](/api/Microsoft.Xna.Framework.Graphics.ClearOptions.html) to [GraphicsDevice.Clear](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_Clear_Microsoft_Xna_Framework_Color_). + +In MonoGame there is no **DepthStencilBuffer** type. The runtime automatically creates a depth buffer when a render target is created, and you specify the format for the depth buffer in a render target's constructor along with the surface format. This prevents a render target from being created without a matching depth buffer. diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_DepthStencilState.md b/articles/getting_to_know/whatis/graphics/WhatIs_DepthStencilState.md new file mode 100644 index 0000000..9609c9f --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_DepthStencilState.md @@ -0,0 +1,16 @@ +--- +title: What Is Depth Stencil State? +description: The definition for the Depth Stencil State for MonoGame! +requireMSLicense: true +--- + +A Depth stencil state controls how the depth buffer and the stencil buffer are used. + +The depth buffer stores floating-point depth or z data for each pixel while the stencil buffer stores integer data for each pixel. The depth-stencil state class, [DepthStencilState](xref:Microsoft.Xna.Framework.Graphics.DepthStencilState), contains state that controls how depth and stencil data impacts rendering. + +During rendering, the `z` position (or depth) of each pixel is stored in the depth buffer. When rendering pixels more than once -- such as when objects overlap -- depth data is compared between the current pixel and the previous pixel to determine which pixel is closer to the camera. When a pixel passes the depth test, the pixel color is written to a render target and the pixel depth is written to the depth buffer. For more information about a depth buffer, see [What Is a Depth Buffer?](WhatIs_DepthBuffer.md). + +A depth buffer may also contain stencil data, which is why a depth buffer is often called a depth-stencil buffer. Use a stencil function to compare a reference stencil value -- a global value you set -- to the per-pixel value in the stencil buffer to mask which pixels get saved and which are discarded. + +> [!NOTE] +> For more information about a stencil buffer, see [What Is a Stencil Buffer?](WhatIs_StencilBuffer.md) diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_GraphicsProfile.md b/articles/getting_to_know/whatis/graphics/WhatIs_GraphicsProfile.md new file mode 100644 index 0000000..b0758af --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_GraphicsProfile.md @@ -0,0 +1,84 @@ +--- +title: What Is a Profile? +description: The definition for a Graphics Profile for MonoGame! +requireMSLicense: true +--- + +A graphics profile is a feature set that is implemented in hardware. The Reach profile implements High Level Shader Language (HLSL) Shader Model 2.0 and the HiDef profile implements HLSL Shader Model 3.0 or above. + +> [!IMPORTANT] +> The information regarding `Graphics Profiles` is recorded here for information only, supporting the history of XNA. +> +> With current technology, the **HiDef profile** is more than sufficient for modern hardware and there should be no limits within the MonoGame architecture for using modern techiques for making the most out of todays technology. + +To simplify multi-platform development, MonoGame creates a [profile](xref:Microsoft.Xna.Framework.Graphics.GraphicsProfile). A profile is platform independent so you do not need to query for capability bits. The APIs for accessing the features implemented in hardware are consistent across platforms so that game code written for one platform will compile and run on another platform with little or no changes. A game will not run if a hardware device does not meet the profile requirements. + +You can set the profile at design time by using the MonoGame property page in Microsoft Visual Studio or you can set a profile at runtime by using the [GraphicsProfile](xref:Microsoft.Xna.Framework.GraphicsDeviceManager.GraphicsProfile) property. For more information. + +> [!NOTE] +> See [Selecting Reach vs. HiDef](http://web.archive.org/web/20120102231201/http://blogs.msdn.com/b/shawnhar/archive/2010/07/19/selecting-reach-vs-hidef.aspx). + +There are two profiles, HiDef and Reach: the former for fully featured, high-powered hardware, and the latter for less featured, available-everywhere hardware. Reach is designed to broadly cover all platforms and has a limited set of graphic features and capabilities implemented in hardware. This profile is designed to support the widest variety of devices, more specifically Windows-based computers, mobiles and consoles. Reach dramatically speeds up writing multi-platform games because you can design and debug game code on one platform knowing that it will run on other platforms. Performance is dependent on the hardware available for each platform. + +The HiDef profile is designed for the highest performance and largest available set of graphic features. Use the HiDef profile to target hardware with more enhanced graphic capabilities such as an consoles and Windows-based computers with at least a DirectX 10 GPU. More specifically, the HiDef profile requires a GPU with console-level capabilities such as multiple render targets (MRT), floating-point surface formats, and per-vertex texture fetching. These are optional capabilities in DirectX 9 hardware, but all are required to support HiDef. Since DirectX 9 graphic cards are not required to support these features, it is easier to say that the HiDef profile requires at least a DirectX 10-capable GPU. A HiDef game will run on a DirectX 9 card if it implements the named DirectX 10 features. + +> [IMPORTANT] +> If you try to run a HiDef game on a device such as a mobile device that does not support HiDef, an exception is thrown at runtime. Additionally, if you try to access HiDef features from a game built for a Reach profile, the runtime throws an exception. To find out which profile your target hardware supports, call [GraphicsAdapter.IsProfileSupported Method](/api/Microsoft.Xna.Framework.Graphics.GraphicsAdapter.html#Microsoft_Xna_Framework_Graphics_GraphicsAdapter_IsProfileSupported_Microsoft_Xna_Framework_Graphics_GraphicsProfile_). + +## Reach vs. HiDef Comparison + +Differences between the Reach and HiDef profiles are presented next. For more detail, see the sections following the table. + +|Profiles|Reach|HiDef| +|-|-|-| +|Platforms|Mobile, Consoles, and any computer running Windows with a DirectX 9 GPU that supports at least Shader Model 2.0.|Consoles, and any Windows-based PC with at least a DirectX 10 (or equivalent) GPU. See the paragraph above for more detail.| +|Shader Model|2.0 |3.0| +|Maximum texture size|2,048|4,096| +|Maximum cube map size|512|4,096| +|Maximum volume texture size|Volume textures are not supported.|256| +|Nonpower of two textures|Yes with limitations: no wrap addressing mode, no mipmaps, no DXT compression on nonpower of two textures.|Yes| +|Nonpower of two cube maps|No|Yes| +|Nonpower of two volume textures|Volume textures are not supported.|Yes| +|Maximum number of primitives per draw call|65,535|1,048,575| +|Maximum number of vertex streams|16|16| +|Maximum vertex stream stride|25|255| +|Index buffer formats|16 bit|16 and 32 bit| +|Vertex element formats|Color, Byte4, Single, Vector2, Vector3, Vector4, Short2, Short4, NormalizedShort2, NormalizedShort4|All of the Reach vertex element formats, as well as HalfVector2 and HalfVector4.| +|Texture formats|Color, Bgr565, Bgra5551, Bgra4444, NormalizedByte2, NormalizedByte4, Dxt1, Dxt3, Dxt5|All of the Reach texture formats, as well as Alpha8, Rg32, Rgba64, Rgba1010102, Single, Vector2, Vector4, HalfSingle, HalfVector2, HalfVector4. Floating point texture formats do not support filtering.| +|Vertex texture formats|Vertex texturing is not supported.|Single, Vector2, Vector4, HalfSingle, HalfVector2, HalfVector4| +|Render target formats|Call **QueryRenderTargetFormat** to find out what is supported.|Call **QueryRenderTargetFormat** to find out what is supported.| +|Multiple render targets|No|Up to four. All must have the same bit depth. Alpha blending and independent write masks per render target are supported.| +|Occlusion queries|No|Yes| +|Separate alpha blend|No|Yes|S + +## Shader Model + +The Reach profile supports HLSL Shader Model 2.0 and the configurable effects for all platforms. Some mobile platforms do not support custom shaders. + +The HiDef profile supports HLSL Shader Model 3.0 and above. Consoles and desktop also support custom shader extensions such as vertex fetching (vfetch). + +## Textures + +Texture size limitations are listed in the table comparing the two profiles. These numbers are the maximum width or height of a texture that can be consumed by the profile. HiDef supports larger textures and volume textures. + +HiDef supports the following features without limitations; Reach supports the following features only for power-of-two textures: + +* The **wrap** texture addressing mode +* Mipmaps +* DXT compression + +## Formats + +There are a wide variety of render target formats. Call [GraphicsAdapter.QueryRenderTargetFormat Method](/api/Microsoft.Xna.Framework.Graphics.GraphicsAdapter.html#Microsoft_Xna_Framework_Graphics_GraphicsAdapter_QueryRenderTargetFormat_Microsoft_Xna_Framework_Graphics_GraphicsProfile_Microsoft_Xna_Framework_Graphics_SurfaceFormat_Microsoft_Xna_Framework_Graphics_DepthFormat_System_Int32_Microsoft_Xna_Framework_Graphics_SurfaceFormat__Microsoft_Xna_Framework_Graphics_DepthFormat__System_Int32__) to find out what is supported for your hardware. + +The runtime also has a built-in fallback mechanism if the format you request is unavailable. The format parameters used when creating render targets and back buffers are now named "**preferredFormat**" instead of "format." The runtime will try to create a resource with the exact format passed in, and will fallback to the closest possible match (based on similar bit depth, number of channels, and so on) if that format is unavailable. For example, if you run a Reach game on a mobile device using a 16-bit render target format and then run the game on some consoles that do not support 16-bit render targets, the runtime will switch the render-target format to a [Color](xref:Microsoft.Xna.Framework.Color) format. + +## Conclusion + +XNA introduced the Reach profile for Consoles, Windows, and mobile, and the HiDef profile for Consoles and Windows devices. The HiDef profile includes a strict superset of the functionality in the Reach profile, which means that HiDef implements all Reach functionality and more. + +If you run a Reach game on a HiDef platform, the framework will enforce Reach rules. Use this to your advantage when you develop a multi-platform game. You can design and debug on the most powerful hardware with the knowledge that the game will compile and run on the other less powerful platforms when you are ready to test your game. The runtime will throw an exception if you try to set the profile to HiDef on hardware that does not support HiDef, or if you are running a Reach profile game that tries to access HiDef features. + +## Cited Works + +"Selecting Reach vs. HiDef." Shawn Hargreaves Blog. July 2010. [http://web.archive.org/web/20120102231201/http://blogs.msdn.com/b/shawnhar/archive/2010/07/19/selecting-reach-vs-hidef.aspx](http://web.archive.org/web/20120102231201/http://blogs.msdn.com/b/shawnhar/archive/2010/07/19/selecting-reach-vs-hidef.aspx) (Last accessed August 2, 2010) diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_ModelBone.md b/articles/getting_to_know/whatis/graphics/WhatIs_ModelBone.md new file mode 100644 index 0000000..18b609a --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_ModelBone.md @@ -0,0 +1,13 @@ +--- +title: What Is a Model Bone? +description: The definition for a Model Bone for MonoGame! +requireMSLicense: true +--- + +A model bone is a matrix that represents the position of a mesh as it relates to other meshes in a 3D model. + +![The structure of a ModelMesh](images/Model-ModelMesh.png) + +A complex computer-generated object, often called a model, is made up of many vertices and materials organized into a set of meshes. In the MonoGame Framework, a model is represented by the [Model](xref:Microsoft.Xna.Framework.Graphics.Model) class. A model contains one or more meshes, each of which is represented by a [ModelMesh](xref:Microsoft.Xna.Framework.Graphics.ModelMesh) class. Each mesh is associated with one bone represented by the [ModelBone](xref:Microsoft.Xna.Framework.Graphics.ModelBone) class. + +The bone structure is set up to be hierarchical to make controlling each mesh (and therefore the entire model) easier. At the top of the hierarchy, the model has a [Root](xref:Microsoft.Xna.Framework.Graphics.Model.Root) bone to specify the overall position and orientation of the model. Each [ModelMesh](xref:Microsoft.Xna.Framework.Graphics.ModelMesh) object contains a [ParentBone](xref:Microsoft.Xna.Framework.Graphics.ModelMesh.ParentBone) and one or more [ModelBone](xref:Microsoft.Xna.Framework.Graphics.ModelBone). You can transform the entire model using the parent bone as well as transform each individual mesh with its bone. To animate one or more bones, update the bone transforms during the render loop by calling [Model.CopyAbsoluteBoneTransformsTo Method](/api/Microsoft.Xna.Framework.Graphics.Model.html#Microsoft_Xna_Framework_Graphics_Model_CopyAbsoluteBoneTransformsTo_Microsoft_Xna_Framework_Matrix___), which iterates the individual bone transforms to make them relative to the parent bone. To draw an entire model, loop through a mesh drawing each sub mesh. diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Rasterizer.md b/articles/getting_to_know/whatis/graphics/WhatIs_Rasterizer.md new file mode 100644 index 0000000..3a07f8d --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Rasterizer.md @@ -0,0 +1,32 @@ +--- +title: What Is Rasterizer State? +description: The definition for a Rasterizer for MonoGame! +requireMSLicense: true +--- + +A [Rasterizer state](xref:Microsoft.Xna.Framework.Graphics.RasterizerState) determines how to render 3D data such as position, color, and texture onto a 2D surface. + +Rasterization takes a 3D scene containing polygons (which are represented by triangles and vertices) and renders the scene onto a 2D surface. This requires mapping or transforming the 3D vertices into 2D vertices using the world, view, and projection transforms to calculate the final vertex positions in the viewing frustum. To reduce the amount of geometry that needs to be rasterized, the rasterizer clips geometry so that only the parts of a polygon that are visible get processed. The resulting list of transformed vertices is then scan-converted to determine how to fill pixel positions between vertices. Scissor testing takes a list of user-supplied rectangles to further limit the areas you may want rasterized. + +Create a rasterizer state object using the [RasterizerState](xref:Microsoft.Xna.Framework.Graphics.RasterizerState) class. Set the rasterizer state to the graphics device using the [RasterizerState](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.RasterizerState) property. + +This is the default state for rasterization: + +* Render triangles with clockwise winding order. +* Fill primitives so they are solid. +* Turn off scissor testing. +* Enable multisampling. +* Avoid using either depth bias or sloped scaled depth bias. + +These are the corresponding API states: + +* Set [CullMode](xref:Microsoft.Xna.Framework.Graphics.RasterizerState.CullMode) to **CullMode.CullCounterClockwiseFace**. +* Set [FillMode](xref:Microsoft.Xna.Framework.Graphics.RasterizerState.FillMode) to **FillMode.Solid**. +* Set [ScissorTestEnable](xref:Microsoft.Xna.Framework.Graphics.RasterizerState.ScissorTestEnable) to **false**. +* Set [MultiSampleAntiAlias](xref:Microsoft.Xna.Framework.Graphics.RasterizerState.MultiSampleAntiAlias) to **true**. +* Set [DepthBias](xref:Microsoft.Xna.Framework.Graphics.RasterizerState.DepthBias) and [SlopeScaleDepthBias](xref:Microsoft.Xna.Framework.Graphics.RasterizerState.SlopeScaleDepthBias) to 0. + +Built-in state objects make it easy to create objects with the most common rasterizer state settings. **CullNone**, **CullClockwise**, and **CullCounterClockwise** are the most common settings. + +> [!NOTE] +> For an example of creating a state object, see [Creating a State Object](../../howto/graphics/HowTo_Create_a_StateObject.md). diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Render_Target.md b/articles/getting_to_know/whatis/graphics/WhatIs_Render_Target.md new file mode 100644 index 0000000..1e44756 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Render_Target.md @@ -0,0 +1,27 @@ +--- +title: What Is a Render Target? +description: The definition for a Render Target for MonoGame! +requireMSLicense: true +--- + +A [render target](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) is a memory buffer for rendering pixels. One common use for a render target is offscreen rendering. + +The graphics pipeline has a default render target called the **back buffer**, which is a portion of video memory that contains the next frame to be drawn. If your program does not create a render target, and you render to the screen, you are using the back buffer by default. Use the [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) class to create additional render targets. A common scenario is to render to one or more offscreen render targets and assemble them in the back buffer to produce the final frame. + +> [!NOTE] +> The [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) class derives from the [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) class because a render target contains a 2D texture. + +- To draw a render target like you would draw a texture, use the render target object directly. That is, pass a [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) object to any method that takes a [Texture2D](xref:Microsoft.Xna.Framework.Graphics.Texture2D) object. + +- To read render target data back from the CPU, call the [Texture2D.GetData Method](/api/Microsoft.Xna.Framework.Graphics.Texture2D.html#Microsoft_Xna_Framework_Graphics_Texture2D_GetData__1___0___). + +> [!NOTE] +> For more information about using a render target, see [Creating a Render Target](../../howto/graphics/HowTo_Create_a_RenderTarget.md). + +To use a render target, create a [RenderTarget2D](xref:Microsoft.Xna.Framework.Graphics.RenderTarget2D) object with the width, height, and other options you prefer. Call [GraphicsDevice.SetRenderTarget](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_SetRenderTarget_Microsoft_Xna_Framework_Graphics_RenderTarget2D_) to make your render target the current render target. Any subsequent **Draw** calls you make will draw into your render target rather than the back buffer. When you are finished rendering, call [GraphicsDevice.SetRenderTarget](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_SetRenderTarget_Microsoft_Xna_Framework_Graphics_RenderTarget2D_) and pass it null to set the device to render to the back buffer again. + +There are other considerations for choosing width and height when you create a render target. For example, you should choose the width and height of the back buffer to match the size of your game window (although Windows Phone scales the final result to match the user's screen). This prevents any resizing when the back buffer is copied to the screen. However, an offscreen render target does not need to have the same width and height as the back buffer. The final image can be rendered in several small render targets and then reassembled in a larger render target. + +A render target has a surface format, which describes how many bits are allocated to each pixel, and how they are divided between red, green, blue, and alpha. For example, [SurfaceFormat.Bgr565](https://monogame.net/api/Microsoft.Xna.Framework.Graphics.SurfaceFormat.html) allocates 16 bits per pixel; 5 bits for blue and red and 6 bits for green. + +A render target works in cooperation with a depth-stencil buffer. When creating a render target, the depth format for the depth-stencil buffer is specified as one of the parameters to the render target constructor. Anytime you set a new render target to the device, the matching depth buffer is also set to the device. diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Sampler.md b/articles/getting_to_know/whatis/graphics/WhatIs_Sampler.md new file mode 100644 index 0000000..4692ffe --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Sampler.md @@ -0,0 +1,36 @@ +--- +title: What Is Sampler State? +description: The definition for a Sampler State for MonoGame! +requireMSLicense: true +--- + +A [Sampler state](xref:Microsoft.Xna.Framework.Graphics.SamplerState) determines how texture data is sampled using texture addressing modes, filtering, and level of detail. + +A texture contains an array of texels, or texture pixels, sampling is done each time a texture pixel, or texel, is read from a texture. The position of each texel is denoted by (u,v), where: + +* _u_ is the width +* _v_ is the height + +These are mapped between 0 and 1 based on the texture width and height. The resulting texture coordinates are used to address a texel when sampling a texture. + +When texture coordinates are below 0 or above 1, the texture address mode defines how the texture coordinate addresses a texel location. For example, when using [TextureAddressMode.Clamp](https://monogame.net/api/Microsoft.Xna.Framework.Graphics.TextureAddressMode.html), any coordinate outside the 0-1 range is clamped to a maximum value of 1, and minimum value of 0 before sampling. + +If the texture is too large or too small for the polygon, the texture is filtered to fit the space. A magnification filter enlarges a texture, a minification filter reduces the texture to fit into a smaller area. Texture magnification repeats the sample texel for one or more addresses which yields a blurrier image. Texture minification is more complicated because it requires combining more than one texel value into a single value. This can cause aliasing or jagged edges depending on the texture data. The most popular approach for minification is to use a mipmap. A mipmap is a multi-level texture. The size of each level is a power-of-two smaller than the previous level down to a 1x1 texture. When minification is used, a game chooses the mipmap level closest to the size that is needed at render time. + +Use the [SamplerState](xref:Microsoft.Xna.Framework.Graphics.SamplerState) class to create a sampler state object. Set the sampler state to the graphics device using the [GraphicsDevice.SamplerStates Property](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.SamplerStates) property. + +This is the default state for sampling: + +* Uses linear filtering. +* Wraps texture addresses on boundaries. +* Sets the maximum anisotropy value to 4. +* Does not use mip maps or LOD bias. + +These are the corresponding API states: + +* Set [Filter](xref:Microsoft.Xna.Framework.Graphics.SamplerState.Filter) to **TextureFilter.Linear**. +* Set [AddressU](xref:Microsoft.Xna.Framework.Graphics.SamplerState.AddressU), [AddressV](xref:Microsoft.Xna.Framework.Graphics.SamplerState.AddressV), and [AddressW](xref:Microsoft.Xna.Framework.Graphics.SamplerState.AddressW) to **TextureAddressMode.Wrap**. +* Set [MaxAnisotropy](xref:Microsoft.Xna.Framework.Graphics.SamplerState.MaxAnisotropy) to 4. +* Set [MaxMipLevel](xref:Microsoft.Xna.Framework.Graphics.SamplerState.MaxMipLevel) and [MipMapLevelOfDetailBias](xref:Microsoft.Xna.Framework.Graphics.SamplerState.MipMapLevelOfDetailBias) to 0. + +Built-in state objects make it easy to create objects with the most common sampler state settings. The most common settings are **LinearClamp**, **LinearWrap**, **PointClamp**, **PointWrap**, **AnisotropicClamp**, and **AnisotropicWrap**. For an example of creating a state object, see [Creating a State Object](../../howto/graphics/HowTo_Create_a_StateObject.md). diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_StencilBuffer.md b/articles/getting_to_know/whatis/graphics/WhatIs_StencilBuffer.md new file mode 100644 index 0000000..dbb0cbd --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_StencilBuffer.md @@ -0,0 +1,20 @@ +--- +title: What Is a Stencil Buffer? +description: The definition for a Stencil Buffer for MonoGame! +requireMSLicense: true +--- + +A stencil buffer contains per-pixel integer data which is used to add more control over which pixels are rendered. A stencil buffer can also be used in combination with a depth buffer to do more complex rendering such as simple shadows or outlines. + +A stencil buffer operates similarly to a [depth buffer](WhatIs_DepthBuffer.md). So similarly, that stencil data is stored in a depth buffer. While depth data determines which pixel is closest to the camera, stencil data can be used as a more general purpose per-pixel mask for saving or discarding pixels. To create the mask, use a stencil function to compare a reference stencil value -- a global value -- to the value in the stencil buffer each time a pixel is rendered. + +For example, to remove an object from a scene: + +* Fill a stencil buffer with a cut out pattern (using zeros) for each pixel where the object is visible. This is done by setting the reference stencil value to 0, clearing the stencil buffer, and rendering the object. +* Then set the reference stencil value to 1, set the compare function to [CompareFunction.LessEqual](xref:Microsoft.Xna.Framework.Graphics.CompareFunction), and render again. + +The stencil data masks those pixels whose value is non zero but less than 1, resulting in drawing over (or removing) the object. + +A stencil buffer can be used in more sophisticated ways such as specifying [StencilOperations](xref:Microsoft.Xna.Framework.Graphics.StencilOperation) that go beyond replace or discard and increment or decrement the stencil buffer during a stencil test. You can also combine this with a [StencilMask](xref:Microsoft.Xna.Framework.Graphics.DepthStencilState.StencilMask) to mask the portion of the stencil buffer that is updated. + +To use a stencil buffer, the [DepthFormat](xref:Microsoft.Xna.Framework.Graphics.DepthFormat) of the depth buffer must reserve some bits for the stencil data; the [DepthFormat.Depth24Stencil8](/api/Microsoft.Xna.Framework.Graphics.DepthFormat.html) format uses 8 bits for a stencil buffer as an example. Combining stencil data with an 8 bit [DepthStencilState.StencilMask Property](xref:Microsoft.Xna.Framework.Graphics.DepthStencilState.StencilMask) provide up to eight different stencil buffers. diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_ViewFrustum.md b/articles/getting_to_know/whatis/graphics/WhatIs_ViewFrustum.md new file mode 100644 index 0000000..d1e9e12 --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_ViewFrustum.md @@ -0,0 +1,19 @@ +--- +title: What Is a View Frustum? +description: The definition for the View Frustum for MonoGame! +requireMSLicense: true +--- + +A view frustum is a 3D volume that defines how models are projected from camera space to projection space. Objects must be positioned within the 3D volume to be visible. + +The MonoGame Framework uses a projection matrix to calculate a vertex position in the view frustum. The matrix reverses the y-coordinate (so it is top down) to reflect a screen origin at the top-left corner. After the matrix is applied, the homogenous vertices (that is, the vertices contain (x,y,z,w) coordinates) are converted to non-homogeneous coordinates so they can be rasterized. + +The most common type of projection is called a perspective projection, which makes objects near the camera appear bigger than objects in the distance. For a perspective projection, the view frustum can be visualized as a clipped pyramid whose top and bottom are defined by the near and far clipping planes as shown in the figure. + +![A diagram visualisation of the View Frustrum](images/frustum.jpg) + +A view frustum is defined by a field of view (fov), and by the distances of the front and back clipping planes, which are specified in z-coordinates. Set up a perspective fov using the [CreatePerspectiveFieldOfView](/api/Microsoft.Xna.Framework.Matrix.html#Microsoft_Xna_Framework_Matrix_CreatePerspectiveFieldOfView_System_Single_System_Single_System_Single_System_Single_) method. + +## See Also + +[What Is a Viewport?](WhatIs_Viewport.md) diff --git a/articles/getting_to_know/whatis/graphics/WhatIs_Viewport.md b/articles/getting_to_know/whatis/graphics/WhatIs_Viewport.md new file mode 100644 index 0000000..d27983a --- /dev/null +++ b/articles/getting_to_know/whatis/graphics/WhatIs_Viewport.md @@ -0,0 +1,27 @@ +--- +title: What Is a Viewport? +description: The definition for the Viewport for MonoGame! +requireMSLicense: true +--- + +A [viewport](xref:Microsoft.Xna.Framework.Graphics.Viewport) is a 2D rectangle that defines the size of the rendering surface onto which a 3D scene is projected. + +A viewport is represented by the [Viewport](xref:Microsoft.Xna.Framework.Graphics.Viewport) class. The **Width** and **Height** properties of the rectangle are used by methods for a variety of calculations such as creating a projection matrix using [CreatePerspectiveFieldOfView](/api/Microsoft.Xna.Framework.Matrix.html#Microsoft_Xna_Framework_Matrix_CreatePerspectiveFieldOfView_System_Single_System_Single_System_Single_System_Single_). Viewport dimensions default to the dimensions of the back buffer, but they can be a different size. For example, to create a split screen game, you might render multiple viewports to a single render target. The viewport dimensions do not correspond to the display dimensions, which are determined by the [DisplayMode](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.DisplayMode) property, or to the game window, which is determined by the [ClientBounds](xref:Microsoft.Xna.Framework.GameWindow.ClientBounds) property. + +Use the [Clear](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_Clear_Microsoft_Xna_Framework_Color_) method to reset a render-target surface. Overloaded versions accept various parameters such as a set of rectangles that define more specific areas rather than the entire surface. Specify in the [ClearOptions](xref:Microsoft.Xna.Framework.Graphics.ClearOptions) enumeration which buffer or render target to reset. + +You can also use the [Clear](/api/Microsoft.Xna.Framework.Graphics.GraphicsDevice.html#Microsoft_Xna_Framework_Graphics_GraphicsDevice_Clear_Microsoft_Xna_Framework_Color_) method to clear stencil bits within a depth buffer. Set the options parameter to determine which render-target components are cleared. The color argument sets the color value of the render target after it has been cleared. The depth parameter clears the depth buffer to the specified depth: 0.0 is the closest distance, and 1.0 is the farthest. Finally, the stencil parameter resets the stencil bits to the specified value. Use integers ranging from 0 to 2n−1, where _n_ is the stencil buffer bit depth. + +## Desktop Area Versus Display Area + +The size of the desktop area in Windows is shown by the [DisplayMode](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.DisplayMode) **Width** and **Height** properties. The display area is different from the game window, which can be obtained from the [ClientBounds](xref:Microsoft.Xna.Framework.GameWindow.ClientBounds) dimensions. On Windows, set the display mode width and height to match the back buffer width and height. This prevents the need to resize the back buffer when switching between windowed and full screen mode. On Xbox 360, you need to display the text and menu items within the inner 80 percent of the display area. This prevents text or menus from getting cut off at the edge of a television screen. This inner area is called the title safe area. + +The game window size is shown by the [ClientBounds](xref:Microsoft.Xna.Framework.GameWindow.ClientBounds) **Width** and **Height** properties. The game window size matches the display size when a game is running in full-screen mode. The game window size may be smaller for a game running in windowed mode. Use **ClientBounds.X** and **ClientBounds.Y** for the upper-left coordinates of the game window relative to the display area. On Xbox 360, the [ClientBounds](xref:Microsoft.Xna.Framework.GameWindow.ClientBounds) **Width** and **Height** properties are always equal to the [DisplayMode](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.DisplayMode)**Width** and **Height**, and **ClientBounds.X** and **ClientBounds.Y** are always (0, 0). + +**Figure 1.  **DisplayMode** and **ClientBounds** areas on Windows and Xbox 360.** + +![DisplayMode and ClientBounds** areas on Windows and console](images/viewport.jpg) + +## See Also + +[What Is a Back Buffer?](WhatIs_BackBuffer.md) diff --git a/articles/getting_to_know/whatis/graphics/images/Model-ModelMesh.png b/articles/getting_to_know/whatis/graphics/images/Model-ModelMesh.png new file mode 100644 index 0000000..f996400 Binary files /dev/null and b/articles/getting_to_know/whatis/graphics/images/Model-ModelMesh.png differ diff --git a/articles/getting_to_know/whatis/graphics/images/blends.jpg b/articles/getting_to_know/whatis/graphics/images/blends.jpg new file mode 100644 index 0000000..46736ec Binary files /dev/null and b/articles/getting_to_know/whatis/graphics/images/blends.jpg differ diff --git a/articles/getting_to_know/whatis/graphics/images/frustum.jpg b/articles/getting_to_know/whatis/graphics/images/frustum.jpg new file mode 100644 index 0000000..a60b360 Binary files /dev/null and b/articles/getting_to_know/whatis/graphics/images/frustum.jpg differ diff --git a/articles/getting_to_know/whatis/graphics/images/viewport.jpg b/articles/getting_to_know/whatis/graphics/images/viewport.jpg new file mode 100644 index 0000000..bfd3e4f Binary files /dev/null and b/articles/getting_to_know/whatis/graphics/images/viewport.jpg differ diff --git a/articles/getting_to_know/whatis/graphics/index.md b/articles/getting_to_know/whatis/graphics/index.md index 36fb5c8..1988d76 100644 --- a/articles/getting_to_know/whatis/graphics/index.md +++ b/articles/getting_to_know/whatis/graphics/index.md @@ -14,12 +14,70 @@ The topics in this section describe the graphical conventions used by MonoGame i Sprites are 2D bitmaps that are drawn directly to a render target without using the pipeline for transformations, lighting or effects. Sprites are commonly used to display information such as health bars, number of lives, or text such as scores. Some games, especially older games, are composed entirely of sprites. -> More Coming soon - ### 3D concepts -> Coming soon +* [What Is 3D Rendering?](WhatIs_3DRendering.md) + + The 3D graphics pipeline uses a graphics device to load resources and render a 3D scene using an effect. + +* [What Is a Configurable Effect?](WhatIs_ConfigurableEffect.md) + + A configurable effect is an optimized rendering effect designed for Windows Phone. A configurable effect is created using a built-in object with options for user configuration. + +* [What Is a Depth Buffer?](WhatIs_DepthBuffer.md) + + A depth buffer contains per-pixel floating-point data for the z depth of each pixel rendered. A depth buffer may also contain stencil data which can be used to do more complex rendering such as simple shadows or outlines. + +* [What Is Blend State?](WhatIs_BlendState.md) + + Blend state controls how color and alpha values are blended when combining rendered data with existing render target data. + +* [What Is Depth Stencil State?](WhatIs_DepthStencilState.md) + + Depth stencil state controls how the depth buffer and the stencil buffer are used. + +* [What Is Rasterizer State?](WhatIs_Rasterizer.md) + + Rasterizer state determines how to render 3D data such as position, color, and texture onto a 2D surface. + +* [What Is Sampler State?](WhatIs_Sampler.md) + + Sampler state determines how texture data is sampled using texture addressing modes, filtering, and level of detail. + +* [What Is Color Blending?](WhatIs_ColorBlending.md) + + Color blending mixes two colors together to produce a third color. + +* [What Is a Stencil Buffer?](WhatIs_StencilBuffer.md) + + A stencil buffer contains per-pixel integer data which is used to add more control over which pixels are rendered. A stencil buffer can also be used in combination with a depth buffer to do more complex rendering such as simple shadows or outlines. + +* [What Is a Model Bone?](WhatIs_ModelBone.md) + + A model bone is a matrix that represents the position of a mesh as it relates to other meshes in a 3D model. ### Other Graphical concepts -> Coming soon +* [What Is a Graphics Profile?](WhatIs_GraphicsProfile.md) + + Provides conceptual information about the MonoGame Framework concept of graphics profiles, including explanations of the Reach and HiDef profiles. + +* [What Is a Back Buffer?](WhatIs_BackBuffer.md) + + A back buffer is a render target whose contents will be sent to the device when [GraphicsDevice.Present](xref:Microsoft.Xna.Framework.Graphics.GraphicsDevice.Present) is called. + +* [What Is a Render Target?](WhatIs_Render_Target.md) + + A render target is a memory buffer for rendering pixels. One common use for a render target is offscreen rendering. + +* [What Is a View Frustum?](WhatIs_ViewFrustum.md) + + A view frustum is a 3D volume that defines how models are projected from camera space to projection space. Objects must be positioned within the 3D volume to be visible. + +* [What Is a Viewport?](WhatIs_Viewport.md) + + A viewport is a 2D rectangle that defines the size of the rendering surface onto which a 3D scene is projected. + +* [What Is Antialiasing?](WhatIs_Antialiasing.md) + + Antialiasing is a technique for softening or blurring sharp edges so they appear less jagged when rendered.