ALPHA混合示例

技巧如下:

设置可变顶点格式时增加一个D3DCOLOR类型的漫反射分量,其中的alpha值指定了alpha混合因子。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// The 2D vertex format and descriptor
typedef struct
{
    float  x, y, z;        // 2D coordinates
    float  rhw;            // rhw
    D3DCOLOR diffuse;      // diffuse color component
} VERTEX;

#define  VERTEX_FVF  (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

// initialize vertex data
VERTEX verts[] = {
    { 100.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 0, 64, 128, 255 ) },
    { 300.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 0, 64, 128, 255 ) },
    { 100.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 0, 64, 128, 255 ) },
    { 300.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 0, 64, 128, 255 ) },
    {  50.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 128, 0, 0, 128 )  },
    { 350.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 128, 0, 0, 128 )  },
    {  50.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 128, 0, 0, 128 )  },
    { 350.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA( 128, 0, 0, 128 )  }
};

D3DCOLOR类型可以用 D3DCOLOR_RGBA宏来生成,定义如下:

1
2
3
4
5
//  maps unsigned 8 bits/channel to D3DCOLOR  
#define  D3DCOLOR_ARGB(a,r,g,b) \ 
    ((D3DCOLOR)((((a)&0xff ) << 24 ) | (((r)&0xff ) << 16 ) | (((g)&0xff ) << 8 ) | ((b)&0xff )))

#define  D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b) 

其中的a指定了alpha因子,a为255表示该颜色完全不透明,a为0表示该颜色完全透明。

在绘制的时候,将首先绘制的图形设置为禁用alpha混合模式,将后面绘制的图形设置为启用alpha混合模式,并设置alpha混合具体模式。

1
2
3
4
5
6
7
8
9
// disable alpha blending and draw 2 polygons  
g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
g_d3d_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

// enable alpha blending and draw 2 polygons  
g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_d3d_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);

完整源码如下:

  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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/***************************************************************************************
PURPOSE:
    Alpha blending Demo
Required libraries:
    D3D9.LIB
***************************************************************************************/

#include <windows.h>
#include <stdio.h>
#include "d3d9.h"

#pragma comment(lib, "d3d9.lib")

#define  WINDOW_WIDTH    400
#define  WINDOW_HEIGHT   400

#define  Safe_Release(p) if((p)) (p)->Release();

//  window handles, class and caption text.
HWND        g_hwnd;
HINSTANCE   g_inst;
static   char  g_class_name[] = "AlphaClass";
static   char  g_caption[]    = "Alpha Blending Demo";

// the Direct3D and device object  
IDirect3D9* g_d3d = NULL;
IDirect3DDevice9* g_d3d_device = NULL;

// The 2D vertex format and descriptor
typedef struct
{
    float  x, y, z;        // 2D coordinates
    float  rhw;            // rhw
    D3DCOLOR diffuse;      // diffuse color component
} VERTEX;

#define  VERTEX_FVF   (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

IDirect3DVertexBuffer9 *  g_vertex_buffer = NULL;
IDirect3DTexture9 *       g_texture = NULL;

// --------------------------------------------------------------------------------
//  Window procedure.
// --------------------------------------------------------------------------------
long WINAPI Window_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return (long) DefWindowProc(hwnd, msg, wParam, lParam);
}

