Managed DirectX (chapter 4)

Source: Internet
Author: User


More rendering TechnologiesTranslation: ClaymanAfter discussing the basic rendering methods, we should focus on some rendering technologies that can improve performance and make the scenario look better:Rendering various primitive typesSo far, we have rendered only one type of elements, called a triangle set. In fact, we can plot many different types of elements. The following list describes the original graph type: pointlist-this is a self-described primitive type, it draws data as a series of discrete points. Indexed primitives cannot be drawn using this type. Linelist -- draw each pair of points as a separate line. At least two vertices are required for use. Linestrip-draws a vertex as a line. At least two vertices are required. Tranglelist -- this is the type we have been using. Each of the three vertices is drawn as a separate triangle. The current removal mode is used to determine how to remove the backend. Tranglestrip-a triangle belt is a series of connected triangles. Each two adjacent triangles share two vertices. In the elimination mode, all even triangles are automatically flipped (flipped on all even-numbered triangles) Because adjacent triangles share two vertices and they are redirected to the opposite direction. This is also the most primitive type used by complex 3D objects. Tranglefan-similar to a triangle band, but all triangles share a vertex. You can use the same data to draw any type or number of elements. Direct3d draws Based on the given primitive type. Let's write a little bit to draw these elements. Modify the code when we create a vertex buffer. Because you do not need to move the vertex, you can delete the world Transform in setupcamera, and delete all the code that references the angle member. Add the following code: Private const int numberitems = 12; 12 is a random number, but there are also some reasons. Too many vertices will make the screen too crowded, and the number of vertices must be divisible by 2 and 3 at the same time. In this way, all elements can be correctly rendered. Next, modify the code for creating the vertex buffer: VB = new vertexbuffer (typeof (customvertex. positioncolored), numberitems, device, usage. dynamic | usage. writeonly, customvertex. positioncolored. format, pool. default); customvertex. positioncolored [] Verts = new customvertex. positioncolored [numberitems]; for (INT I = 0; I <numberitems; I ++) {float xpos = (float) (RND. nextdouble () * 5.0f)-(float) (RND. nextdouble () * 5.0f); setp Osition (New vector3 (xpos, ypos, zpos); Verts [I]. color = randomcolor. toargb ();} There is nothing special here. we modified the vertex buffer size to save enough vertices. Next, we modified the method for creating the vertex and used a random method to fill the vertex. You can find the declaration about RND and randomcolor in the source code. Now you need to modify the drawing method. Several types of original images are displayed on a rolling basis, which can easily show the relationships between them. We display one type every two seconds. It can be timed based on the relative time (in ticks) from the start time to the present. Add the declaration of two member variables: Private bool needrecreate = false; Private Static readonly int imitialtickcount = system. environment. tickcount; the first Boolean variable controls re-creation of vertex buffering at the beginning of each "Cycle. In this way, the same vertex does not need to be displayed every time. Use the following code to replace the simple drawprimitives method: (See switch in the source code) This is basically a piece of self-explanatory code. Call drawprimitives to draw the original graph based on different time points in a cycle. Note: because of the original graph type, the original number of images that can be drawn with the same number of vertices is also different. Run the program. The original graph is displayed in the order of pointlist, linelist, linestrip, traglelist, and tanglestrip. If you think the "point" is too small to be clearly visible when the pointlist is displayed, you can adjust the render state to slightly enlarge it: device. renderstare. pointsize = 3.0f;Use index Buffer)Remember the code we used to create a box. We created 36 vertices in total. In fact, we only use eight different vertices, that is, the eight vertices of a square. In such a small program, storing the same vertex for many times does not cause any major problems. However, in a large program that needs to store a large amount of data, it is very important to reduce data duplication to save space. Fortunately, one index buffer mechanism in direct3d allows the same graph to share its vertex data. As his name implies, the index buffer is a buffer that stores the vertex data index. The index in the buffer is a 32-bit or 16-bit integer. For example, when you use indexes 0, 1, and 6 to draw a triangle, the image will be rendered by ing the index to the corresponding vertex. Use the index to modify the code for drawing the box. First, modify the method for creating the vertex: VB = new vertexbuffer (typeof (customvertex. positioncolored), 8, device, usage. dynamic | usage. writeonly, customvertex. positioncolored. format, pool. default); customvertex. positioncolored [] Verts = new customvertex. positioncolored [8]; Verts [0] = new customvertex. positioncolored (-1.0f, 1.0f, 1.0f, color. red. toargb) As you can see, We dramatically reduce the number of vertices and store only eight vertices of a square. Now that we have vertices, what should the indexes of 36 plot boxes look like? Take a look at the previous program and list the appropriate indexes in the order of 36 vertices: Private Static readonly short [] indices = {, 2, // front face, 2, // front face ·····}For ease of reading, the index is divided into three rows, indicating a special triangle. The first triangle uses vertex 0, 1, 2, and the second uses 1, 3, 2, and so on. It is not enough to have an index list. You also need to create an index Buffer: Private indexbuffer IB = NULL. This object is used to store and allow direct3d to access the index. It is similar to creating a vertex buffer. Next, initialize the object and fill in the data: IB = new vertexbuffer (typeof (short), indices. length, device, usage. writeonly, pool. default); IB. created + = new eventhandler (ib_created); onindexbuffercreate (IB, null ); Private void ib_created (Object sender, eventargs e) {indexbuffer buffer = (indexbuffer) sender; buffer. setdata (indices, 0, lockflags. None );} In addition to the constraints of the parameters, the index buffer constructor is simply a model. As mentioned above, only 16-bit or 32-bit integers can be used as indexes. We subscribe to the event handler and manually call it when the program runs for the first time. Finally, the index buffer is filled with data. Now, you need to modify the rendering Image Code to use this data. If you still remember, we used a method called "setstreamsource" to tell DirectX which fast vertex buffer is used for rendering. Likewise, there is also a mechanism for index buffering, but it is only an attribute, because only one type of index buffering can be used at a time. After setstreamsource, set the following attributes: device. Indices = Ib; direct3d knows that the vertex buffer exists, and then modify the drawing code. Currently, our drawing method tries to draw 12 original graphs from the vertex buffer, but this will not succeed, because there are only eight vertices in the vertex buffer. Add 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); device. drawindexedprimitives (primitivetype. trianglelist, 0, 0, 8, 0, indices. length/3 );} Here, we change drawprimitives to drawindexedprimitives. Let's take a look at the prototype of this method: Public void drawindexedprimitives (primitivetype, int basevertex, int minvertexindex, int numvertices, int startindex, int primcount ); The first parameter is the same as the previous method, indicating the original graph type to be drawn. The basevertex parameter indicates the offset from the index buffering start point to the first vertex index to be used. Minvertexindex is the smallest vertex index value among the vertices. Obviously, numvertices refers to the number of vertices to be used. Startindex indicates the position in the array from which the vertex is read. The last parameter is the original number of images to be drawn. Now, with the eight vertices in the index buffer, we can draw 12 original images that constitute the cube. Next, use the drawbox method to replace the original drawprimitives method. Drawbox (angle/(float) math. Pi, angle/(float) math. Pi * 2.0f, angle/(float) math. PI/4.0f, 0.0f, 0.0f, 0.0f );(For details, refer to the source code) Run the program again and you can see that the box with very bright colors is rotating. Each vertex has a different color. Therefore, it truly reflects the shortcomings of using index buffering to share the vertex. When multiple graphs share the original vertex, all vertex data is shared, including color and normal data. When deciding whether to share a vertex, you must ensure that shared data does not result in errors in light or color (because the computing of the light depends on the normal ). We can see that the color of each side of the cube is calculated by the vertex color interpolation.Use Using depth buffer)Depth buffer (also known as Z-buffer or W-buffer) is that direct3d stores "depth" during rendering ("depth" generally refers to the window coordinate from the screen to the observer's Z axis ). Depth information is used to determine the substitution relationship between pixels during grating (note: the degree is usually measured by the distance from the viewpoint to the object, in this way, pixels with a large depth value will be replaced by pixels with a smaller depth value, that is, distant objects are blocked by near objects ). So far, our programs have never used deep buffering, so no pixels are blocked during grating. In addition, we have not even overlapped pixels, so now we can draw some cubes that will overlap with existing cubes. Add the following code after calling the existing drawbox method: drawbox (angle/(float) math. pi, angle/(float) math. pI * 2.0f, angle/(float) math. PI/4.0f, 0.0f, (float) math. cos (angle), (float) math. sin (angle); · (omitted) We added three rotating cubes to the cube in the middle of the original row. Run the program and you can see the overlapping cubes, but you cannot distinguish the boundary of the overlapping parts of the two cubes. It looks like a normal spot. This requires in-depth buffering. Adding a deep buffer is a simple task. Do you remember the presentation parameters parameter that we passed to the device constructor? Well, this will be where we add a deep buffer. To create a device that contains a deep buffer, two new parameters are required: Public Mircosoft. directX. direct3d. depthformat encode [get, set] public bool enableautodepthstencel [get, set] enableautodepthstencel can be set to true to enable the deep buffer for the device. Use depthformat to specify the autodepthstencilformat Member. In the depthformat enumeration, the values that can be used are listed in the following table: D16 a 16-bit Z-buffer bit depth. d32 a 32-bit Z-buffer bit depth. d16lockable a 16-bit Z-buffer bit depth that is lockable. d32flockable a lockable format where depth value is represented by a standard IEEE floating point number. d15s1 a 16-bit Z-buffer bit Depth Using 15 bits for depth channel, with the last bit used for the stencel channel (stencel channels will be discusse D later ). d24s8 a 32-bit Z-buffer bit Depth Using 24 bits for depth channel, with the remaining 8 bits used for the stencel channel. d24x8 a 32-bit Z-buffer bit Depth Using 24 bits for depth channel, with the remaining 8 bits ignored. d24x4s4 a 32-bit Z-buffer bit Depth Using 24 bits for depth channel, with 4 bits used for the stencel channel, and the remaining 4 bits ignored. d24fs8 a non-lockable fo Rmat that contains 24 points of depth (as a floating point) and 8 bits for the stencel channel. the larger the depth buffer, the more deep data can be stored, but this is at the cost of performance. Unless you are sure you need to use a large depth of buffer, you can use the smallest value. Most modern graphics cards support a minimum of 16-bit depth buffer, so. Add the code: presentparams. autodepthstencilformat = depthformat. D16; presentparams. swapeffect = swapeffect. Discard; Perfect, and now the device has received a deep buffer. Let's see what's different. Run the program. Wow, the results were not what we expected, and the program was destroyed. What happened to these cubes? Why is rendering damaged after deep buffering. The reason is that the deep buffer has never been "cleared", so it is always in an incorrect state. You should clear the depth buffer at the same time as the clear device. modify the code as follows: device. Clear (clearflags. Target | clearflags. zbuffer, color. cornflowerblue, 1.0f, 0 ); Okay, everything is normal. Take a break and enjoy our work. ^_^.

Need source code can go to this place to go to The http://bbs.gameres.com/showthread.asp? Threadid = 24673

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.