Create a scenario and track-draw a scenario

Source: Internet
Author: User
Scenario Rendering

In the previous chapter, you can see that, with the help of the. x model, you can use a simplified method to create a 3D scenario. First, you create a diffuse texture, and then create a normal texture, and finally add an elevation map to generate a canyon for xNa shooter.

For this game, you still need to use a very simplified method to render the scene, because the development time is very short, and it usually takes several months to make a high-precision scene rendering engine. For example, the scenario engine used in arena wars games supports very large scenarios, but it has never been used in the game. optimizing in different hardware configurations requires a lot of work, in particular, it also supports different types of ground textures in 24.

To keep it simple, this racing game only uses a very large ground texture, but you also need a normal texture and an extra detail texture to add some details, especially when you are very close to the ground, this usually happens when you stay very close to the scene. At first I made a 4096x4096 texture, but it was hard to be updated, including the normal texture. The unzipped diffuse texture is about 64 MB, and 64 MB is also used for the normal texture. Imagine creating 10 or more textures on a computer with only 1 GB of memory, and the results would be terrible. Even if it is compressed into a dxt5 texture, the 4096x4096 normal texture still has about 12 Mb, Which is annoying when loading the texture alone. Another reason why I gave up using a 4096x4096 texture is the content pipeline in xNa, which takes a long time to convert such a large texture to A. xNb content file.

I scaled down to 2048x2048 texture, which looks almost as good as 4096x4096, but only takes 1/4 of the size and loading time. The normal texture is even reduced to 1024x1024, because it does not seem very different. Another reason for not using large textures is that Microsoft's Xbox 360 memory size is limited (64 MB), and you should not load too many things or too large textures, otherwise the performance will be greatly reduced. Instead of creating a super-large texture, I added a detailed texture to make the scene look better when the lens is zoomed closer. The following pages will discuss how to draw these textures.

Texture

First, you need an elevation chart and know how big your scenario is. Initially I wanted the Texel (texture pixel, texture 1 pixel) of a scene to be 1 meter (3.3 feet ), so the 4096x4096 texture makes the entire scenario 4x4 km big (about 2.5x2. 5 miles ). The scene size remains unchanged when the texture is reduced to 2048 × 2048, And now each texture pixel is 2 × 2 meters.

So where do you get the height value for your scenario? You may not be very good either.ProgramTo help you do this, you certainly do not have enough time to write a custom scene elevation chart editor. A good idea is to search for and use existing elevation maps on the Internet, with many resources available (geographic, NASA, and even other planetary elevation maps ).

I want to have some mountains for this racing game. It was good enough for the test, but later I needed mountains around the scene, so I had to modify the elevation map so that the scene was surrounded by mountains and other mountains around the border. In the final elevation chart, you can see Figure 12-5. Please note that the landscapegridheights.png elevation map used by this game has only 257x257 pixels, because only 257x257 (66049) vertices can be generated in the landscape class, that is, 256*256*2 polygon (about 0.13 million polygon ). Too many polygon will greatly slow the rendering speed, but processing 130000 polygon is not a big problem for today's graphics cards, and the Xbox 360 can also handle well (still several hundred frames per second ).


Figure 12-5

You may notice that the elevation chart is used for flat areas in urban areas, but simply placing all buildings and objects at the same height. The white area in the middle is a mountain, and the white-gray area surrounding the map boundary indicates the boundary Mountain.

This elevation map generates a normal map with a slightly fluctuating texture. In addition, you can also mix diffuse Textures like in the previous chapter, but because I want to change the diffuse texture frequently, the normal texture will not be affected by the diffuse texture. Figure 12-6 shows the game scenario where diffuse textures and normal maps are used.


Figure 12-6

Please note that I have tried these textures many times until they become the current one, and I am not totally satisfied, but you must stop it, especially when you do not have more time for improvement. For example, the normal texture looks great from a distance, but there is no variation when it is near, maybe it can be improved by better matching the diffuse texture. In any case, they look good in the game and I have not heard any complaints.

Finally, you have added a detail texture when approaching the scene. You won't immediately notice the detail Paster, but figure 12-7 shows a convincing difference between use and no detail Paster. There is such a big scene in this racing game, and it is allowed to zoom in the camera. If there is no detailed texture, the screen performance is poor.


Figure 12-7

Rendering

If you open the racing game project, you can see a lot of classes from previous chapters, but there are two new namespaces that will be discussed in this chapter: landscapes and tracks. There is only one landscape class in the landscapes namespace (see figure 12-8). It is responsible for rendering scenes, including all objects in the scene, all tracks and tracks, basically everything except your car. In The misson class, you only call the render method of landscape to execute all rendering operations. There are several helper methods available for shadow ing. The details about shadow ing will be discussed in chapter 14th.


Figure 12-8

All scene objects are created and created in the landscape class, especially in the construction functions of the track class, which are used inside the landscape class. You can immediately see the 3D model used in this game.

