We have successfully created a window last time. If everything goes well, we can see the window we wrote, but it's a bit monotonous. There's nothing left in the green room, now, let's add something to it. Our goal this time is to add a triangle and color it. Well, let's just talk about it. first go to the Code: // ================================================ ===================================================/ /Desc: draw a triangle using the vertex buffer ============================================ ========================================================== ====# include <d3d9. h> // outputs // Desc: global variable // --------------------------------------------------------------------------------- lpdirect3d9 g _ Pd3d = NULL; // direct3d object lpdirect3ddevice9 g_pd3ddevice = NULL; // direct3d device object lpdirect3dvertexbuffer9 g_pvb = NULL; // vertex buffer object // vertex // Desc: vertex structure // vertex struct customvertex {float X, Y, Z, rhw; DWORD color ;};# define d3dfvf_customvertex (d3dfvf_xyz Rhw | d3dfvf_diffuse) // vertex format // vertex // Desc: Initialize direct3d // initialize hresult initd3d (hwnd) {// create a direct3d object, this object is used to create the direct3d device object if (null = (g_pd3d = direct3dcreate9 (d3d_sdk_version) return e_fail; // set the d3dpresent_parameters structure and prepare to create the direct3d device object D3 Dpresent_parameters d3dpp; zeromemory (& d3dpp, sizeof (d3dpp); d3dpp. required wed = true; d3dpp. swapeffect = d3dswapeffect_discard; d3dpp. backbufferformat = success; // create a direct3d device object if (failed (g_pd3d-> createdevice (d3dadapter_default, d3ddevtype_hal, hwnd, hidden, & d3dpp, & g_pd3ddevice) {return e_fail ;} return s_ OK ;}//------------------------------------ ------------------------------------- // Desc: Create and fill the vertex buffer // vertex hresult initvb () {// customvertex vertices [] ={{ 100366f, 400366f, 0.5f, 1.0f, 0xffff0000 ,}, {3000000f, 500000f, 0.5f, 1.0f, 0xff00ff00 ,}, {5000000f, 4000000f, 0.5f, 1.0f, 0xff0000ff ,},}; // create the vertex buffer if (failed (g_pd3ddevice-> createvertexbuffer (3 * sizeof (Cu Stomvertex), 0, d3dfvf_customvertex, d3dpool_default, & g_pvb, null) {return e_fail;} // fill in the vertex buffer void * pvertices; if (failed (g_pvb-> lock (0, sizeof (vertices), (void **) & pvertices, 0) return e_fail; memcpy (pvertices, vertices, sizeof (vertices); g_pvb-> unlock (); Return s_ OK;} // release // Desc: Release the created object //------------ ----------------------------------------------------------------- Void cleanup () {// release the vertex buffer object if (g_pvb! = NULL) g_pvb-> release (); // release the direct3d device object if (g_pd3ddevice! = NULL) g_pd3ddevice-> release (); // release the direct3d object if (g_pd3d! = NULL) g_pd3d-> release ();} // render // Desc: rendering image // define void render () {// clear background buffer g_pd3ddevice-> clear (0, null, d3dclear_target, d3dcolor_xrgb (45, 50,170), 1.0f, 0); // start drawing the image in the background buffer if (succeeded (g_pd3ddevice-> beginscene ())) {// draw the graphic g_pd3ddev in the background Buffer Ice-> setstreamsource (0, g_pvb, 0, sizeof (customvertex); g_pd3ddevice-> setfvf (d3dfvf_customvertex); g_pd3ddevice-> drawprimitive (cost, 0, 1 ); // end drawing graph g_pd3ddevice-> endscene ();} // submit the graph drawn in the background buffer to display g_pd3ddevice-> present (null, null, null, null);} // ----------------------------------------------------------------------------- // Desc: Message Processing //------------------------ Export lresult winapi msgproc (hwnd, uint MSG, wparam, lparam) {Switch (MSG) {Case wm_destroy: cleanup (); postquitmessage (0); Return 0 ;} return defwindowproc (hwnd, MSG, wparam, lparam);} // outputs // Desc: entry function //----------------------------------------- Optional int winapi winmain (hinstance hinst, hinstance, lpstr, INT) {// register window class wndclassex WC = {sizeof (wndclassex), cs_classdc, msgproc, 0l, 0l, getmodulehandle (null), null, l "classname", null}; registerclassex (& WC ); // create the window hwnd = createwindow (L "classname", l "vertex buffer", ws_overlappedwindow, 200,100,600,500, getvertex topwindow (), null, WC. hinst Ance, null); // initialize direct3d if (succeeded (initd3d (hwnd) {// create and fill the vertex buffer if (succeeded (initvb ())) {// display window showwindow (hwnd, sw_showdefault); updatewindow (hwnd); // enter the message loop MSG; zeromemory (& MSG, sizeof (MSG); While (MSG. message! = Wm_quit) {If (peekmessage (& MSG, null, 0u, 0u, pm_remove) {translatemessage (& MSG); dispatchmessage (& MSG);} else {render (); // rendered image }}} unregisterclass (L "classname", WC. hinstance); Return 0;} This is all our code this time: (change the rules this time, first go to the Code, haha) we can see that this time we followed a lot of code from the previous time, we made some modifications on the last framework and added some things we needed this time. This time we will mainly discuss the code changes. The first is to declare the changes to the global volume: lpdirect3dvertexbuffer9 g_pvb = NULL; // The number of vertex buffer objects is of great significance for this triangle and will be explained later. Struct customvertex {float X, Y, Z, rhw; DWORD color ;};# define d3dfvf_customvertex (d3dfvf_xyzrhw | d3dfvf_diffuse) // we define a vertex buffer in the vertex format, this buffer is a highlight of direct3d. It is a buffer in flexible fixed-point format. It allows programmers to define the desired fixed-point format based on their own needs. The format can contain vertex coordinates and colors, attributes such as the normal direction and texture coordinates can be described in the flexible fixed-point format fvf. For example, d3dfvf_xyzrhw | d3dfvf_diffuse indicates that the vertex information includes: the color values of vertex coordinates and diffuse reflection after coordinate transformation. For details about the format of vertex coordinates, see the SDK documentation. Note: # The d3dfvf_customvertex (d3dfvf_xyzrhw | d3dfvf_diffuse) // The d3dfvf_customvertex macro In the vertex format statement will be passed as a parameter to the vertex buffer creation function createvertexbuffer. changes in the winmain function: basically nothing has been changed in this function. The only place to add is if (succeeded (initvb, this statement calls the initvb function. What is this function? This function is the main character of this time. We don't want to draw triangles. This function is used to define the information of triangles. We will discuss this function in detail later. The init3d function remains the same and has not been changed. Next, let's take a look at this major play: initvb function at the beginning of this function: // vertex data customvertex vertices [] ={{ 100366f, 400366f, 0.5f, 1.0f, 0xffff0000 ,}, {3000000f, 500000f, 0.5f, 1.0f, 0xff00ff00 ,}, {5000000f, 4000000f, 0.5f, 1.0f, 0xff0000ff ,},}; vertices [] defines an array of triangle vertices. Each vertex contains the X, Y, Z, rhw, and color of each vertex after coordinate transformation. (X, y, z) is the coordinate values of triangle vertices in the projection matrix, which correspond to the coordinate positions of X, Y, and Z axes and the projection orthogonal coefficient rhw. The following figure shows how to create a triangle. If (failed (g_pd3ddevice-> createvertexbuffer (3 * sizeof (customvertex), 0, d3dfvf_customvertex, d3dpool_default, & g_pvb, null ))) {return e_fail;} is nested outside the if Statement, which is a security detection mechanism and mainly consists of the createvertexbuffer function. The declaration of this function is as follows:
Hresult createvertexbuffer (UintLength,DWORDUsage,DWORDFvf,D3dpoolPool,Idirect3dvertexbuffer9 **Ppvertexbuffer,Handle *Psharedhandle);Length: Specify the buffer size, in bytes. Here we use 3 * sizeof (customvertex), so we multiply it by 3. We all know that, triangle, each triangle element has three Vertex buffers. Usage: Specifies the attributes of the vertex buffer. It can be set to 0 or any combination of the following macros (logical or): d3dusage_autogenmipmap d3dusage_depthstenric d3dusage_d3dusage_dynamic. For details, please refer to the SDK documentation. If you search, you will copy one of the above types to the document and search all of them. Haha. Fvf: the flexible vertex format we created above is used. I am not wrong about it, huh, huh. Pool: Specifies the memory type of the vertex buffer. We use d3dpool_default, which means that the vertex buffer is stored as much as possible. For other parameters, see the SDK documentation. Ppvertexbuffer: The g_pvb that we added at the beginning is used. Now, let's explain what it did. Why? Didn't you see it? I believe you can see that it is not just to store the pointer of the vertex buffer we have created. It is just a pointer and there is nothing mysterious. This is also very important. We have been busy for so long, that is, to get it and use it to draw our triangle, so we also need to protect it. Psharedhandle: it is a reserved parameter and can be set to null. Okay, we get the buffer location in the memory. Let's do something. Let's look at the following code: void * pvertices; If (failed (g_pvb-> lock (0, sizeof (vertices), (void **) & pvertices, 0) return e_fail; memcpy (pvertices, vertices, sizeof (vertices); g_pvb-> unlock (); how do these codes fill the buffer we just obtained? Did not understand? Well, if you do not understand it, it may be that some functions do not understand its role. First, lock and unlock. The two functions are locks and unlock functions. Let's explain the locking functions in detail. The meanings of the four parameters are: (from the past to the next) 1. The revelation address of locking the memory, we use zero, 2. specify the size of the lock memory. We use the size of the vertex we have defined. 3. the pointer we just declared is used to save the memory pointer we want to lock to facilitate operations on this area. 4. It indicates the lock attribute of the vertex buffer. We will take 0. (because it is late today, it is a bit lazy, haha). This function can be used to find the SDK documentation. After we obtain the saved address (pvertices), fill in the memory address (which is basically in the video memory, the memcpy function fills in the quantities of vertex formats that we have just defined into inner (explicit) storage. Then unlock the region. All right, this function is complete. There is nothing mysterious. You can understand it after reading it. Render: There is something in the render function in the remaining functions. I also said before that this function will be constantly added. In this function, several lines of code are added between beginscene and endscene: g_pd3ddevice-> setstreamsource (0, g_pvb, 0, sizeof (customvertex )); g_pd3ddevice-> setfvf (d3dfvf_customvertex); g_pd3ddevice-> drawprimitive (d3dpt_trianglelist, 0, 1); let's take a look at the following sentence: setstreamsource is used to connect the vertex buffer to the rendered data stream. The declaration is as follows:
Hresult setstreamsource (UintStreamnumber,Idirect3dvertexbuffer9 *Pstreamdata,UintOffsetinbytes,UintStride);Streamnumber: the serial number of the rendered data stream linked to the vertex buffer. It is an integer greater than or equal to 0. We use 0 pstreamdata to indicate the buffer address linked to the rendered data stream. Of course we need to render the triangle we just filled in, so we will pass g_pvb in. Offsetinbytes: the starting address of the valid vertex data in the rendered data stream, expressed in bytes. When we lock the memory, the lock starts from 0, so we use 0. (It's Too Late. Alas, there's a power outage. Sorry, I'll come here today and continue tomorrow.) Well, I have a basketball game in the morning, so it's late. Yesterday we saw the setstreamsource function, and another parameter: stride: represents the number of bytes for the difference between two adjacent vertex addresses in the rendering data stream. Generally, it is equal to the number of bytes occupied by the vertex in memory. We use the length of the data type defined by ourselves. The following is the setfvf function. This function declares the flexible vertex format in the current rendering data stream. Needless to say, you can also guess what parameters we want to pass in, of course it is our flexible vertex format: d3dfvf_customvertex. Another function is to render our triangle: drawprimitive. The function is used to draw elements in the rendering data stream of course. The declaration is as follows:
Hresult drawprimitive (D3dprimitivetypePrimitivetype,UintStartvertex,UintPrimitivecount);Primitivetype: indicates the type of the element to be drawn. We draw a triangle, So we enter d3dpt_trianglelist, indicating that we want to draw a triangle element. Other elements are: d3dpt_pointlist. D3dpt_linelist line segment element d3dpt_linestrip line segment strip, representing a group of line segments with uninterrupted points. D3dpt_trianglestrip triangle strip d3dpt_trianglefan triangle fan represents a group of triangles that are slices startvertex: represents the elements that are drawn from the first vertex. Of course we should start from 0th. Peimitivecount: indicates the number of elements to be drawn. We draw a triangle, so we only draw one. The parameter is set to 1. well, well, this program has basically been introduced, and there are not many changes. It's quite simple, right. If there is no compilation error, you will see that there is more triangle than the window of yesterday, and it also has a bit of color. However, it is still ugly. It doesn't matter. It looks like it slowly, next let's take a look at how to draw other elements. First come here. (I finally finished my work yesterday, huh, huh)
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