03. Initializing Direct3D 11

全局变量

IDXGISwapChain* SwapChain; ID3D11Device* d3d11Device; ID3D11DeviceContext* d3d11DevCon; ID3D11RenderTargetView* renderTargetView; float red = 0.0f; float green = 0.0f; float blue = 0.0f; int colormodr = 1; int colormodg = 1; int colormodb = 1;

函数原型
bool InitializeDirect3d11App(HINSTANCE hInstance);
void ReleaseObjects();
bool InitScene();
void UpdateScene();
void DrawScene();
if(!InitializeDirect3d11App(hInstance))    //Initialize Direct3D
{
    MessageBox(0, L"Direct3D Initialization - Failed",
        L"Error", MB_OK);
    return 0;
}

if(!InitScene())    //Initialize our scene
{
    MessageBox(0, L"Scene Initialization - Failed",
        L"Error", MB_OK);
    return 0;
}

messageloop();

ReleaseObjects();    

 

 

Initializing Direct3D 11初始化dx11

 1 bool InitializeDirect3dApp(HINSTANCE hInstance)
 2 {
 3 HRESULT hr;
 4 
 5 //Describe our Buffer
 6 DXGI_MODE_DESC bufferDesc;
 7 
 8 ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
 9 
10 bufferDesc.Width = Width;
11 bufferDesc.Height = Height;
12 bufferDesc.RefreshRate.Numerator = 60;
13 bufferDesc.RefreshRate.Denominator = 1;
14 bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
15 bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
16 bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
17 
18 //Describe our SwapChain
19 DXGI_SWAP_CHAIN_DESC swapChainDesc; 
20     
21 ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
22 
23 swapChainDesc.BufferDesc = bufferDesc;
24 swapChainDesc.SampleDesc.Count = 1;
25 swapChainDesc.SampleDesc.Quality = 0;
26 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
27 swapChainDesc.BufferCount = 1;
28 swapChainDesc.OutputWindow = hwnd; 
29 swapChainDesc.Windowed = TRUE; 
30 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
31 
32 
33 //Create our SwapChain
34 hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
35     D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
36 
37 //Create our BackBuffer
38 ID3D11Texture2D* BackBuffer;
39 hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
40 
41 //Create our Render Target
42 hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
43 BackBuffer->Release();
44 
45 //Set our Render Target
46 d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
47 
48 return true;
49 }

Describing the BackBuffer( DXGI_MODE_DESC )

typedef struct DXGI_MODE_DESC {
  UINT                     Width;//宽度
  UINT                     Height;//高度
  DXGI_RATIONAL            RefreshRate;//刷新率 设为60HZ
  DXGI_FORMAT              Format;//显示方式 rgba每个8bit 一共32bit
  DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;//渲染方式 不指定 双缓冲无所谓
  DXGI_MODE_SCALING        Scaling;//缩放 不指定
} DXGI_MODE_DESC, *LPDXGI_MODE_DESC;
DXGI_MODE_DESC bufferDesc;

ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));

bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;//渲染方式不指定
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;//缩放不指定

Describing the SwapChain( DXGI_MODE_DESC )

typedef struct DXGI_SWAP_CHAIN_DESC {
  DXGI_MODE_DESC   BufferDesc;// 上述的backbuffer
  DXGI_SAMPLE_DESC SampleDesc;//采样方式
  DXGI_USAGE       BufferUsage;//
  UINT             BufferCount;//缓冲区数量 1:双缓冲 2:三缓冲
  HWND             OutputWindow;//我们自己的输出窗口
  BOOL             Windowed;//是否窗口化
  DXGI_SWAP_EFFECT SwapEffect;//cpu访问后台缓冲区的方式
  UINT             Flags;//额外的标志
} DXGI_SWAP_CHAIN_DESC;
DXGI_SWAP_CHAIN_DESC swapChainDesc; 
    
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));

swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;//每个像素多重采样的数量
swapChainDesc.SampleDesc.Quality = 0;//质量
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hwnd; 
swapChainDesc.Windowed = TRUE; 
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

 

