Managed DirectX (chapter 5)

Source: Internet
Author: User

Rendering with Meshes

Translation: Clayman

Clayman_joe@yahoo.com.cn

 Define MeshAlthough you often need to manually create vertex and index data, it is more common to load existing vertex data from external resources, such as from a file. We usually use the. X file to save this information. In the previous chapter, most of the code is used to create the ry. This seems completely feasible for simple triangles and cubes, but imagine that using the same method to create an object with tens of thousands of vertices would, the time and effort will be terrible. Fortunately, managed DirectX has an object that can encapsulate and load vertex and index data. This isMesh. Mesh can be used to store any type of graphic data, but is mainly used to encapsulate complex models. The mesh class also has some ways to improve the rendering object performance. All mesh objects contain a vertex buffer and an index cache. In addition, it also containsAttribute Buffer)-- We will discuss it later in this chapter. The real mesh object package is located in the direct3d extension Library (d3dx direct3d extensions library. To add a reference to the direct3dx. dll assembly, we will try to use mesh to create a Rotated Cube. First, add the mesh member before declaring the vertex buffer and index buffer members: Private mesh = NULL; the mesh class has three constructor functions, but no one of them is needed now. The mesh class has several static methods that can be used to create or load different models. The first thing to note is the "box" method. Just like its name, it creates a mesh containing a cube. Think about it, we can render the cube immediately, which is perfect. ^_^ (Note: You can delete all the Code related to vertex buffering and index buffering ). Add the following code after creating the device: mesh = mesh. box (device, 2.0f, 2.0f, 2.0f); this method creates a mesh that contains vertices and indexes, and can be rendered as a cube with a length, width, and height of 2. It is the same size as the cube created manually with vertex buffering. We have reduced the code for creating an object to one line, so it is no longer easy. Although a mesh has already been created, can we use the original method to render it? Do you still need another path? Previously, during rendering, we needed to call setstreamsource to tell direct3d which vertex buffer to read data. We also had to set indexes and vertex format attributes. These are not required for rendering mesh. (TIPS: mesh has all vertex buffering, index buffering, and vertex format information. Stream source, index, and vertex format attributes are automatically set during rendering.) How to render the mesh? Mesh is divided into a series of subsets (allocated based on the size of the attribute buffer), and rendered using a method called drawsubset. Modify the drawbox method: Private void drawbox (float yaw, float pitch, float roll, float X, float y, float Z) {angle + = 0.01f; device. transform. world = (matrix. rotationyawpitchroll (yaw, pitch, roll) * matrix. translation (x, y, z); mesh. drawsubset (0);} change the deawindexedprimitives method to drawsubset. The normal elements created using the mesh class always have only one subset based on 0. Well, this is all the changes made to run the program again, which is unexpectedly simple. Run it. Well, I got nine boxes (12 in the source code) Again, but all the boxes turned white, right? Observe the vertex format in the mesh (you can view the vertexformat attribute of the mesh). Only the vertex position and normal data are stored in the mesh. There is no color data in the mesh, and the light is turned on. Naturally, everything is white. Remember that as long as the vertex data contains the normal information, you can use the light. Since the box has normal data, maybe we should open the light. By default, the light is turned on. Now you can delete or set the code for closing the light to true. Hehe, we successfully changed the white box to black -.-#. I hope you have guessed that this is because there is no light source in the scenario, so everything is black. For a specific light source, creating a light that can illuminate the entire scene will be good. WelcomeAmbient lighting). Environment light provides a balanced (constant) light source for the scenario. All objects in a scenario are illuminated in the same way, because ambient light does not depend on the factors required by several other light sources (such as location, direction, and attenuation ). Environment light can be used without the need for normal data. Environment light is the most efficient lighting type, but it cannot create a real "world ". But now, he can achieve our satisfaction. Add the following code to set the rendrstate: device. renderstate. Ambient = color. Red; the ambient light is completely defined by ambient render state and a color parameter is accepted. Here, we want the global light to be red so that we can see the obvious effect. Run the program and you want to see nine red rotating boxes. Unfortunately, they are still black. What else are missing?Use Material and lighting (using materials and lighting)What is the difference between this and lighting? The biggest difference (except for mesh) is that there is no color information in the vertex beads. This causes illumination failure. In order for direct3d to correctly calculate the color of a specific point in a 3D object, in addition to the color of the light, you also need to know how the object reflects the color of the light. In the real world, if the red light shines on the pale blue surface, it will show a soft purple. You also need to describe how our "surface" (our box) is reflective. In direct3d,Material (Materials)This attribute is described. You can specify how an object reflects ambient light and diffuse light, what the specular highlights looks like, and whether the object is completely reflected (emit) light. Add the following code to drawbox (before the drawsubset method): Material boxmaterial = new material (); boxmaterial. ambient = color. white; boxmaterial. diffuse = color. white; device. material = boxmaterial; a new material is created here.Environment Color (ambient color)(Note: The ambient color and ambient light color are different ^_^) and the scattering color values are set to white. White indicates that it reflects all the light. Next, we assign the material to the material attribute of the device, so that direct3d knows the material data used for rendering. Run the program and now you can see the correct results. Changing the color of ambient light can change the color of all boxes. Changing the environmental color of the material can change how the light illuminates the object. (Note: I regret that I didn't have a good optical course. 555 ~~, In the complete Maya manual, this is what we say: the Environmental color (ambient color), when it is black, it means (environmental light) will not affect the color of the material, when the environmental color becomes lighter, it will light the material and mix the two colors to affect the color of the material. If there is ambient light in a scenario, the color and brightness of the light will control the effect of the ambient color on the final Material color ). Changing the material to a color without a red color (such as green) will make the object black again (Note: At this time, the object will not reflect red, and the red light will be absorbed by all the objects ), changing to a color with some red components (such as gray) will make the object appear dark gray. As mentioned earlier, objects rendered in this way are not too real. You can't even see the "chamfer" of each cube, as if it were red cube-like stripes. This is because ambient light calculates all vertices in the same way. We need a little bit of light. After creating the environment light, add the following code: device. lights [0]. type = lighttype. directional; device. lights [0]. diffuse = color. white; device. lights [0]. direction = new vector3 (0,-1,-1); device. lights [0]. commit (); device. lights [0]. enabled = true; a white direction light is created here, which is in the same direction as the camera. Now we can see the changes in light and shade in different directions. When creating a mesh, a series of objects can be used. Use one of the following methods to create a mesh (which requires device as the first parameter): (the left-hand coordinate system is used below) mesh = mesh. box (device, 2.0f, 2.0f, 2.0f); width, height, and depth indicate the size mesh of the box on X, Y, and Z axes = mesh. cylinder (device, 2.0f, 2.0f, 2.0f, 36,36); radius1, radius2 indicates the bottom and bottom radius of the cylinder, which must be non-negative; Length indicates the height of the cylinder in the z direction; slices indicates the number of segments along the central axis, and stacks indicates the number of "heaps" along the main axis. (Note: similar to the number of blocks in the horizontal and vertical directions divided by longitude and weft.) mesh = mesh. polygon (device, 2.0f, 8); Length indicates the length of each side of the polygon, and sides indicates the number of edges mesh = mesh. sphere (device, 2.0f, 36, 36); radius indicates the sphere radius. The meanings of slices and stacks are the same as those of cylinder. Mesh = mesh. TORUS (device, 0.5f, 2.0f, 36,18) innerradius ring diameter, outterradius ring outer diameter, number of sides on the sides cross section, number of rings on the rings cross section, the first two values must be non-negative, the last two must be greater than or equal to three. Mesh = mesh. Teapot (device) creates a teapot (for a teapot, you do not see the error ^_^ ). Each of the above methods has an overload that can return adjacency information. Each side uses three integers as the response information, three sides (adjacency information is returned as three integers per face that specify the three neighbors of each face in the mesh) are specified ).Use mesh to render complex modelsRendering the teapot is interesting, but it is impossible to render the teapot in the game. A large number of mesh objects are created by artists using professional modeling software. If your modeling software can export the. X file, congratulations, you are lucky (the direct SDK contains the export converter of common modeling software ). You can create a mesh by loading several data types stored in the X file. Of course, vertex and index data are the most basic requirements for rendering objects. Each subset of the mesh is associated with a material. Each material group can also contain texture information. You can also use both the X file and the High Level Shader Language (HLSL) file to create a mesh. HLSL is an advanced technology that we will discuss in depth later. Like creating static methods of the original type of a "simple" graph, there are two main static methods of the mesh class that can load external models. The two methods are mesh. formfile and mesh. fromstream respectively. The two methods are essentially the same. The stream method has more reloads to adapt to streams of different sizes. The most common overload methods are as follows: public static mesh fromfile (string filename, meshflags options, device, out graphicsstream adjacency, out extendedmaterial materials, out effectinstance effects ); public static mesh fromstream (Stream stream, int readbytes, meshflags options, device, out graphicsstream adjacency, out extendedmaterial materials, out writable tinstance effects); the first parameter is the data source loaded as mesh. For the fromfile method, it is the file name to be loaded; For the fromstream method, it is the stream used and the number of data bytes to be read. If you use the entire stream, you only need to use the overload without the readbytes parameter. The meshflags parameter controls where to go and how to load data. The value of this parameter can be combined by the following values: mesh flags enumeration valuesparameter valuemeshflags. donotclip use the usage. donotclip flag for vertex and index buffers. meshflags. dynamic equivalent to using both ibdynamic and vbdynamic. meshflags. ibdynamicuse usage. dynamic for index buffers. meshflags. ibmanaged use the pool. managed memory store for index buffers. meshflags. ibsoftware processinguse the usage. softwareprocessing fl AG for index buffers. meshflags. ibsystemmem use the pool. systemmemory memory pool for index buffers. meshflags. ibwriteonly use the usage. writeonly flag for index buffers. meshflags. vbdynamic use usage. dynamic for vertex buffers. meshflags. vbmanaged use the pool. managed memory store for vertex buffers. meshflags. vbsoftwareprocessing use the usage. softwareprocessing flag for vertex buffers. meshflags. vbs Ystemmem use the pool. systemmemory memory pool for vertex buffers. meshflags. vbwriteonly use the usage. writeonly flag for vertex buffers. meshflags. managed equivalent to using both ibmanaged and vbmanaged. meshflags. npatches use the usage. npatches flag for both index and Vertex buffers. this is required if the mesh will be rendered using n-patch enhancement. meshflags. points use the usage. points flag For both index and Vertex buffers. meshflags. rtpatches use the usage. rtpatches flag for both index and Vertex buffers. meshflags. softwareprocessing equivalent to using both ibsoftwareprocessing and vbsoftwareprocessing. meshflags. systemmemory equivalent to using both ibsystemmem and vbsystemmem. meshflags. use32bit use 32-bit indices for the index buffer. while possible, normally not recommended. meshfl AGS. usehardwareonly use hardware processing only. The next parameter is the device for rendering the mesh. Because the resource must be associated with a device, this is a required parameter. The adjacency parameter is an "out" parameter, indicating that after this method is completed, adjacency will be allocated and passed out, and it will return callback information. The extendedmaterial class saves the normal direct3d material and a character string loaded as a texture. This string is usually the texture or resource file name used, because the texture is loaded by the program, it can also be a string provided by any user. After the group, the effectinstance parameter describes the HLSL material files and values used for mesh. You can select method overloading with different parameters as needed. A lot of details about loading and rendering mesh are discussed here, but it is actually not that complicated. You may be worried at first, but it is really easy to see the actual code. Try it now. First, make sure that there are variable members that can be used to store materials and textures for different subsets. After declaring the mesh, add the following code: private material [] meshmaterials; private texture [] meshtextures; because the mesh may have many different subsets, therefore, you must create an array of materials and textures to meet the needs of each subset. Now let's add some methods to actually load the mesh. Create a function named "loadmesh" with the Code as follows: Private void loadmesh (string file) {''''' (more code here, see the source code)} Okay. Although it seems a little scary than the simple work we have done before, it is actually not like this. First, we declare the extendenmaterial array used to save the mesh subset information. Then, call the fromfile method to load the mesh. We do not care about the adjacency or HLSL parameters, so we chose to overload the parameters without them. After the mesh is loaded, materials and texture information must be stored for a large number of subsets. After determining whether there are different subsets, we finally use the subset size to allocate the size to the material and texture members. Next, use a loop to copy the data in extenedmaterial to meshmaterials. If the subset also contains texture information, use the textureloader. fromfile method to create the texture. This method accepts two parameters, device, and the file name used as the texture. This method can be faster than the previously used system. Drawing. BitmapMany. To draw a mesh, you also need to add the following method: Private void drawmesh (float yaw, float pitch, float roll, float X, float y, float Z) {angle + = 0.01f; device. transform. world = matrix. rotationyawpitchroll (yaw, pitch, roll) * matrix. translation (x, y, z); For (INT I = 0; I <meshmaterials. length; I ++) {Device. material = meshmaterials [I]; device. settexture (0, meshtextures [I]); mesh. drawsubset (I) ;}} you may have noticed that this method retains the signature part of the drawbox method. Next, to draw the mesh, iterate all the materials, and perform the following steps: 1. Assign the saved materials to device; 2. Assign the texture to device. If there is no texture, no error occurs even if the value is null. 3. Call the drawsubset method perfect based on the subset ID. Now we have finished loading and rendering mesh. I have created a model named Tiny. X. Add the following code to load the model: This. loadmesh (@".. /.. /tiny. X "); you also need to adjust the camera position. It should be something other than tiny that the model looks like. Because the model is very large, the camera needs to step back and modify the following method: device. transform. projection = matrix. perspectivefovlh (float) math. PI/4, this. width/This. height, 1.0f, 1000.0f); device. transform. view = matrix. lookatlh (New vector3 (, 58020.f), new vector3 (), new vector3 (, 0); the distance from the cropping plane is increased after the redeployment, move the camera relatively backward, and complete the final task: Call the drawmesh method in the rendering part: This. drawmesh (angle/(float) math. pi, angle/(float) math. pI * 2.0f, angle/(float) math. PI/4.0f, 0.0f, 0.0f, 0.0f); finally, you can adjust the color of the light. We took another big step forward, which is much more interesting than watching the cube rotate.

We took another big step forward, which is much more interesting than watching the cube rotate.

In the next chapter, we will use managed DirectX to write a real game. It may seem simple, but after all, it is our first 3D Game ^ _ ^, chapter 6 compares the content, which can be translated 3 or 4 times.

Can go to this place to download source code http://bbs.gameres.com/showthread.asp? Threadid = 24918

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.