// --------------------------------------------------------------------------------
//  Initialize d3d, d3d device, vertex buffer, texutre. 
// --------------------------------------------------------------------------------  
BOOL Do_Init()
{
    D3DPRESENT_PARAMETERS present_param;
    D3DDISPLAYMODE display_mode;
    BYTE *  vertex_ptr;

    // initialize vertex data
    VERTEX verts[] = {
        { 100.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0, 64, 128, 255) },
        { 300.0f, 100.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0, 64, 128, 255) },
        { 100.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0, 64, 128, 255) },
        { 300.0f, 300.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(0, 64, 128, 255) },
        {  50.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128, 0, 0, 128)  },
        { 350.0f, 150.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128, 0, 0, 128)  },
        {  50.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128, 0, 0, 128)  },
        { 350.0f, 350.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(128, 0, 0, 128)  }
    }; 

    // do a windowed mode initialization of Direct3D
    if ((g_d3d = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
        return FALSE;

    // retrieves the current display mode of the adapter
    if (FAILED(g_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &display_mode)))
        return FALSE;

    ZeroMemory(&present_param, sizeof (present_param));

    // initialize d3d presentation parameter
    present_param.Windowed           = TRUE;
    present_param.SwapEffect         = D3DSWAPEFFECT_DISCARD;
    present_param.BackBufferFormat   = display_mode.Format;

    // creates a device to represent the display adapter  
    if (FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hwnd,
                                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_param, &g_d3d_device)))
        return  FALSE;

    // create the vertex buffer and set data  
    g_d3d_device->CreateVertexBuffer(sizeof(VERTEX) * 8, 0, VERTEX_FVF, D3DPOOL_DEFAULT, &g_vertex_buffer, NULL);

    // locks a range of vertex data and obtains a pointer to the vertex buffer memory  
    g_vertex_buffer->Lock(0, 0, (void **)&vertex_ptr,  0);

    memcpy(vertex_ptr, verts,  sizeof (verts));

    // unlocks vertex data  
    g_vertex_buffer->Unlock();

    return TRUE;
}

// --------------------------------------------------------------------------------
//  Release all d3d resource.
// --------------------------------------------------------------------------------
BOOL Do_Shutdown()
{
    Safe_Release(g_vertex_buffer);
    Safe_Release(g_d3d_device);
    Safe_Release(g_d3d);

    return  TRUE;
}

// --------------------------------------------------------------------------------
//  Render a frame.
// --------------------------------------------------------------------------------
BOOL Do_Frame()
{
    // clear device back buffer
    g_d3d_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 1.0f, 0);

    // Begin scene
    if (SUCCEEDED(g_d3d_device->BeginScene()))
    {
        // set the vertex stream, shader, and texture.

        // binds a vertex buffer to a device data stream
        g_d3d_device->SetStreamSource( 0, g_vertex_buffer, 0, sizeof (VERTEX));

        // set the current vertex stream declation
        g_d3d_device->SetFVF(VERTEX_FVF);

        // assigns a texture to a stage for a device
        g_d3d_device->SetTexture( 0, g_texture);

        // disable alpha blending and draw 2 polygons
        g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
        g_d3d_device->DrawPrimitive(D3DPT_TRIANGLESTRIP,  0,  2);

        // enable alpha blending and draw 2 polygons
        g_d3d_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        g_d3d_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        g_d3d_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
        g_d3d_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);

        // end the scene
        g_d3d_device->EndScene();
    }

    // present the contents of the next buffer in the sequence of back buffers owned by the device
    g_d3d_device->Present(NULL, NULL, NULL, NULL);

     return  TRUE;
}

// --------------------------------------------------------------------------------
//  Main function, routine entry.
// --------------------------------------------------------------------------------
int  WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{
    WNDCLASSEX  win_class;
    MSG         msg;

    g_inst  =  inst;

    // create window class and register it
    win_class.cbSize         = sizeof (win_class);
    win_class.style          = CS_CLASSDC;
    win_class.lpfnWndProc    = Window_Proc;
    win_class.cbClsExtra     = 0;
    win_class.cbWndExtra     = 0;
    win_class.hInstance      = inst;
    win_class.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
    win_class.hCursor        = LoadCursor(NULL, IDC_ARROW);
    win_class.hbrBackground  = NULL;
    win_class.lpszMenuName   = NULL;
    win_class.lpszClassName  = g_class_name;
    win_class.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

    if (! RegisterClassEx(&win_class))
        return  FALSE;

    // create the main window  
    g_hwnd = CreateWindow(g_class_name, g_caption, WS_CAPTION  |  WS_SYSMENU, 0, 0,
                        WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, inst, NULL);

    if (g_hwnd == NULL)
        return  FALSE;

    ShowWindow(g_hwnd, SW_NORMAL);
    UpdateWindow(g_hwnd);

    // initialize game
    if (Do_Init() == FALSE)
        return  FALSE;

    // start message pump, waiting for signal to quit.
    ZeroMemory(&msg, sizeof (MSG));

    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        // draw a frame
        if (Do_Frame() == FALSE)
            break ;
    }

    // run shutdown function
    Do_Shutdown();

    UnregisterClass(g_class_name, inst);
    
    return  (int) msg.wParam;
}

r_alpha.jpg