Creating the Device and SwapChain( D3D11CreateDeviceAndSwapChain() )


HRESULT D3D11CreateDeviceAndSwapChain(
  __in   IDXGIAdapter *pAdapter,//我们使用的adapter NULL使用默认的
  __in   D3D_DRIVER_TYPE DriverType,//direct3d要怎么实现 D3D_DRIVER_TYPE_HARDWARE将由gpu来实现
  __in   HMODULE Software,//软件栅格化的句柄 NULL
  __in   UINT Flags,//NULL
  __in   const D3D_FEATURE_LEVEL *pFeatureLevels,//NULL 使用最好的
  __in   UINT FeatureLevels,//NULL
  __in   UINT SDKVersion,//D3D11_SDK_VERSION
  __in   const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,//刚创建的交换链
  __out  IDXGISwapChain **ppSwapChain,//接收我们刚创建的交换链
  __out  ID3D11Device **ppDevice,//device
  __out  D3D_FEATURE_LEVEL *pFeatureLevel,//D3D_FEATURE_LEVEL 最高的
  __out  ID3D11DeviceContext **ppImmediateContext//device context
);
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
    D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);

Creating the BackBuffer( GetBuffer() )

HRESULT GetBuffer(
  [in]       UINT Buffer,//0
  [in]       REFIID riid,//ID3D11Texture2D 改变后缓冲区的借口类型的引用id
  [in, out]  void **ppSurface//backbuffer
);
ID3D11Texture2D* BackBuffer;
hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );

Creating the Render Target( ID3D11Device::CreateRenderTargetView() ) and release backbuffer

HRESULT CreateRenderTargetView(
  [in]   ID3D11Resource *pResource,//Back buffer
  [in]   const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,//设null创建一个视图来访问mipmap为0的所有子资源
  [out]  ID3D11RenderTargetView **ppRTView//rendertarget

hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
BackBuffer->Release();

Set the Render Targets( ID3D11DeviceContext::OMSetRenderTargets() )

void OMSetRenderTargets(
  [in]  UINT NumViews,//需要绑定的View 数目 我们只有一个
  [in]  ID3D11RenderTargetView *const **ppRenderTargetViews,//需要绑定的view
  [in]  ID3D11DepthStencilView *pDepthStencilView//深度模板 没有设NULL
);

Clean Up

释放所有我们创建的com objects

void ReleaseObjects()
{
    //Release the COM Objects we created
    SwapChain->Release();
    d3d11Device->Release();
    d3dDevCon->Release();
}

 

Initialize Scene

初始化场景
bool InitScene()
{

    return true;
}

Update Scene

更新场景,如改变objects 位置,改变值,场景内的任何改变,本节只改变背景颜色

 1 void UpdateScene()
 2 {
 3     //Update the colors of our scene
 4     red += colormodr * 0.00005f;
 5     green += colormodg * 0.00002f;
 6     blue += colormodb * 0.00001f;
 7 
 8     if(red >= 1.0f || red <= 0.0f)
 9         colormodr *= -1;
10     if(green >= 1.0f || green <= 0.0f)
11         colormodg *= -1;
12     if(blue >= 1.0f || blue <= 0.0f)
13         colormodb *= -1;
14 }

Render Scene

DrawScene() render 我们的场景,该函数只渲染场景不更新场景 交换前后缓冲区,掉present会将back buffer 渲染到屏幕

 1 void DrawScene()
 2 {
 3     //Clear our backbuffer to the updated color
 4     D3DXCOLOR bgColor( red, green, blue, 1.0f );
 5 
 6     d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);
 7 
 8     //Present the backbuffer to the screen 
 9     SwapChain->Present(0, 0);
10 }

