Problem of rendering scene to texture
You want to save the content on the screen in a texture file, so that the screen can be realized, or the scene can be drawn to a texture, this texture is used for deep textures/refraction textures or as input to post-processing effect.
Solution
The simplest method is to use the device. resolvebackbuffer method, which writes the content in the current backup buffer to a texture. If you only want to plot a scene to a texture, or specify the size of the texture, you need to use the device. setrendertarget method to change the rendering target from the screen to the Target defined in the memory. Once the scenario has been fully drawn to that goal, you can store its content in a texture.
Working Principle
The simplest way is to plot the scenario to the screen and copy the content in the backup buffer to resolvetexture2d. In this way, you must first create a resolvetexture2d object to store the content of the backup buffer. This means that the size and format of the resolvetexture2d object must be the same as that of the backup buffer. Add the following to the loadcontent method:CodeCreate a resolvetexture2d object:
Presentationparameters pp = device. presentationparameters; resolvetexture = new resolvetexture2d (device, pp. backbufferwidth, pp. backbufferheight, 1, device. displaymode. format );
The first line of code gets the current presentationparameters, which contains all the details about the current configuration of the image device, including the current width, height, and backup buffer data format. The second line of code creates a resolvetexture2d object based on presentationparameters. After creating the resolvetexture2d object, you can use it to store the content of the current backup buffer. Add the following code to the draw method where you want to extract the backup Buffer:
Device. resolvebackbuffer (resolvetexture); resolvetexture. Save ("output.bmp", imagefileformat. BMP );
The above code stores the content of the current backup buffer in the resolvetexture variable. Because resolvetexture2d is inherited from the texture2d class, you can treat this resolvetexture2d as a normal texture2d processing. In the previous example, we saved the texture as a file.
Note:: Due to hardware restrictions, the content in the backup buffer will be discarded after the device. resolvebackbuffer method is called!
Use a custom rendering target of the same size as the screen (render target)
You can customize a rendertarget2d and activate the rendertarget2d before drawing, instead of drawing it to the backup buffer. Rendering target-as the name implies: A piece of memory that can be used to draw on it. After all the rendering is complete, copy the rendering target content to a texture. Add a variable:
Rendertarget2d rendertarget;
Then instantiate It In The loadcontent method:
Presentationparameters pp = device. presentationparameters; rendertarget = new rendertarget2d (device, pp. backbufferwidth, pp. backbufferheight, 1, device. displaymode. format );
You have defined the width and height of the rendering target, specified the level of mipmap to 1 (see tutorial 3-6), and set the data format. In this example, you use the same value as the backup buffer.
Note:: Mipmap can only be executed when the width/height of the texture is an integer power of 2. When you specify other mipmaps greater than 1, the reason is that the texture size is not an integer power of 2.
After you initialize the rendering target, you can use the following code in the draw method to set it as an active rendering target. After this line of code, everything will be drawn to this custom rendering target:
Device. setrendertarget (0, rendertarget );
You need to add this line of code before the draw method calls clear, because the rendering target content needs to be cleared before drawing other things. Then, you draw the entire scene. After the scene is drawn, copy the content of the rendering target to a texture. Before that, you need to use activating to deactivate another rendering target. In this Code, you set the second parameter to null to use the backup buffer as the rendering target:
Device. setrendertarget (0, null); texture2d resolvedtexture = rendertarget. gettexture ();
Now that you have activat's default backup buffer, everything that is rendered later is drawn to the screen as before.
The last line of code loads the content in the Custom rendering target into the resolvedtexture variable.
Set a custom rendering target with a size not equal to the screen size
You can also select to draw a rendering target different from the screen size. This is useful. For example, it can be used in the intermediate process of post-processing effect. A smaller image can be used in fuzzy, intensity, and edge detection shader to reduce the burden on the video card.
This is not a problem if the length/width ratio is the same as that of the window. If you want to set a rendering target with a different aspect ratio and window, your projection matrix will be incorrect for the rendering target, because this projection matrix is created using the aspect ratio of the window (see tutorial 2-1), you need to define a new projection matrix for the rendering target:
Presentationparameters pp = device. presentationparameters; int width = pp. backbufferwidth/2; int Height = pp. backbufferheight/4; rendertarget = new rendertarget2d (device, width, height, 1, device. displaymode. format); rendertargetprojectionmatrix = matrix. createperspectivefieldofview (mathhelper. piover4, (float) width/(float) height, 0.5f, 100366f );
First, you define the resolution of the rendering target and create the corresponding rendering target and projection matrix. The width of the new rendering target is set to half of the window width, and the height is 1/4. In this way, the aspect ratio of the rendering target is different from that of the window. If you still use the old projection matrix, the scene seems to have been squashed in the vertical direction. Now, as long as you are rendering the scenario to the rendering target, you must use rendertargetprojectionmatrix to replace the projection matrix of the corresponding window. The Code initializes an rendertarget2d object and sets the desired resolution. Note that if you save the content in the texture, the texture size must be the same as that of the rendering target.
Protected override void loadcontent () {Device = graphics. graphicsdevice; basiceffect = new basiceffect (device, null); ccross = new coordcross (device); spritebatch = new spritebatch (device); presentationparameters pp = device. presentationparameters; int width = pp. backbufferwidth/2; int Height = pp. backbufferheight/4; rendertarget = new rendertarget2d (device, width, height, 1, device. displaymode. format); rendertargetprojectionmatrix = matrix. createperspectivefieldofview (mathhelper. piover4, (float) width/(float) height, 0.5f, 100366f );}
In the draw method, you activate a custom rendering target to render the scene, deactivate the rendering target, and save the content to a texture. Note: Use rendertargetprojectionmatrix to draw 3D objects to the rendering target. This texture can also be displayed on the screen using spritebatch:
Protected override void draw (gametime) {Device. setrendertarget (0, rendertarget); device. clear (clearoptions. target | clearoptions. depthbuffer, color. cornflowerblue, 1, 0); ccross. draw (fpscam. viewmatrix, rendertargetprojectionmatrix); device. setrendertarget (0, null); texture2d resolvedtexture = rendertarget. gettexture (); graphics. graphicsdevice. clear (color. tomato); spritebatch. begin (); spritebatch. draw (resolvedtexture, new vector2 (100,100), color. white); spritebatch. end (); base. draw (gametime );}