To render a scenario, you must first generate it in the constructor. Before you view the constructor, you should check the testrenderlandscape unit test in the landscape class. before implementing the class, you should first write the unit test. You have also noticed other unit tests. generatelandscapeheightfile generates a level file for the scene elevation map and generates a special content file. This method is the same as in the rocket Commander, because it is impossible to load bitmap data in Xbox 360.

/// <Summary> // test render landscape // </Summary> Public static void testrenderlandscape () {testgame. start ("testrenderlandscape", delegate {racinggame. loadlevel (racinggame. level. beginner); racinggame. landscape. setcartostartposition () ;}, delegate {If (basegame. allowshadowmapping) {// generate shadows shadereffect. shadowmapping. generateshadows (delegate {racinggame. landscape. generateshadow (); racinggame. carmodel. generateshadow (racinggame. player. carrendermatrix) ;}); // render shadows shadereffect. shadowmapping. rendershadows (delegate {racinggame. landscape. useshadow (); racinggame. carmodel. useshadow (racinggame. player. carrendermatrix) ;};}// if (basegame. allowshadowmapping) basegame. UI. postscreenglowshader. start (); basegame. UI. rendergamebackground (); racinggame. landscape. render (); racinggame. carmodel. rendercar (0, color. goldenrod, racinggame. player. carrendermatrix); // and flush render manager to draw all objects basegame. meshrendermanager. render (); If (basegame. allowshadowmapping) shadereffect. shadowmapping. showshadows (); basegame. UI. postscreenglowshader. show (); testgame. UI. writetext (2, 50, "number of objects:" + racinggame. landscape. landscapeobjects. count) ;}) ;}// testrenderlandscape ()

This unit test has done a lot of things, and it shows cars and all scene objects. Tracks, all shadow mappings, and post-screen shaders are also tested here to ensure they work well in the scene. If you only want to test the scenario, you only need to call the render method in the landscape class.

The loadlevel method in the racinggame class is the main class of the game, which is responsible for loading a level. All levels use the same scenario, which means you do not have to reload it. However, you should checkCode. The scenario constructor performs the following operations:

    • Load the elevation chart data graph from the level file and create the tangent Vertex

    • Generate and smooth the normal of the entire scenario, and regenerate the tangent from the new normal.

    • Set the vertex buffer for these vertices
    • Calculate the index buffer (similar to the scenario triangle you saw in the previous chapter)

    • SET index Buffer

    • Load and generate track data for the current level, including all scene objects

    • Finally, add additional objects, such as the city ground, to give the city objects a better texture ..

The most important part of the constructor is to generate a tangent vertex from the elevation chart, which generates a vertex for you by traversing all 257x257 points in the elevation chart:

// Build our tangent verticesfor (INT x = 0; x <gridwidth; X ++) for (INT y = 0; y <gridheight; y ++) {// Step 1: Calculate position int Index = x + y * gridwidth; vector3 Pos = calclandscapepos (X, Y, heights); mapheights [x, y] = POS. z; vertices [Index]. pos = Pos; // Step 2: Calculate all edge vectors (For normals and tangents) // This involves quite complicated optimizations and mathematics, // ha Rd to explain with just a comment. read my book: D vector3 edge1 = pos-calclandscapepos (X, Y + 1, heights); vector3 edge2 = pos-calclandscapepos (x + 1, Y, heights ); vector3 edge3 = pos-calclandscapepos (X-1, Y + 1, heights); vector3 edge4 = pos-calclandscapepos (x + 1, Y + 1, heights ); vector3 edge5 = pos-calclandscapepos (X-1, Y-1, heights); // Step 3: calculate normal based on the E Dges (interpolate // from 3 cross products we build from our edges ). vertices [Index]. normal = vector3.normalize (vector3.cross (edge2, edge1) + vector3.cross (edge4, edge3) + vector3.cross (edge3, edge5); // Step 4: Set tangent data, just use edge1 vertices [Index]. tangent = vector3.normalize (edge1); // Step 5: Set texture coordinates, use full 0.0f to 1.0f range! Vertices [Index]. UV = new vector2 (y/(float) (gridheight-1), X/(float) (gridwidth-1);} // For (INT)