messageloop()方法,先调用UpdateScene() 更新场景,然后然后掉DrawScene()把backbuffer渲染到屏幕

 1 int messageloop(){
 2 MSG msg;
 3 ZeroMemory(&msg, sizeof(MSG));
 4 while(true)
 5 {
 6     BOOL PeekMessageL( 
 7         LPMSG lpMsg,
 8         HWND hWnd,
 9         UINT wMsgFilterMin,
10         UINT wMsgFilterMax,
11         UINT wRemoveMsg
12         );
13 
14     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
15     {
16         if (msg.message == WM_QUIT)
17             break;
18         TranslateMessage(&msg);    
19         DispatchMessage(&msg);
20     }
21     else{
22 ///////////////**************new**************////////////////////
23         // run game code
24         
25         UpdateScene();
26         DrawScene();
27         
28 ///////////////**************new**************////////////////////
29     }
30 }
31 return msg.wParam;
32 }

 

Error Checking: 

DXGetErrorDescription 

需添加#include <DXErr.h>和
DXErr.lib
 1 #pragma comment (lib, "DXErr.lib")
 2 #include <DXErr.h>
 3 
 4 ...
 5 
 6 bool InitializeDirect3d11App(HINSTANCE hInstance)
 7 {
 8     HRESULT hr;
 9 
10     //Describe our Buffer
11     DXGI_MODE_DESC bufferDesc;
12 
13     ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
14 
15     bufferDesc.Width = Width;
16     bufferDesc.Height = Height;
17     bufferDesc.RefreshRate.Numerator = 60;
18     bufferDesc.RefreshRate.Denominator = 1;
19     bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
20     bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
21     bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
22     
23     //Describe our SwapChain
24     DXGI_SWAP_CHAIN_DESC swapChainDesc; 
25         
26     ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
27 
28     swapChainDesc.BufferDesc = bufferDesc;
29     swapChainDesc.SampleDesc.Count = 1;
30     swapChainDesc.SampleDesc.Quality = 0;
31     swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
32     swapChainDesc.BufferCount = 1;
33     swapChainDesc.OutputWindow = hwnd; 
34     swapChainDesc.Windowed = TRUE; 
35     swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
36 
37 
38     //Create our SwapChain
39     hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
40         D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
41     if(FAILED(hr))
42     {    
43         MessageBox(NULL, DXGetErrorDescription(hr),
44             TEXT(" D3D11CreateDeviceAndSwapChain"), MB_OK);    
45         return 0;    
46     }    
47 
48     //Create our BackBuffer
49     ID3D11Texture2D* BackBuffer;
50     hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
51     if(FAILED(hr))
52     {    
53         MessageBox(NULL, DXGetErrorDescription(hr),
54             TEXT("SwapChain->GetBuffer"), MB_OK);    
55         return 0;    
56     }    
57 
58     //Create our Render Target
59     hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
60     BackBuffer->Release();
61     if(FAILED(hr))
62     {    
63         MessageBox(NULL, DXGetErrorDescription(hr),
64             TEXT("d3d11Device->CreateRenderTargetView"), MB_OK);    
65         return 0;    
66     }    
67 
68     //Set our Render Target
69     d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
70 
71     return true;
72 }

 

  1 ///////////////**************new**************////////////////////
  2 
  3 #include <windows.h>
  4 #include <d3d11.h>
  5 #include <d3dx11.h>
  6 #include <d3dx10.h>
  7 #include <xnamath.h>
  8 
  9 //Global Declarations//
 10 IDXGISwapChain* SwapChain;
 11 ID3D11Device* d3d11Device;
 12 ID3D11DeviceContext* d3d11DevCon;
 13 ID3D11RenderTargetView* renderTargetView;
 14 
 15 float red = 0.0f;
 16 float green = 0.0f;
 17 float blue = 0.0f;
 18 int colormodr = 1;
 19 int colormodg = 1;
 20 int colormodb = 1;
 21 
 22 ///////////////**************new**************////////////////////
 23 
 24 LPCTSTR WndClassName = L"firstwindow";
 25 HWND hwnd = NULL;
 26 
 27 const int Width  = 300;
 28 const int Height = 300;
 29 
 30 ///////////////**************new**************////////////////////
 31 
 32 //Function Prototypes//
 33 bool InitializeDirect3d11App(HINSTANCE hInstance);
 34 void ReleaseObjects();
 35 bool InitScene();
 36 void UpdateScene();
 37 void DrawScene();
 38 
 39 ///////////////**************new**************////////////////////
 40 
 41 bool InitializeWindow(HINSTANCE hInstance,
 42                       int ShowWnd,
 43                       int width, int height,
 44                       bool windowed);
 45 int messageloop();
 46 
 47 LRESULT CALLBACK WndProc(HWND hWnd,
 48                          UINT msg,
 49                          WPARAM wParam,
 50                          LPARAM lParam);
 51 
 52 
 53 int WINAPI WinMain(HINSTANCE hInstance,    //Main windows function
 54                    HINSTANCE hPrevInstance, 
 55                    LPSTR lpCmdLine,
 56                    int nShowCmd)
 57 {
 58 
 59     if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
 60     {
 61         MessageBox(0, L"Window Initialization - Failed",
 62             L"Error", MB_OK);
 63         return 0;
 64     }
 65 
 66     ///////////////**************new**************////////////////////
 67 
 68     if(!InitializeDirect3d11App(hInstance))    //Initialize Direct3D
 69     {
 70         MessageBox(0, L"Direct3D Initialization - Failed",
 71             L"Error", MB_OK);
 72         return 0;
 73     }
 74 
 75     if(!InitScene())    //Initialize our scene
 76     {
 77         MessageBox(0, L"Scene Initialization - Failed",
 78             L"Error", MB_OK);
 79         return 0;
 80     }
 81 
 82     messageloop();
 83 
 84     ReleaseObjects();
 85 
 86     ///////////////**************new**************////////////////////
 87 
 88     return 0;
 89 }
 90 
 91 bool InitializeWindow(HINSTANCE hInstance,
 92                       int ShowWnd,
 93                       int width, int height,
 94                       bool windowed)
 95 {
 96     typedef struct _WNDCLASS {
 97         UINT cbSize;
 98         UINT style;
 99         WNDPROC lpfnWndProc;
100         int cbClsExtra;
101         int cbWndExtra;
102         HANDLE hInstance;
103         HICON hIcon;
104         HCURSOR hCursor;
105         HBRUSH hbrBackground;
106         LPCTSTR lpszMenuName;
107         LPCTSTR lpszClassName;
108     } WNDCLASS;
109 
110     WNDCLASSEX wc;
111 
112     wc.cbSize = sizeof(WNDCLASSEX);
113     wc.style = CS_HREDRAW | CS_VREDRAW;
114     wc.lpfnWndProc = WndProc;
115     wc.cbClsExtra = NULL;
116     wc.cbWndExtra = NULL;
117     wc.hInstance = hInstance;
118     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
119     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
120     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
121     wc.lpszMenuName = NULL;
122     wc.lpszClassName = WndClassName;
123     wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
124 
125     if (!RegisterClassEx(&wc))
126     {
127         MessageBox(NULL, L"Error registering class",    
128             L"Error", MB_OK | MB_ICONERROR);
129         return 1;
130     }
131 
132     hwnd = CreateWindowEx(
133         NULL,
134         WndClassName,
135         L"Window Title",
136         WS_OVERLAPPEDWINDOW,
137         CW_USEDEFAULT, CW_USEDEFAULT,
138         width, height,
139         NULL,
140         NULL,
141         hInstance,
142         NULL
143         );
144 
145     if (!hwnd)
146     {
147         MessageBox(NULL, L"Error creating window",
148             L"Error", MB_OK | MB_ICONERROR);
149         return 1;
150     }
151 
152     ShowWindow(hwnd, ShowWnd);
153     UpdateWindow(hwnd);
154 
155     return true;
156 }
157 
158 ///////////////**************new**************////////////////////
159 
160 bool InitializeDirect3d11App(HINSTANCE hInstance)
161 {
162     //Describe our Buffer
163     DXGI_MODE_DESC bufferDesc;
164 
165     ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
166 
167     bufferDesc.Width = Width;
168     bufferDesc.Height = Height;
169     bufferDesc.RefreshRate.Numerator = 60;
170     bufferDesc.RefreshRate.Denominator = 1;
171     bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
172     bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
173     bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
174 
175     //Describe our SwapChain
176     DXGI_SWAP_CHAIN_DESC swapChainDesc; 
177 
178     ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
179 
180     swapChainDesc.BufferDesc = bufferDesc;
181     swapChainDesc.SampleDesc.Count = 1;
182     swapChainDesc.SampleDesc.Quality = 0;
183     swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
184     swapChainDesc.BufferCount = 1;
185     swapChainDesc.OutputWindow = hwnd; 
186     swapChainDesc.Windowed = TRUE; 
187     swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
188 
189 
190     //Create our SwapChain
191     D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
192         D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
193 
194     //Create our BackBuffer
195     ID3D11Texture2D* BackBuffer;
196     SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
197 
198     //Create our Render Target
199     d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
200     BackBuffer->Release();
201 
202     //Set our Render Target
203     d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
204 
205     return true;
206 }
207 
208 void ReleaseObjects()
209 {
210     //Release the COM Objects we created
211     SwapChain->Release();
212     d3d11Device->Release();
213     d3d11DevCon->Release();
214 }
215 bool InitScene()
216 {
217 
218     return true;
219 }
220 
221 void UpdateScene()
222 {
223     //Update the colors of our scene
224     red += colormodr * 0.00005f;
225     green += colormodg * 0.00002f;
226     blue += colormodb * 0.00001f;
227 
228     if(red >= 1.0f || red <= 0.0f)
229         colormodr *= -1;
230     if(green >= 1.0f || green <= 0.0f)
231         colormodg *= -1;
232     if(blue >= 1.0f || blue <= 0.0f)
233         colormodb *= -1;
234 }
235 
236 void DrawScene()
237 {
238     //Clear our backbuffer to the updated color
239     D3DXCOLOR bgColor( red, green, blue, 1.0f );
240 
241     d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);
242 
243     //Present the backbuffer to the screen
244     SwapChain->Present(0, 0);
245 }
246 
247 ///////////////**************new**************////////////////////
248 
249 int messageloop(){
250     MSG msg;
251     ZeroMemory(&msg, sizeof(MSG));
252     while(true)
253     {
254         BOOL PeekMessageL( 
255             LPMSG lpMsg,
256             HWND hWnd,
257             UINT wMsgFilterMin,
258             UINT wMsgFilterMax,
259             UINT wRemoveMsg
260             );
261 
262         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
263         {
264             if (msg.message == WM_QUIT)
265                 break;
266             TranslateMessage(&msg);    
267             DispatchMessage(&msg);
268         }
269         else{
270             ///////////////**************new**************////////////////////
271             // run game code
272 
273             UpdateScene();
274             DrawScene();
275 
276             ///////////////**************new**************////////////////////
277         }
278     }
279     return msg.wParam;
280 }
281 
282 LRESULT CALLBACK WndProc(HWND hwnd,
283                          UINT msg,
284                          WPARAM wParam,
285                          LPARAM lParam)
286 {
287     switch( msg )
288     {
289     case WM_KEYDOWN:
290         if( wParam == VK_ESCAPE ){
291             DestroyWindow(hwnd);
292         }
293         return 0;
294 
295     case WM_DESTROY:
296         PostQuitMessage(0);
297         return 0;
298     }
299     return DefWindowProc(hwnd,
300         msg,
301         wParam,
302         lParam);
303 }

 





 

 

 

 

工程设置如下:

 

 

 

 

















 

posted @ 2017-12-21 21:58  YinaPan  阅读(726)  评论(0编辑  收藏  举报