stage3d的资料实在是太少了。 so~ dreamfairy 决定从directX 入手来学习stage3d. 毕竟彼此是师徒关系,所以API基本都一致,名字也无二。
和stage3d一样,要创建一个cube需要准备 顶点,顶点索引。 贴图还需要创建 Texture.
在directX中。 context3D 是以 IDirect3DDevice9 来存在的。
准备工作有以下几个类.
cube.h 申明了cube的顶点和索引信息,以及 IDirect3DDevice9 的引用
cube.cpp 对Cube进行填充顶点,索引,以及绘制
texCube.cpp 负责具体的渲染循环,包括矩阵,相机,创建贴图等。
vertex.h 顶点坐标类,保存了顶点坐标,以及UV贴图坐标
代码如下:
cube.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include "d3dx9.h" class Cube { public: Cube(IDirect3DDevice9* device); ~Cube(); bool draw(D3DXMATRIX* world, D3DMATERIAL9* mtrl, IDirect3DTexture9* tex); private: IDirect3DDevice9* _device; IDirect3DVertexBuffer9* _vb; IDirect3DIndexBuffer9* _ib; }; |
cube.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #include "cube.h" #include "vertex.h" Cube::Cube(IDirect3DDevice9* device) { _device = device; _device->CreateVertexBuffer( 24 * sizeof(Vertex), D3DUSAGE_WRITEONLY, FVF_VERTEX, D3DPOOL_MANAGED, &_vb, 0); Vertex* v; _vb->Lock(0,0,(void**)&v,0); // fill in the front face vertex data v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); v[1] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f); v[2] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f); v[3] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f); // fill in the back face vertex data v[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); v[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f); v[6] = Vertex( 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); v[7] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); // fill in the top face vertex data v[8] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); v[9] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f); v[10] = Vertex( 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f); v[11] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f); // fill in the bottom face vertex data v[12] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f); v[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f); v[14] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f); v[15] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f); // fill in the left face vertex data v[16] = Vertex(-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f); v[17] = Vertex(-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f); v[18] = Vertex(-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f); v[19] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f); // fill in the right face vertex data v[20] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); v[21] = Vertex( 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); v[22] = Vertex( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f); v[23] = Vertex( 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f); _vb->Unlock(); _device->CreateIndexBuffer( 36 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &_ib, 0); WORD* i = 0; _ib->Lock(0,0,(void**)&i,0); // fill in the front face index data i[0] = 0; i[1] = 1; i[2] = 2; i[3] = 0; i[4] = 2; i[5] = 3; // fill in the back face index data i[6] = 4; i[7] = 5; i[8] = 6; i[9] = 4; i[10] = 6; i[11] = 7; // fill in the top face index data i[12] = 8; i[13] = 9; i[14] = 10; i[15] = 8; i[16] = 10; i[17] = 11; // fill in the bottom face index data i[18] = 12; i[19] = 13; i[20] = 14; i[21] = 12; i[22] = 14; i[23] = 15; // fill in the left face index data i[24] = 16; i[25] = 17; i[26] = 18; i[27] = 16; i[28] = 18; i[29] = 19; // fill in the right face index data i[30] = 20; i[31] = 21; i[32] = 22; i[33] = 20; i[34] = 22; i[35] = 23; _ib->Unlock(); } Cube::~Cube() { if(_vb){_vb->Release();_ib = 0;} if(_ib){_ib->Release();_ib = 0;} }; bool Cube::draw(D3DXMATRIX* world, D3DMATERIAL9* mtrl, IDirect3DTexture9* tex) { if(world) _device->SetTransform(D3DTS_WORLD, world); if(mtrl) _device->SetMaterial(mtrl); if(tex) _device->SetTexture(0,tex); _device->SetStreamSource(0,_vb,0,sizeof(Vertex)); _device->SetIndices(_ib); _device->SetFVF(FVF_VERTEX); _device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12); return true; } |
vertex.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | struct Vertex { Vertex(){} Vertex( float x, float y, float z, float nx, float ny, float nz, float u, float v) { _x = x; _y = y; _z = z; _nx = nx; _ny = ny; _nz = nz; _u = u; _v = v; } float _x,_y,_z; float _nx,_ny,_nz; float _u,_v; }; #define FVF_VERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1) |
texCube.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | #include "d3dUtility.h" #include "cube.h" #include "vertex.h" IDirect3DDevice9* Device = 0; const int Width = 640; const int Height = 480; Cube* Box = 0; IDirect3DTexture9* Tex = 0; bool Setup() { Box = new Cube(Device); D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Ambient = D3DXCOLOR(0.8f,0.8f,0.8f,1.0f); light.Diffuse = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f); light.Specular = D3DXCOLOR(0.2f,0.2f,0.2f,1.0f); light.Direction = D3DXVECTOR3(1.0f,-1.0f,0.0f); Device->SetLight(0,&light); Device->LightEnable(0,true); Device->SetRenderState(D3DRS_NORMALIZENORMALS,true); Device->SetRenderState(D3DRS_SPECULARENABLE,true); //创建材质 D3DXCreateTextureFromFile( Device, "biohazerd.jpg", &Tex); //创建材质过滤 Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); Device->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR); D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI * 0.5f, (float)Width / (float)Height, 1.0f, 1000.0f); Device->SetTransform(D3DTS_PROJECTION,&proj); return true; } void Cleanup() { d3d::Delete<Cube*>(Box); d3d::Release<IDirect3DTexture9*>(Tex); } bool Display(float timeDelta) { if(Device) { static float angle = (3.0f * D3DX_PI) / 2.0f; static float height = 2.0f; D3DXMATRIX roy; static float y = 0.0f; if(y >= 6.28f) y = 0.0f; bool keyDown = false; if(::GetAsyncKeyState(VK_LEFT) & 0x8000f) { angle -= 0.5f * timeDelta; keyDown = true; } if(::GetAsyncKeyState(VK_RIGHT) & 0x8000f) { angle += 0.5f * timeDelta; keyDown = true; } if(::GetAsyncKeyState(VK_UP) & 0x8000f) { height += 5.0f * timeDelta; keyDown = true; } if(::GetAsyncKeyState(VK_DOWN) & 0x8000f) { height -= 5.0f * timeDelta; keyDown = true; } if(!keyDown) { y += timeDelta; D3DXMatrixRotationY(&roy, y); Device->SetTransform(D3DTS_WORLD, &roy); } D3DXVECTOR3 position(cosf(angle) * 3.0f, height, sinf(angle) * 3.0f); D3DXVECTOR3 target(0.0f,0.0f,0.0f); D3DXVECTOR3 up(0.0f,1.0f,0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &position, &target, &up); Device->SetTransform(D3DTS_VIEW, &V); Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff,1.0f,0); Device->BeginScene(); Device->SetMaterial(&d3d::WHITE_MTRL); Device->SetTexture(0,Tex); Box->draw(0,0,0); Device->EndScene(); Device->Present(0,0,0,0); } return true; } LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { if(!d3d::InitD3D(hinstance, Width, Height, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, "InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) { ::MessageBox(0, "Setup() - FAILED", 0, 0); return 0; } d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; } |