You can see that this code generates vertices in five steps. First, calculate the location vector. Then, all edge vectors are calculated, and the normal is constructed from the three forks and the tangent is allocated. Finally, texture coordinates are allocated, but you have installed X and Y to make later XY rendering easier, but you still need to correctly align the texture to make it look like a bitmap. The vertex list is generated when it is defined. Because only the 257 × 257 elevation map mesh is supported, the calclandscapepos auxiliary method is very simple, but the height vector is extracted from the elevation chart data:

 
Private vector3 calclandscapepos (int x, int y, byte [] heights) {// make sure we stay on the valid map data int MapX = x <0? 0: x> = gridwidth? Gridwidth-1: X; int mapy = Y <0? 0: y> = gridheight? Gridheight-1: Y; float heightpercent = heights [MapX + mapy * gridwidth]/255.0f; return New vector3 (x * mapwidthfactor, y * mapheightfactor, heightpercent * mapzscale );} // calclandscapepos (X, Y, texdata)

After all the vertices and indexes are generated, you can finally render the scenario with the help of landscapenormalmapping. FX. You don't believe how easy it is. The following code renders a polygon of 130000. It also includes landscapenormalmapping shader using diffuse textures, normal textures, and extra detail textures:

// Render landscape (pretty easy with all the data we got here) shadereffect. landscapenormalmapping. render (MAT, "diffusewithdetail20", delegate {basegame. device. vertexdeclaration = tangentvertex. vertexdeclaration; basegame. device. vertices [0]. setsource (vertexbuffer, 0, tangentvertex. sizeinbytes); basegame. device. indices = indexbuffer; basegame. device. drawindexedprimitives (primitivetype. trianglelist, 0, 0, gridwidth * gridheight, 0, (gridwidth-1) * (gridheight-1) * 2 );});

The shadereffect class from Chapter 1 allows you to render the scene material by using the special technology of the renderdelegate code.

The render method in the landscape class also renders the track and all scene objects. Track rendering will be discussed in the rest of this chapter. We won't talk about all the models used in the game, because there are too many models. Take a look at the testrendermodels unit test of the model class. You can see all of them in Figure 12-9.


Figure 12-9

Optimization skills

The processing scenario engine is not easy. Even if you have created a great scenario engine that supports many different shader and texture sets, you still have to worry about performance. On the other hand, if you already have a scene engine with good performance, such as racing games from this chapter or shooting games from the previous chapter, you may still want to improve the visual quality without affecting its performance. Making the scene engine fit your game is a tough challenge. As I told you before, I tried to create a more complex scenario and graphics engine, which can create a huge scenario that is 100 times larger than the final one, but after optimization, these features have never been used.

Instead, you should focus on what the game is doing. Taking racing games as an example, a fixed scenario is easy to implement, and it is always the same. Therefore, testing is easier. You can reuse some existing scenes and objects for other levels without having to redesign everything. For many different tracks, the scenario is not big enough (4096 × 4096 meters), because the first level only shows you a small part of the scenario (about 20% ~ 30% ).

The scenario rendering technology used in this chapter and the next chapter has three disadvantages:

    • You cannot change the scene size at will, which will involve a lot of work. If you have used a texture of 4096x4096, you may not be able to further improve the texture quality. If the texture is very close to the ground, it looks very fuzzy even if you use extra details.

    • It is difficult to change the diffuse texture map. You need to combine different types of textures on your own, but it is still difficult to see the results and involves many tests. Worse, the longer the texture, the longer the development time.

    • The scene engine is not powerful enough to handle Advanced effects, such as adding a crater on the ground or adding additional textures (tracks, roads, leaves, etc.), and you cannot even dynamically change the appearance. This means that the scenario is static. To create a level editor, you also need a more flexible solution that allows you to change texture types and automatically combine them.

The best way to bypass these problems is to use a scene rendering technology called splatting, which uses a series of textures and renders them to a texture map with the same resolution as the elevation chart. Because it does not look very good to side different textures on the ground, you need to perform interpolation. You can weaken the texture block, but this looks too rough, or you can save the percentage value for each Texture type.

Scenes are rendered separately from ground textures. You should make the lowest one completely opaque to ensure that you do not see the scenes behind them, the ground texture is a mixture of alpha (see figure 12-10 ).


Figure 12-10

You can also use an Alpha mixed texture or just mix the color values (see figure 12-10 ). Because shader is used in xNa, you can combine four (pixal shader 1.1) or eight (pixel shader 2.0) textures in one shader pass to optimize performance. If your scene engine needs to process more textures, you will need multiple passes until everything is correctly rendered. It is sometimes faster to render only the visible texture without rendering all. It will become more difficult when you generate vertex and index buffering, but if you have a lot of textures, such as 20 or 30 different ground textures, the performance will be greatly increased, since each Texture type on the ground only uses 10% or lower, rendering is meaningless all the time.

No matter what technology you choose, I strongly recommend that you start with a simple one, such as rendering a large scenario where only one texture is tiled and then improved. You may also want the game to reach several hundred frames per second after adding all scene models, 3D objects, and effects.

There are more skills and tips for creating good scenarios. You can implement pre-computed lighting and shadows, and there are many opportunities to use better shader, especially when the scenes include water. The lawn can be implemented through fur shader. The appearance of rocks and cuts can be enhanced through parallax ing or even offset ing. If you are interested in these topics, refer to the books about shader, suchGame programming gemsAndShaderx, Or search for tips, tips, and tutorials through the Internet.

Figure 12-11 shows how to use post-screen shaders, Hud, and sky box ing (if you forget, see Chapter 5th and Chapter 6th for details about these types of shaders, the final scenario.


Figure 12-11

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.