More rendering technology translation: Clayman After discussing the basic rendering method, we should put the attention to some rendering techniques that can improve performance and make the scene look better:
Rendering various primitive types
So far, we only render a type of element, called a triangular collection. In fact, we can draw a lot of different types of elements, and the list below describes these map original types:
PointList - This is a self-description type type, which draws data as a range of discrete points. This type cannot be used to draw indexed primitives.
LINELIST - Draws each pair as a separate line. There are at least two vertices when used.
LINESTRIP - draws the vertex as a fold line. At least two vertices are required.
TRANGLIST - this is the type we have been using. Every three vertices are drawn into a separate triangle. Decide how to carry out on the back side by the current culling mode.
The TRANGLESTRIP-Triangle belt is a series of connected triangles, and each two adjacent triangles share two vertices. Remove the mode automatically flipped all even triangles (Flipped on all even-numbered triangles), because the adjacent triangles share two vertices, they will be turned to the opposite direction. This is also the most complex 3D object used by the most element type.
Tranglefan - similar to the triangle belt, but all triangles share a vertex.
You can use the same data to draw any type, any number of primitives. Direct3D draws according to a given element type. Write a little bit to draw these few types of elements.
Modify the code we create a vertex buffer. Because you don't need to move the vertices, you can delete the World Transform in SetupCamera, and all the code that reference to the Angle member can also be deleted. Add the code:
Private const Int numberItems = 12;
12 Although it is a casually selected number, there is also a reason. Too many vertices will make the screen too crowd, and the number of vertices can be used at the same time by 2 and 3. This will be properly rendered regardless of that element. Next, modify the code that creates a 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 { FLOAT XPOS = (float) (rnd.nextdouble () * 5.0f) - (float) (rnd.nextdouble () * 5.0f); ······ (For details, see the source code) VERTS [I] .SetPosition (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, modify the method of creating a vertex, fill the top point in a random manner. You can find declarations about RND and Randomcolor in the source code. Now you need to modify the drawing method. The non-stop scrolling shows several types of Titraen, which can make contact between them. We show a type every two seconds. The relative time (in ticks) can be scheduled according to the boot. Add a declaration of two member variables: private bool needrecreate = false; Private static readonly int mitialtickcount = system.environment.tickcount; The first Boolean variable controls to recreate the vertex buffer when each "cycle" begins. This way, you don't have to display the same vertices every time. Use the code instead of a simple DrawPrimitives method: (See some of the Switch in the source code) This is basically a code that can be interpreted. DrawPrimitives call DrawPrimitives to draw the corresponding map of the original according to different times in one cycle. Note that due to the difference in Titra, the same number of vertices can be drawn. Run the program, which will be displayed in the order of PointList, LINELIST, LINESTRIP, TRAGLELIST, Tanglestrip. If you think that "point" is too small when you display PointList, you can zoomer it slightly by adjusting the Render State: Device.renderstare.PointSize = 3.0F; Using index buffer (Index buffer) Remember the code when we create a box, we have created 36 top points. In fact, we only use 8 different vertices, that is, 8 top points of the square. In such a small program, the same vertex is stored many times and does not have any problems. However, in a much larger program that needs to store a lot of data, it is very important to reduce the repetition of the data. Fortunately, Direct3D has a mechanism that has become an index buffer to share his vertex data. As his name suggests, the index buffer is a buffer that saves the vertex data index. The index in the buffer is 32-bit or 16-bit integers. For example, when you use indexes 0, 1, 6 to draw a triangle, you will be reflected to the corresponding vertex by indexing to render the image. Use the index to modify the code to draw the box, first modify the method of creating a 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 ()); ····· (see the source ONVERTEXBUFFERCREATE method) As you can see, we dramatically reduce the number of vertices, and store only 8 top points of the square. Since there is already a vertex, what should the 36-drawn boxes look like? Look at the previous procedure, follow the order of 36 top points, list the appropriate index: Private static readonly short [] indices = { 0, 1, 2, // Front Face 1, 3, 2, // Front Face ····· } In order to facilitate reading, the index is divided into three lines, indicating a triangular triangle. The first triangle uses vertices 0, 1, 2 second uses 1, 3, 2; There is only an index list that is not enough, but also create an index buffer: private indexbuffer ib = null; This object is where it is stored and allows Direct3D to access the index. It is also similar to the method of creating a vertex buffer. Next, the object is initialized, fill the data: IB = New VertexBuffer (TypeOf (Short), INDES.LENGTH, DEVICE, USAGE.WRITEONLY, POOL.DEFAULT; ib.created = new eventhandler (ib_created); OnNDEXBUFFERCREATE (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 parameters, the index buffer constructor is simply in a mold. As mentioned earlier, only 16-bit or 32-bit integers can be used as an index. We subscribe to the event handler and manually call him during the first runtime runtime. Finally, the data is filled with the index. Now, you need to modify the code of the rendered image to use this data. If you still remember, we used a method called "setStreamSource" to tell which fast vertex buffer when you tell DirectX rendering. Similarly, there is such a mechanism for index caches, but it is just a property, because the same time may only use a type of index buffer. After setStreamSource, set the following properties: Device.indices = IB; This Direct3D knows the existence of the vertex buffer, and then modify the drawing code. Currently, our drawing method is trying to draw 12 maps from the vertex, but it will not succeed, because now the vertex buffer only 8 top points. Add a 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.drawIndexedPrimities (PrimitiveType.trianglelist, 0,0,8,0, indices.length / 3); } Here, we change DrawPrimities to DrawIndexedprimities. Let's take a look at the prototype of this method: Public Void DrawIndexedPrimities (PrimitiType PrimitiType, Int Basevertex, Int NumvertExIndex, Int Numvertices, int StartIndex, int primcount); The first parameter is the same as the previous method, indicating the type of the graphical type to be drawn. Parameter basevertex represents the offset of the first vertex index to be used from the index buffer. MINVERTEXINDEX is the smallest vertex index value in these vertices. Obviously, Numvertices refers to the number of vertices to use. StartIndex indicates which position from the array begins to read the vertices. The last parameter is the number of maps to be drawn. Now by the 8 top points in the index buffer, 12 maps of the form factor can be plotted. Next, use the DrawBox method instead of 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); (略, see the source code) Run the program again, you can see the color of a very bright color in the rotation. Each of our vertices has different colors, so true reflects the shortcomings of using the index buffer shared vertex. When multiple map original shared vertices, all vertex data are shared, including colors, normal data, and more. When deciding whether or not to share the vertices, you must determine that shared data does not bring errors on the light or color (because the light is calculated dependent on the normal). It can be seen that the colors of each surface of the cube are calculated from the vertex color interpolation. Use depth buffer (Using Depth Buffer) DePth Buffer (iiically, what is the Z-Buffer or W-Buffer) is Direct3D stores "depth" when rendering ("depth" general finger direction is a window coordinate of the Z-axis pointing from the screen pointing the observer. . Depth information is used to determine an alternative relationship between pixels when rasterization (Note: The degree usually uses the distance to the point of view to the object, so that the pixel with a larger depth value will have a smaller depth value. The pixel is replaced, that is, the nearby object is blocked by the object). So far, our procedures have not used depth buffers, so there is no pixel to be blocked when rasterization. In addition, we haven't even overlap each other, then, now draw some cubes that will overlap with existing cubes. Add the following code after the existing Drawbox method is called: 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 (ANE)); ···(slightly) We added three rotating cubes to the original middle row of cubes. Operating the program, you can see overlapping cubes, but you can't distinguish between the two cube overlapping parts, it is just a common spot. This needs to be processed by depth buffering. Adding a depth buffer is a simple task. Remember that we pass the presentation parameters parameter we pass to the Device constructor? Well, this will be where we add depth buffering. Create a Device containing depth buffering, you need to use two new parameters: Public mircosoft.directx.direct3d.depthformat autodepthstencilformat [get, set] Public Bool Enableautodepthstencil [get, set] Set EnableAutodePthstencil to True You can open the depth buffer for Device, and use DepthFormat to specify AutodePthstencilFormat members. DEPTHFORMAT enumeration, the available value is listed in the table: D 16 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 buy for the Stencil Channel (Stencil Channels Will Be Discussed Later). D24S8 A 32-BIT Z-BUFFER BIT DEPTH USING 24 BITS for Depth Channel D24X8 A 32-BIT Z-BUFFER BIT DEPTH USING 24 BITS for Depth Channel D24X4S4 A 32-BIT Z-BUFFER BIT Depth USING 24 BITS for Depth Channel, with 4 Bits Used for the Stencil Channel, And The Remaining 4 Bits Ignored. D24FS8 A Non-Lockable Format That Contains 24 Points of Depth (As a floating point) and 8 bits for the Stencil Channel. The larger the depth buffer, the more depth data that can be stored, but this is at the expense of performance. Unless you are determined to use a large depth buffer, you can use the smallest value. Most modern graphics cards support the minimum 16-bit depth buffer, SO, add code: Presentparams.autodepthstencilFormat = depthformat.d16; Presentparams.swaPeffect = swapeffect.discard; Perfect, now Device has a depth buffer. Let's see what is different, run the program. Wow, the result is not what we expect, the program is destroyed. What happened to these cubes? Why did the rendering have been destroyed after the depth buffer is added. Oh, the reason is that the depth buffer has never been "cleared", so it has been in an incorrect state. At the same time, the Clear Device is buffered, and the modification code is as follows. Device.clear (Clearflags.target | Clearflags.zbuffer, Color.cornflowerBlue, 1.0F, 0); OK, everything is normal, take a break, enjoy our work, ^ _ ^.