新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 深度测试与alpha混合 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 17824 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 深度测试与alpha混合 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 深度测试与alpha混合

    在绘制复杂的三维场景时,不可避免地会出现物体间的相互遮挡,在这种情况下,为了正确地绘制场景需要使用深度测试。半透明物体的绘制不同于不透明物体,Direct3D通过alpha混合实现半透明物体的绘制。深度测试可以简化复杂场景的绘制,alpha混合可以使绘制的三维场景更完整、更逼真。

    在复杂的场景中,通常有多个物体需要绘制,这些物体之间通常会存在遮挡关系,离观察点较远的物体会因为近处物体的者的遮挡而不可见或只有部分可见,Direct3D图形系统提供了深度测试功能来实现这种效果。

    深度缓冲区与深度测试

    要理解深度测试,首先需要理解深度缓冲区。深度缓冲区是Direct3D用来存储绘制到屏幕上的每个像素点的深度信息的一块内存缓冲区。当Direct3D将一个场景渲染到目标表面上时,它使用深度缓冲区来决定光栅化后各个多边形的像素的前后遮挡关系,最终决定哪个颜色值被绘制出来。也就是说,Direct3D通过比较当前绘制的像素点的深度和对应深度缓冲区的点的深度值来决定是否绘制当前像素。如果深度测试结果为TRUE,则绘制当前像素,并用当前像素点的深度来更新深度缓冲区,反之则不予绘制。通常情况下,深度缓冲区对应于屏幕大小的一块二维区域。

    对一个启用了深度缓冲区的场景进行光栅化操作时,渲染表面上的每个点都要进行深度测试。在深度测试开始时,深度缓冲区的深度值被设置为该场景可能出现的最大值,渲染表面上的颜色值被设置为背景颜色值。然后测试场景内即将绘制的每个多边形,看它是否小于存储在深度缓冲区中的深度值,如果该多边形的深度值更小,则该深度值被更新到深度缓冲区中,并将渲染表面上当前点的颜色值替换为该多边形的颜色。如果多边形在这一点的深度值更大,将继续测试列表中的下一个多边形。

    创建深度缓冲区

    若要在Direct3D图形程序中应用深度测试,首先必须在创建Direct3D渲染设备时创建深度缓冲区,示例代码如下:

    D3DPRESENT_PARAMETERS d3dpp;ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed   = TRUE;d3dpp.SwapEffect   = D3DSWAPEFFECT_DISCARD;d3dpp.BackBufferFormat  = D3DFMT_UNKNOWN;d3dpp.EnableAutoDepthStencil = TRUE;                   // 表示由Direct3D创建并管理一个深度缓冲区d3dpp.AutoDepthStencilFormat = D3DFMT_D16;     // 表示深度缓冲区中每一个像素的深度值由16位的二进制数表示
    if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,          &d3dpp, &g_device))){ return false;}

    激活深度测试

    深度缓冲区随Direct3D渲染设备创建好后,调用Direct3D渲染状态设置函数IDirect3DDevice9::SetRenderState(),将第一个参数设为D3DRS_ZENABLE,第二个参数设为TRUE,激活深度测试:

    g_device->SetRenderState(D3DRS_ZENABLE,   TRUE);

    设置深度测试函数

    接下来依然调用IDirect3DDevice9::SetRenderState()函数设置深度测试函数,第一个参数设置为D3DRS_ZFUNC:

    D3DRS_ZFUNC
    One member of the D3DCMPFUNC enumerated type. The default value is D3DCMP_LESSEQUAL. This member enables an application to accept or reject a pixel, based on its distance from the camera.
    The depth value of the pixel is compared with the depth-buffer value. If the depth value of the pixel passes the comparison function, the pixel is written.

    The depth value is written to the depth buffer only if the render state is TRUE.

    Software rasterizers and many hardware accelerators work faster if the depth test fails, because there is no need to filter and modulate the texture if the pixel is not going to be rendered.

    第二个参数设置为想要设置的深度测试函数,它属于D3DCMPFUNC枚举类型,定义如下:

    Defines the supported compare functions.

    typedef enum D3DCMPFUNC{    D3DCMP_NEVER = 1,    D3DCMP_LESS = 2,    D3DCMP_EQUAL = 3,    D3DCMP_LESSEQUAL = 4,    D3DCMP_GREATER = 5,    D3DCMP_NOTEQUAL = 6,    D3DCMP_GREATEREQUAL = 7,    D3DCMP_ALWAYS = 8,    D3DCMP_FORCE_DWORD = 0x7fffffff,} D3DCMPFUNC, *LPD3DCMPFUNC;
    Constants
    D3DCMP_NEVER
    Always fail the test.
    D3DCMP_LESS
    Accept the new pixel if its value is less than the value of the current pixel.
    D3DCMP_EQUAL
    Accept the new pixel if its value equals the value of the current pixel.
    D3DCMP_LESSEQUAL
    Accept the new pixel if its value is less than or equal to the value of the current pixel.
    D3DCMP_GREATER
    Accept the new pixel if its value is greater than the value of the current pixel.
    D3DCMP_NOTEQUAL
    Accept the new pixel if its value does not equal the value of the current pixel.
    D3DCMP_GREATEREQUAL
    Accept the new pixel if its value is greater than or equal to the value of the current pixel.
    D3DCMP_ALWAYS
    Always pass the test.
    D3DCMP_FORCE_DWORD
    Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.
    Remarks
    The values in this enumerated type define the supported compare functions for the D3DRS_ZFUNC, D3DRS_ALPHAFUNC, and D3DRS_STENCILFUNC render states.

    通常情况下,深度测试函数设置为D3DCMP_LESS,表示当测试点深度值小于深度缓冲区中相应值时,通过深度测试并绘制相关像素,这样没有被遮挡的物体才显示,而被遮挡的物体就不显示。示例代码如下:

    g_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);

    更新深度缓冲区

    设置了深度测试函数后,还需要设置深度测试成功时对深度缓冲区如何操作,是保持原来的深度值,还是用当前像素的深度值更新对应的数值。

    D3DRS_ZWRITEENABLE
    TRUE to enable the application to write to the depth buffer. The default value is TRUE. This member enables an application to prevent the system from updating the depth buffer with new depth values. If FALSE, depth comparisons are still made according to the render state D3DRS_ZFUNC, assuming that depth buffering is taking place, but depth values are not written to the buffer.
    示例代码如下:

    g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

    表示如果通过测试,则用当前像素的深度值更新深度缓冲区中对应的数值,这是最常用的设置,也是默认设置。


    [此贴子已经被作者于2009-4-27 10:25:07编辑过]

       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/3/9 9:56:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    示例程序

    该示例程序绘制了一个矩形和一个坦克模型,其中先绘制矩形,再绘制坦克模型,而且坦克模型在矩形的后面被遮挡住。如果按下"1"键,则禁用深度测试,这时坦克虽然被矩形遮挡住,但仍然被绘制出来了;如果按下"2"键,则启用深度测试,这时坦克模型被矩形遮挡住,没有绘制出来。

    按此在新窗口浏览图片

    按下数字键"1",禁用深度测试,被矩形部分遮住的坦克被绘制出来。

    按此在新窗口浏览图片

    按下数字键"2",启用深度测试,被矩形部分遮住的坦克没有被绘制出来。

    源程序:

    #include <d3dx9.h>

    #pragma warning(disable : 4127)

    #define CLASS_NAME    "GameApp"

    #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

    IDirect3D9*                g_d3d;
    IDirect3DDevice9*        g_device;

    ID3DXMesh*                g_mesh;
    D3DMATERIAL9*            g_mesh_materials;
    IDirect3DTexture9**        g_mesh_textures;
    DWORD                    g_num_materials;
    IDirect3DVertexBuffer9* g_shutter_vb;

    D3DXMATRIX                g_mat_tank;
    D3DXMATRIX                g_mat_shutter;

    struct sCustomVertex
    {   
        float x, y, z;   
        DWORD color;     
    };

    #define D3DFVF_CUSTOM_VERTEX   (D3DFVF_XYZ | D3DFVF_DIFFUSE)

    void setup_matrices()
    {
        // setup world matrix
        D3DXMATRIX mat_world;
        D3DXMatrixIdentity(&mat_world);
        g_device->SetTransform(D3DTS_WORLD, &mat_world);

        // setup view matrix

        D3DXVECTOR3 eye(0.0f, 2.0f, -30.0f);
        D3DXVECTOR3 at(0.0f,  2.0f,   0.0f);
        D3DXVECTOR3 up(0.0f,  1.0f,   0.0f);

        D3DXMATRIX mat_view;
        D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
        g_device->SetTransform(D3DTS_VIEW, &mat_view);

        // setup projection matrix
        D3DXMATRIX mat_proj;
        D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);
        g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
    }

    bool init_geometry()
    {
        ID3DXBuffer* material_buffer;

        /*
         D3DXLoadMeshFromXA(
            LPCSTR pFilename,
            DWORD Options,
            LPDIRECT3DDEVICE9 pD3DDevice,
            LPD3DXBUFFER *ppAdjacency,
            LPD3DXBUFFER *ppMaterials,
            LPD3DXBUFFER *ppEffectInstances,
            DWORD *pNumMaterials,
            LPD3DXMESH *ppMesh);
        */

        if(FAILED(D3DXLoadMeshFromX("tank.x", D3DXMESH_SYSTEMMEM, g_device, NULL, &material_buffer, NULL,
                                    &g_num_materials, &g_mesh)))
        {
            MessageBox(NULL, "Could not find tank.x", "ERROR", MB_OK);
            return false;
        }

        D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();

        g_mesh_materials = new D3DMATERIAL9[g_num_materials];
        g_mesh_textures     = new IDirect3DTexture9*[g_num_materials];

        for(DWORD i = 0; i < g_num_materials; i++)
        {
            g_mesh_materials[i] = xmaterials[i].MatD3D;

            // set ambient reflected coefficient, because .x file do not set it.
            g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse;

            g_mesh_textures[i] = NULL;

            if(xmaterials[i].pTextureFilename != NULL && strlen(xmaterials[i].pTextureFilename) > 0)    
                D3DXCreateTextureFromFile(g_device, xmaterials[i].pTextureFilename, &g_mesh_textures[i]);    
        }

        material_buffer->Release();

        // create shutter vertex buffer

        sCustomVertex vertices[] =
        {
            { -8,   -2,  -10.0f,   0xFFFFFF00},     
            { -8,    6,  -10.0f,   0xFFFFFF00},    
            {  8,   -2,  -10.0f,   0xFFFFFF00},    
            {  8,    6,  -10.0f,   0xFFFFFF00}
        };

        g_device->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &g_shutter_vb, NULL);
        
        void* ptr;
        g_shutter_vb->Lock(0, sizeof(vertices),  &ptr, 0);
        memcpy(ptr, vertices, sizeof(vertices));
        g_shutter_vb->Unlock();

        return true;
    }

    bool init_d3d(HWND hwnd)
    {
        g_d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if(g_d3d == NULL)
            return false;

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));

        d3dpp.Windowed                    = TRUE;
        d3dpp.SwapEffect                = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat            = D3DFMT_UNKNOWN;
        d3dpp.EnableAutoDepthStencil    = TRUE;
        d3dpp.AutoDepthStencilFormat    = D3DFMT_D16;

        if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_device)))
        {
            return false;
        }
        
        if(! init_geometry())
            return false;

        setup_matrices();    

        g_device->SetRenderState(D3DRS_ZENABLE,         TRUE);
        g_device->SetRenderState(D3DRS_ZFUNC,         D3DCMP_LESS);
        g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

        g_device->SetRenderState(D3DRS_AMBIENT, 0xFF00BB00);

        // rotate tank

        D3DXQUATERNION quat;
        D3DXMATRIX mat_rotation;

        D3DXMatrixIdentity(&g_mat_tank);

        D3DXQuaternionRotationYawPitchRoll(&quat, D3DX_PI/4, -D3DX_PI/4, 0.0f);
        D3DXMatrixRotationQuaternion(&mat_rotation, &quat);
        D3DXMatrixMultiply(&g_mat_tank, &mat_rotation, &g_mat_tank);

        D3DXMatrixIdentity(&g_mat_shutter);
        
        return true;
    }

    void cleanup()
    {
        delete[] g_mesh_materials;

        if(g_mesh_textures)
        {
            for(DWORD i = 0; i < g_num_materials; i++)
                release_com(g_mesh_textures[i]);

            delete[] g_mesh_textures;
        }
        
        release_com(g_mesh);
        release_com(g_shutter_vb);
        release_com(g_device);
        release_com(g_d3d);
    }

    void render()
    {
        g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);

        g_device->BeginScene();

        // render shutter
        g_device->SetRenderState(D3DRS_LIGHTING, FALSE);
        g_device->SetTransform(D3DTS_WORLD, &g_mat_shutter);
        g_device->SetStreamSource(0, g_shutter_vb, 0, sizeof(sCustomVertex));
        g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);
        g_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

        // render tank
        g_device->SetRenderState(D3DRS_LIGHTING, TRUE);
        g_device->SetTransform(D3DTS_WORLD, &g_mat_tank);

        for(DWORD i = 0; i < g_num_materials; i++)
        {
            g_device->SetMaterial(&g_mesh_materials[i]);
            g_device->SetTexture(0, g_mesh_textures[i]);

            g_mesh->DrawSubset(i);
        }        
        
        g_device->EndScene();

        g_device->Present(NULL, NULL, NULL, NULL);
    }

    LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_KEYDOWN:
            switch(wParam)
            {
            case 49: // press key "1", disable depth test.
                g_device->SetRenderState(D3DRS_ZENABLE, FALSE);
                break;

            case 50: // press key "2", enable depth test.
                g_device->SetRenderState(D3DRS_ZENABLE, TRUE);
                break;

            case VK_ESCAPE:
                DestroyWindow(hwnd);
                break;
            }    

            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }

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

    int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
    {
        WNDCLASSEX wc;

        wc.cbSize            = sizeof(WNDCLASSEX);
        wc.style            = CS_CLASSDC;
        wc.lpfnWndProc        = WinProc;
        wc.cbClsExtra        = 0;
        wc.cbWndExtra        = 0;
        wc.hInstance        = inst;
        wc.hIcon            = NULL;
        wc.hCursor            = NULL;
        wc.hbrBackground    = NULL;
        wc.lpszMenuName        = NULL;
        wc.lpszClassName    = CLASS_NAME;
        wc.hIconSm            = NULL;

        if(! RegisterClassEx(&wc))
            return -1;

        HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 640, 480,
                                 NULL, NULL, wc.hInstance, NULL);    

        if(hwnd == NULL)
            return -1;

        if(init_d3d(hwnd))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            MSG msg;
            ZeroMemory(&msg, sizeof(msg));

            while(msg.message != WM_QUIT)
            {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                    
                render();
            }
        }

        cleanup();
        UnregisterClass(CLASS_NAME, wc.hInstance);    

        return 0;
    }
      
    [B][URL=http://www.cppblog.com/Files/changingnow/ZTest.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/3/9 9:58:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客3
    发贴心情 
    深度测试与alpha混合(2)
    前面的一些例子中,已经遇到了alpha值的概念,如结构体D3DCOLORVALUE中的成员变量a,但它并没有被使用,因为还没有激活alpha混合(alpha blending),并且alpha总是被赋值为1.0f(默认渲染状态下alpha为1.0f,表示完全不透明)。

    alpha混合原理

    在前面介绍的示例程序中,绘制图形的颜色总是替换当前颜色缓冲区中存在的颜色,这样后面的物体总是覆盖在原有的物体上。但是当想要绘制类似于玻璃、水等具有透明效果的物体时,这种方法显然满足不了要求。通过定义一个表示物体半透明度的alpha值和一个半透明计算公式,可以将要绘制的物体颜色与颜色缓冲区中存在的颜色相混合,从而绘制出具有半透明效果的物体。Direct3D计算alpha颜色混合的方法如下:

    color = (RGBsrc * Ksrc) OP (RGBdst * Kdst)

    其中color表示alpha混合后的颜色值,RGBsrc表示源颜色值,即将要绘制的图元的颜色值;Ksrc表示源混合系数,通常赋值为表示半透明程度的alpha值,也可以是属于枚举类型D3DBLEND的任意值,用来和RGBsrc相乘。RGBdst表示目标颜色值,即当前颜色缓冲区中的颜色值,Kdst表示目标混合系数,可以是属于枚举D3DBLEND的任意值,用来和RGBdst相乘。OP表示源计算结果与颜色缓冲区计算结果的混合方法,默认状态下OP为D3DBLEND_ADD,即源计算结果与颜色缓冲区计算结果相加。

    图形显示中,对alpha混合最普遍的用法是:把Ksrc赋值为D3DBLEND_SRCALPHA,即当前绘制像素的alpha值;把Kdst赋值为D3DBLEND_INVSRCALPHA,即1减去当前绘制像素的alpha值;把OP赋值为D3DBLEND_ADD,使源计算结果和颜色缓冲区计算结果相加,这样一来,alpha混合颜色的公式变为:

    color = (RGBsrc * Ksrc) + (RGBdst * Kdst)

    上面的设置可以较好地模拟大多数半透明物体的效果。

    启用alpha混合

    想要绘制半透明物体,首先需要激活Direct3D的alpha混合运算,调用Direct3D渲染状态设置函数IDirect3DDevice9:::SetRenderState(),将第一个参数设置为D3DRS_ALPHABLENDENABLE,第二个参数设置为TRUE,可以激活alpha混合,代码如下:

    g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

    设置alpha混合系数

    在上面介绍的alpha混合原理中提到的源混合系数和目标混合系数,也是通过Direct3D渲染状态设置函数IDirect3DDevice9::SetRenderState()设置的。若将第一个参数设置为D3DRS_SRCBLEND,则用于设置源混合系数,若将第一个参数设置为D3DRS_DESTBLEND,则用于设置目标混合系数,第二个参数可以设置为D3DBLEND枚举常量,各具体枚举常量的含义如下:

    Defines the supported blend mode.

    typedef enum D3DBLEND{    D3DBLEND_ZERO = 1,    D3DBLEND_ONE = 2,    D3DBLEND_SRCCOLOR = 3,    D3DBLEND_INVSRCCOLOR = 4,    D3DBLEND_SRCALPHA = 5,    D3DBLEND_INVSRCALPHA = 6,    D3DBLEND_DESTALPHA = 7,    D3DBLEND_INVDESTALPHA = 8,    D3DBLEND_DESTCOLOR = 9,    D3DBLEND_INVDESTCOLOR = 10,    D3DBLEND_SRCALPHASAT = 11,    D3DBLEND_BOTHSRCALPHA = 12,    D3DBLEND_BOTHINVSRCALPHA = 13,    D3DBLEND_BLENDFACTOR = 14,    D3DBLEND_INVBLENDFACTOR = 15,    D3DBLEND_SRCCOLOR2 = 16,    D3DBLEND_INVSRCCOLOR2 = 17,    D3DBLEND_FORCE_DWORD = 0x7fffffff,} D3DBLEND, *LPD3DBLEND;
    Constants
    D3DBLEND_ZERO
    Blend factor is (0, 0, 0, 0).
    D3DBLEND_ONE
    Blend factor is (1, 1, 1, 1).
    D3DBLEND_SRCCOLOR
    Blend factor is (Rs, Gs, Bs, As).
    D3DBLEND_INVSRCCOLOR
    Blend factor is (1 - Rs, 1 - Gs, 1 - Bs, 1 - As).
    D3DBLEND_SRCALPHA
    Blend factor is (As, As, As, As).
    D3DBLEND_INVSRCALPHA
    Blend factor is ( 1 - As, 1 - As, 1 - As, 1 - As).
    D3DBLEND_DESTALPHA
    Blend factor is (Ad Ad Ad Ad).
    D3DBLEND_INVDESTALPHA
    Blend factor is (1 - Ad 1 - Ad 1 - Ad 1 - Ad).
    D3DBLEND_DESTCOLOR
    Blend factor is (Rd, Gd, Bd, Ad).
    D3DBLEND_INVDESTCOLOR
    Blend factor is (1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad).
    D3DBLEND_SRCALPHASAT
    Blend factor is (f, f, f, 1); where f = min(As, 1 - Ad).
    D3DBLEND_BOTHSRCALPHA
    Obsolete. Starting with DirectX 6, you can achieve the same effect by setting the source and destination blend factors to D3DBLEND_SRCALPHA and D3DBLEND_INVSRCALPHA in separate calls.
    D3DBLEND_BOTHINVSRCALPHA
    Source blend factor is (1 - As, 1 - As, 1 - As, 1 - As), and destination blend factor is (As, As, As, As); the destination blend selection is overridden. This blend mode is supported only for the D3DRS_SRCBLEND render state.
    D3DBLEND_BLENDFACTOR
    Constant color blending factor used by the frame-buffer blender. This blend mode is supported only if D3DPBLENDCAPS_BLENDFACTOR is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9.
    D3DBLEND_INVBLENDFACTOR
    Inverted constant color-blending factor used by the frame-buffer blender. This blend mode is supported only if the D3DPBLENDCAPS_BLENDFACTOR bit is set in the SrcBlendCaps or DestBlendCaps members of D3DCAPS9.
    D3DBLEND_SRCCOLOR2
    Blend factor is (PSOutColor[1]r, PSOutColor[1]g, PSOutColor[1]b, not used). See Render Target Blending. Differences between Direct3D 9 and Direct3D 9Ex:
    This flag is available in Direct3D 9Ex only.

    D3DBLEND_INVSRCCOLOR2
    Blend factor is (1 - PSOutColor[1]r, 1 - PSOutColor[1]g, 1 - PSOutColor[1]b, not used)). See Render Target Blending. Differences between Direct3D 9 and Direct3D 9Ex:
    This flag is available in Direct3D 9Ex only.

    D3DBLEND_FORCE_DWORD
    Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.
    Remarks
    In the preceding member descriptions, the RGBA values of the source and destination are indicated by the s and d subscripts.

    The values in this enumerated type are used by the following render states:

    D3DRS_DESTBLEND
    D3DRS_SRCBLEND
    D3DRS_DESTBLENDALPHA
    D3DRS_SRCBLENDALPHA
    See D3DRENDERSTATETYPE

    Render Target Blending
    Direct3D 9Ex has improved text rendering capabilities. Rendering clear-type fonts would normally require two passes. To eliminate the second pass, a pixel shader can be used to output two colors, which we can call PSOutColor[0] and PSOutColor[1]. The first color would contain the standard 3 color components (RGB). The second color would contain 3 alpha components (one for each component of the first color).

    These new blending modes are only used for text rendering on the first render target.

    设置alpha混合系数的代码示例如下:

    g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    设置alpha混合方法

    alpha混合方法指定源颜色和目标颜色的混合方法,通过Direct3D渲染状态设置函数IDirect3DDevice9::SetRenderState()设置,其中第一个参数设置为 D3DRS_BLENDOP,第二个参数设置为D3DBLENDOP枚举常量,各常量的含义如下:

    Defines the supported blend operations. See Remarks for definitions of terms.

    typedef enum D3DBLENDOP{    D3DBLENDOP_ADD = 1,    D3DBLENDOP_SUBTRACT = 2,    D3DBLENDOP_REVSUBTRACT = 3,    D3DBLENDOP_MIN = 4,    D3DBLENDOP_MAX = 5,    D3DBLENDOP_FORCE_DWORD = 0x7fffffff,} D3DBLENDOP, *LPD3DBLENDOP;
    Constants
    D3DBLENDOP_ADD
    The result is the destination added to the source. Result = Source + Destination
    D3DBLENDOP_SUBTRACT
    The result is the destination subtracted from to the source. Result = Source - Destination
    D3DBLENDOP_REVSUBTRACT
    The result is the source subtracted from the destination. Result = Destination - Source
    D3DBLENDOP_MIN
    The result is the minimum of the source and destination. Result = MIN(Source, Destination)
    D3DBLENDOP_MAX
    The result is the maximum of the source and destination. Result = MAX(Source, Destination)
    D3DBLENDOP_FORCE_DWORD
    Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.
    Remarks
    Source, Destination, and Result are defined as:

    Term Type Description
    Source Input Color of the source pixel before the operation.
    Destination Input Color of the pixel in the destination buffer before the operation.
    Result Output Returned value that is the blended color resulting from the operation.

    This enumerated type defines values used by the following render states:

    D3DRS_BLENDOP
    D3DRS_BLENDOPALPHA

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/3/9 9:59:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客4
    发贴心情 
    示例程序:

    该示例程序模拟了直升飞机螺旋桨的半透明效果。在程序的初始化阶段,载入Heli.x文件,它是一个包含直升飞机的三维模型文件,其中螺旋桨的材质漫反射属性为(R, G, B, A) = (0.183700; 0.183700; 0.183700; 0.500000; ),可以用文本方式打开Heli.x查看它的材质属性,Heli.x是一个文本格式的.x文件。

    示例程序中没有设置alpha混合方法,所以应用程序将采用默认的alpha混合方法D3DBLEND_ADD,即将源计算结果与颜色缓冲区计算结果相加。由于直升机螺旋桨的材质的alpha值为0.5f,因此它的最终颜色就是50%的玻璃颜色加上50%的背景颜色。

    按此在新窗口浏览图片

    按下数字键"1",激活alpha混合。

    按此在新窗口浏览图片

    按下数字键"0",禁用alpha混合。

    按此在新窗口浏览图片

    设置alpha混合方法为D3DBLENDOP_SUBTRACT的效果图,启用alpha混合时。

    g_device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);

    按此在新窗口浏览图片

    设置以下代码时的效果图,可以看到直升机变亮了,启用alpha混合:

    g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
    g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);

    按此在新窗口浏览图片

    设置以下代码时的效果图,可以看到直升机变暗了,启用alpha混合:

    g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
    g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTCOLOR);

    可以根据需要自己修改设置,以实现不同的颜色混合效果。

    由于alpha混合是当前绘制的像素颜色与颜色缓冲区中存在的颜色的混合运算,因此,在绘制半透明物体前,必须保证位于半透明物体后的物体先于半透明物体绘制,也就是说,先绘制不透明物体,再绘制半透明物体。

    有些计算机硬件由于功能的限制,可能不支持某些混合方法,这时Direct3D会自动使用alpha混合方法D3DBLENDOP_ADD。

    源程序:

    #include <d3dx9.h>

    #pragma warning(disable : 4127)

    #define CLASS_NAME    "GameApp"

    #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

    IDirect3D9*                g_d3d;
    IDirect3DDevice9*        g_device;

    ID3DXMesh*                g_mesh;
    D3DMATERIAL9*            g_mesh_materials;
    IDirect3DTexture9**        g_mesh_textures;
    DWORD                    g_num_materials;

    void setup_world_matrix()
    {
        D3DXMATRIX mat_world;
        D3DXMatrixRotationY(&mat_world, timeGetTime() / 1000.0f);
        g_device->SetTransform(D3DTS_WORLD, &mat_world);
    }

    void setup_view_proj_matrices()
    {
        // setup view matrix

        D3DXVECTOR3 eye(0.0f, 15.0f, -20.0f);
        D3DXVECTOR3 at(0.0f,  0.0f,   0.0f);
        D3DXVECTOR3 up(0.0f,  1.0f,   0.0f);

        D3DXMATRIX mat_view;
        D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
        g_device->SetTransform(D3DTS_VIEW, &mat_view);

        // setup projection matrix
        D3DXMATRIX mat_proj;
        D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);
        g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
    }

    bool init_geometry()
    {
        ID3DXBuffer* material_buffer;

        /*
         D3DXLoadMeshFromXA(
            LPCSTR pFilename,
            DWORD Options,
            LPDIRECT3DDEVICE9 pD3DDevice,
            LPD3DXBUFFER *ppAdjacency,
            LPD3DXBUFFER *ppMaterials,
            LPD3DXBUFFER *ppEffectInstances,
            DWORD *pNumMaterials,
            LPD3DXMESH *ppMesh);
        */

        if(FAILED(D3DXLoadMeshFromX("heli.x", D3DXMESH_SYSTEMMEM, g_device, NULL, &material_buffer, NULL,
                                    &g_num_materials, &g_mesh)))
        {
            MessageBox(NULL, "Could not find heli.x", "ERROR", MB_OK);
            return false;
        }

        D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();

        g_mesh_materials = new D3DMATERIAL9[g_num_materials];
        g_mesh_textures     = new IDirect3DTexture9*[g_num_materials];

        for(DWORD i = 0; i < g_num_materials; i++)
        {
            g_mesh_materials[i] = xmaterials[i].MatD3D;

            // set ambient reflected coefficient, because .x file do not set it.
            g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse;

            g_mesh_textures[i] = NULL;

            if(xmaterials[i].pTextureFilename != NULL && strlen(xmaterials[i].pTextureFilename) > 0)    
                D3DXCreateTextureFromFile(g_device, xmaterials[i].pTextureFilename, &g_mesh_textures[i]);    
        }

        material_buffer->Release();

        return true;
    }

    bool init_d3d(HWND hwnd)
    {
        g_d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if(g_d3d == NULL)
            return false;

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));

        d3dpp.Windowed                    = TRUE;
        d3dpp.SwapEffect                = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat            = D3DFMT_UNKNOWN;
        d3dpp.EnableAutoDepthStencil    = TRUE;
        d3dpp.AutoDepthStencilFormat    = D3DFMT_D16;

        if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_device)))
        {
            return false;
        }
        
        if(! init_geometry())
            return false;

        setup_view_proj_matrices();    

        g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        g_device->SetRenderState(D3DRS_SRCBLEND,         D3DBLEND_SRCALPHA);
        g_device->SetRenderState(D3DRS_DESTBLEND,         D3DBLEND_INVSRCALPHA);    

        //g_device->SetRenderState(D3DRS_SRCBLEND,         D3DBLEND_ONE);
        //g_device->SetRenderState(D3DRS_DESTBLEND,         D3DBLEND_INVDESTCOLOR);    

        //g_device->SetRenderState(D3DRS_BLENDOP,             D3DBLENDOP_SUBTRACT);        

        g_device->SetRenderState(D3DRS_ZENABLE,         TRUE);
        g_device->SetRenderState(D3DRS_ZFUNC,         D3DCMP_LESS);
        g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

        g_device->SetRenderState(D3DRS_AMBIENT, 0xFFFFBB55);
        
        return true;
    }

    void cleanup()
    {
        delete[] g_mesh_materials;

        if(g_mesh_textures)
        {
            for(DWORD i = 0; i < g_num_materials; i++)
                release_com(g_mesh_textures[i]);

            delete[] g_mesh_textures;
        }
        
        release_com(g_mesh);
        release_com(g_device);
        release_com(g_d3d);
    }

    void render()
    {
        g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);

        g_device->BeginScene();

        setup_world_matrix();

        // render opaque object first
        for(DWORD i = 0; i < g_num_materials; i++)
        {
            if(g_mesh_materials[i].Diffuse.a == 1.0f)
            {
                g_device->SetMaterial(&g_mesh_materials[i]);
                g_device->SetTexture(0, g_mesh_textures[i]);

                g_mesh->DrawSubset(i);
            }        
        }        

        // render transparent object second
        for(DWORD i = 0; i < g_num_materials; i++)
        {
            if(g_mesh_materials[i].Diffuse.a != 1.0f)
            {
                g_device->SetMaterial(&g_mesh_materials[i]);
                g_device->SetTexture(0, g_mesh_textures[i]);

                g_mesh->DrawSubset(i);
            }        
        }        
        
        g_device->EndScene();

        g_device->Present(NULL, NULL, NULL, NULL);
    }

    LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_KEYDOWN:
            switch(wParam)
            {
            case 48: // press key "0", disable alpha blend.
                g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                break;

            case 49: // press key "1", enable alpha blend.
                g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                break;

            case VK_ESCAPE:
                DestroyWindow(hwnd);
                break;
            }    

            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }

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

    int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
    {
        WNDCLASSEX wc;

        wc.cbSize            = sizeof(WNDCLASSEX);
        wc.style            = CS_CLASSDC;
        wc.lpfnWndProc        = WinProc;
        wc.cbClsExtra        = 0;
        wc.cbWndExtra        = 0;
        wc.hInstance        = inst;
        wc.hIcon            = NULL;
        wc.hCursor            = NULL;
        wc.hbrBackground    = NULL;
        wc.lpszMenuName        = NULL;
        wc.lpszClassName    = CLASS_NAME;
        wc.hIconSm            = NULL;

        if(! RegisterClassEx(&wc))
            return -1;

        HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 640, 480,
                                 NULL, NULL, wc.hInstance, NULL);    

        if(hwnd == NULL)
            return -1;

        if(init_d3d(hwnd))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            MSG msg;
            ZeroMemory(&msg, sizeof(msg));

            while(msg.message != WM_QUIT)
            {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                    
                render();
            }
        }

        cleanup();
        UnregisterClass(CLASS_NAME, wc.hInstance);    

        return 0;
    }
      
    [B][URL=http://www.cppblog.com/Files/changingnow/AlphaBlend.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/3/9 9:59:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客5
    发贴心情 
    深度测试与alpha混合(3)
    alpha源混合系数通常设置为D3DBLEND_SRCALPHA,即当前绘制像素的alpha值。目标混合系数设置为D3DBLEND_INVSRCALPHA,即1减去当前绘制像素的alpha值。那么当前绘制像素的alpha值又是如何得到的呢?如果没有使用材质和纹理,当前绘制像素的alpha值来自每个顶点颜色设置的alpha值;如果使用光照和材质,则当前像素的alpha值来自物体表面材质;如果为物体表面使用了纹理,则alpha值还与纹理有关。

    顶点alpha

    如果在程序中直接指定每个顶点的颜色,则可以直接给出每个顶点颜色的 alpha值,可以在定义顶点时直接声明该顶点的alpha值,也可以在程序运行时动态地修改顶点的alpha值。有了顶点的alpha值,渲染对象中每个像素的alpha值由该对象的alpha值和着色模式决定。当着色模式为FLAT着色模式时,构成对象的各个多边形中所有像素的alpha都等于该多边形的第一个顶点的alpha值。当着色模式为GOURAUD着色模式时,每个多边形面上的像素的alpha值由它的各个顶点的alpha值进行线性插值得到的。

    示例程序:

    圆筒在不断的绕x, y, z轴旋转。

    按此在新窗口浏览图片

    按下数字键"1",启用alpha顶点混合

    按此在新窗口浏览图片

    按下数字键"0",禁用alpha顶点混合

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/4/27 10:17:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客6
    发贴心情 
    源程序:


    #include <d3dx9.h>

    #pragma warning(disable : 4127)    // disable warning: conditional expression is constant

    #define CLASS_NAME    "GameApp"

    #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

    typedef unsigned char uchar;

    IDirect3D9*                g_d3d;
    IDirect3DDevice9*        g_device;
    IDirect3DVertexBuffer9* g_vertex_buffer;

    struct sCustomVertex
    {
        float x, y, z;
        DWORD color;
    };

    #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

    void setup_world_matrix()
    {
        D3DXMATRIX mat_world;
        D3DXMatrixIdentity(&mat_world);

        float angle = (timeGetTime() % 1000) * (2 * D3DX_PI) / 1000.0f;

        D3DXQUATERNION quat;
        D3DXMATRIX mat_rotation;

        D3DXQuaternionRotationYawPitchRoll(&quat, angle, angle, angle);
        D3DXMatrixRotationQuaternion(&mat_rotation, &quat);
        D3DXMatrixMultiply(&mat_world, &mat_rotation, &mat_world);

        g_device->SetTransform(D3DTS_WORLD, &mat_world);
    }

    void setup_view_proj_matrices()
    {
        // setup view matrix

        D3DXVECTOR3 eye(0.0f, 3.0f, -5.0f);
        D3DXVECTOR3 at(0.0f,  0.0f,   0.0f);
        D3DXVECTOR3 up(0.0f,  1.0f,   0.0f);

        D3DXMATRIX mat_view;
        D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
        g_device->SetTransform(D3DTS_VIEW, &mat_view);

        // setup projection matrix
        D3DXMATRIX mat_proj;
        D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
        g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
    }

    void init_vb()
    {    
        g_device->CreateVertexBuffer(50 * 2 * sizeof(sCustomVertex), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT,
                                     &g_vertex_buffer, NULL);

        sCustomVertex* vertices;

        g_vertex_buffer->Lock(0, 0, (void**)&vertices, 0);

        for(int i = 0; i < 50; i++)
        {
            float theta = (2 * D3DX_PI * i) / (50 - 1);

            vertices[2 * i + 0].x      = sin(theta);
            vertices[2 * i + 0].y      = -1.0f;
            vertices[2 * i + 0].z      = cos(theta);            
            vertices[2 * i + 0].color = 0x88FF0000;

            vertices[2 * i + 1].x      = sin(theta);
            vertices[2 * i + 1].y      = 1.0f;
            vertices[2 * i + 1].z      = cos(theta);            
            vertices[2 * i + 1].color = 0x8844FF00;
        }
        
        g_vertex_buffer->Unlock();
    }

    bool init_d3d(HWND hwnd)
    {
        g_d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if(g_d3d == NULL)
            return false;

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));

        d3dpp.Windowed            = TRUE;
        d3dpp.SwapEffect        = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat    = D3DFMT_UNKNOWN;

        if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_device)))
        {
            return false;
        }

        init_vb();
        setup_view_proj_matrices();

        g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
        g_device->SetRenderState(D3DRS_LIGHTING, FALSE);

        g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        g_device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
        g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

        return true;
    }

    void cleanup()
    {
        release_com(g_vertex_buffer);
        release_com(g_device);
        release_com(g_d3d);
    }

    inline void extract_argb(D3DCOLOR color, uchar* alpha, uchar* red, uchar* green, uchar* blue)
    {
        // Extract alpha, red, green, blue from D3D color value.

        if(alpha != NULL) *alpha = uchar((color >> 24) & 0xff);
        if(red   != NULL) *red   = uchar((color >> 16) & 0xff);
        if(green != NULL) *green = uchar((color >> 8) & 0xff);
        if(blue  != NULL) *blue  = uchar(color & 0xff);
    }

    void render()
    {
        g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);    

        g_device->BeginScene();

        setup_world_matrix();

        g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
        g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);
        g_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 * 50 - 2);

        // change all vertices's color and alpha

        sCustomVertex* vertex;

        g_vertex_buffer->Lock(0, 50 * 2 * sizeof(sCustomVertex), (void**)&vertex, 0);

        for(int i = 0; i < 50 * 2; i++)
        {    
            uchar alpha, red, green, blue;
            extract_argb(vertex->color, &alpha, &red, &green, &blue);

            if(++alpha > 255)    alpha = 0;
            if(++red > 255)        red = 0;
            if(++green > 255)    green = 0;
            if(++blue > 255)    blue = 0;

            vertex->color = D3DCOLOR_RGBA(red, green, blue, alpha);

            vertex++;
        }    

        g_vertex_buffer->Unlock();

        g_device->EndScene();

        g_device->Present(NULL, NULL, NULL, NULL);
    }

    LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_KEYDOWN:
            switch(wParam)
            {
            case VK_ESCAPE:
                DestroyWindow(hwnd);
                break;

            case 48:    // press key "0", disable alpha blend.
                g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                break;

            case 49:    // press key "1", enable alpha blend.
                g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                break;
            }        
                
            break;

        case WM_DESTROY:        
            PostQuitMessage(0);
            return 0;
        }

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

    int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
    {
        WNDCLASSEX wc;

        wc.cbSize            = sizeof(WNDCLASSEX);
        wc.style            = CS_CLASSDC;
        wc.lpfnWndProc        = WinProc;
        wc.cbClsExtra        = 0;
        wc.cbWndExtra        = 0;
        wc.hInstance        = inst;
        wc.hIcon            = NULL;
        wc.hCursor            = NULL;
        wc.hbrBackground    = NULL;
        wc.lpszMenuName        = NULL;
        wc.lpszClassName    = CLASS_NAME;
        wc.hIconSm            = NULL;

        if(! RegisterClassEx(&wc))
            return -1;

        HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
                                 NULL, NULL, wc.hInstance, NULL);

        if(hwnd == NULL)
            return -1;

        if(init_d3d(hwnd))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            MSG msg;
            ZeroMemory(&msg, sizeof(msg));

            while(msg.message != WM_QUIT)
            {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                    
                render();
                Sleep(10);
            }
        }

        cleanup();
        UnregisterClass(CLASS_NAME, wc.hInstance);    

        return 0;
    }

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/4/27 10:17:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客7
    发贴心情 
    深度测试与alpha混合(4)
    材质alpha

    顶点alpha是没有使用光照和材质的情况,如果对场景内的物体添加光照和材质而没有添加纹理时,顶点alpha值取决于材质属性中漫反射颜色的alpha系数和灯光颜色中的alpha系数,顶点alpha值是根据光照计算得到的。顶点光照计算是分别针对红、绿、蓝和alpha进行的,其中alpha光照计算的结果就是顶点的alpha值。有了顶点的alpha值就可根据着色模式计算出每个像素的alpha值,第一个示例程序就是材质alpha的例子。

    纹理alpha

    当对物体表面使用了纹理之后,像素的alpha值就是纹理alpha混合之后的值,所以这又取决于纹理的alpha混合方法,纹理alpha混合方法决定了纹理alpha混合之后的alpha值是取自材质,还是取自纹理,或者取自二者的某种运算。像素alpha值的具体计算过程是这样的,首先得到顶点alpha值,顶点alpha值可能是直接指定的,也可能是光照计算得到,然后根据着色模式对顶点alpha值进行插值,得到的结果再根据纹理alpha混合方法和纹理采样得到的alpha值进行指定的运算,得到最终每个像素的alpha值。

    示例程序中将一幅纹理应用到一个矩形表面,其中纹理alpha混合的设置如下:

    g_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);g_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);g_device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
    D3DTOP_MODULATE
    Multiply the components of the arguments.
    SRGBA = Arg1 x Arg2

    在示例程序中将矩形4个顶点的颜色值设置为0xFFFFFFFF,其alpha成分设置为ff,即alpha值为1.0f,所以纹理alpha混合的最终结果就是取纹理的alpha值。

    sCustomVertex vertices[] ={ { -3,   -3,  0.0f,   0xffffffff,  0.0f, 1.0f}, { -3,    3,  0.0f,   0xffffffff,  0.0f, 0.0f},  {  3,   -3,  0.0f,   0xffffffff,  1.0f, 1.0f},  {  3,    3,  0.0f,   0xffffffff,  1.0f, 0.0f}}
    示例程序在一个矩形表面贴了一颗树的纹理,在树的纹理中,没有树叶和树枝的地方alpha值为0,即完全透明;有树叶和树枝的地方alpha值为1,即完全不透明。所以通过alpha混合后,渲染的结果就像是一棵真的树。

    按此在新窗口浏览图片

    按下数字键"1",启用纹理alpha混合。

    按此在新窗口浏览图片

    按下数字键"0",禁用纹理alpha混合。

    按此在新窗口浏览图片

    将顶点alpha由ff改为88后启用纹理混合的效果,可以看出纹理的颜色变暗了。

    sCustomVertex vertices[] =    { { -3,   -3,  0.0f,   0x88ffffff,  0.0f, 1.0f}, { -3,    3,  0.0f,   0x88ffffff,  0.0f, 0.0f},  {  3,   -3,  0.0f,   0x88ffffff,  1.0f, 1.0f},  {  3,    3,  0.0f,   0x88ffffff,  1.0f, 0.0f}    };

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/4/27 10:18:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客8
    发贴心情 
    源程序:

    #include <d3dx9.h>

    #pragma warning(disable : 4127)    // disable warning: conditional expression is constant

    #define CLASS_NAME    "GameApp"

    #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

    typedef unsigned char uchar;

    IDirect3D9*                g_d3d;
    IDirect3DDevice9*        g_device;
    IDirect3DVertexBuffer9* g_vertex_buffer;
    IDirect3DTexture9*        g_texture;

    struct sCustomVertex
    {
        float x, y, z;
        DWORD color;
        float u, v;
    };

    #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

    void setup_matrices()
    {
        // setup world matrix
        D3DXMATRIX mat_world;
        D3DXMatrixIdentity(&mat_world);
        g_device->SetTransform(D3DTS_WORLD, &mat_world);

        // setup view matrix

        D3DXVECTOR3 eye(0.0f, 0.0f,  -10.0f);
        D3DXVECTOR3 at(0.0f,  0.0f,   0.0f);
        D3DXVECTOR3 up(0.0f,  1.0f,   0.0f);

        D3DXMATRIX mat_view;
        D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
        g_device->SetTransform(D3DTS_VIEW, &mat_view);

        // setup projection matrix
        D3DXMATRIX mat_proj;
        D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
        g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
    }

    bool init_vb()
    {    
        if(FAILED(D3DXCreateTextureFromFile(g_device, "tree.tga", &g_texture)))
        {
            MessageBox(NULL, "Can not load texture file tree.tga!", "ERROR", MB_OK);
            return false;
        }

        sCustomVertex vertices[] =
        {
            { -3,   -3,  0.0f,   0xffffffff,  0.0f, 1.0f},
            { -3,    3,  0.0f,   0xffffffff,  0.0f, 0.0f},    
            {  3,   -3,  0.0f,   0xffffffff,  1.0f, 1.0f},    
            {  3,    3,  0.0f,   0xffffffff,  1.0f, 0.0f}

            /*
            { -3,   -3,  0.0f,   0x88ffffff,  0.0f, 1.0f},
            { -3,    3,  0.0f,   0x88ffffff,  0.0f, 0.0f},    
            {  3,   -3,  0.0f,   0x88ffffff,  1.0f, 1.0f},    
            {  3,    3,  0.0f,   0x88ffffff,  1.0f, 0.0f}
            */
        };

        g_device->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &g_vertex_buffer, NULL);

        void* ptr;

        g_vertex_buffer->Lock(0, 0, &ptr, 0);
        memcpy(ptr, vertices, sizeof(vertices));
        g_vertex_buffer->Unlock();

        return true;
    }

    bool init_d3d(HWND hwnd)
    {
        g_d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if(g_d3d == NULL)
            return false;

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));

        d3dpp.Windowed            = TRUE;
        d3dpp.SwapEffect        = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat    = D3DFMT_UNKNOWN;

        if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_device)))
        {
            return false;
        }

        if(! init_vb())
            return false;

        setup_matrices();

        g_device->SetRenderState(D3DRS_LIGHTING, FALSE);

        g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
        g_device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
        g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

        g_device->SetTextureStageState(0, D3DTSS_COLOROP,    D3DTOP_SELECTARG1);
        g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);

        g_device->SetTextureStageState(0, D3DTSS_ALPHAOP,    D3DTOP_MODULATE);
        g_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
        g_device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

        return true;
    }

    void cleanup()
    {
        release_com(g_vertex_buffer);
        release_com(g_texture);
        release_com(g_device);
        release_com(g_d3d);
    }

    void render()
    {
        g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(55, 5, 5), 1.0f, 0);    

        g_device->BeginScene();    

        g_device->SetTexture(0, g_texture);
        g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
        g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);
        g_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

        g_device->EndScene();

        g_device->Present(NULL, NULL, NULL, NULL);
    }

    LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_KEYDOWN:
            switch(wParam)
            {
            case VK_ESCAPE:
                DestroyWindow(hwnd);
                break;

            case 48:    // press key "0", disable alpha blend.
                g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                break;

            case 49:    // press key "1", enable alpha blend.
                g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                break;
            }        
                
            break;

        case WM_DESTROY:        
            PostQuitMessage(0);
            return 0;
        }

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

    int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
    {
        WNDCLASSEX wc;

        wc.cbSize            = sizeof(WNDCLASSEX);
        wc.style            = CS_CLASSDC;
        wc.lpfnWndProc        = WinProc;
        wc.cbClsExtra        = 0;
        wc.cbWndExtra        = 0;
        wc.hInstance        = inst;
        wc.hIcon            = NULL;
        wc.hCursor            = NULL;
        wc.hbrBackground    = NULL;
        wc.lpszMenuName        = NULL;
        wc.lpszClassName    = CLASS_NAME;
        wc.hIconSm            = NULL;

        if(! RegisterClassEx(&wc))
            return -1;

        HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
                                 NULL, NULL, wc.hInstance, NULL);

        if(hwnd == NULL)
            return -1;

        if(init_d3d(hwnd))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            MSG msg;
            ZeroMemory(&msg, sizeof(msg));

            while(msg.message != WM_QUIT)
            {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                    
                render();
                Sleep(10);
            }
        }

        cleanup();
        UnregisterClass(CLASS_NAME, wc.hInstance);    

        return 0;
    }
      
    [B][URL=http://www.cppblog.com/Files/changingnow/TextureAlpha.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/4/27 10:18:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客9
    发贴心情 
    深度测试与alpha混合(5)
    透过那些透明度非常高的物体看其他物体,例如透过几乎完全透明的玻璃看其他物体,会感到玻璃好像不存在,在三维图形程序中渲染时就可以不渲染这些透明度非常高的物体,从而可以提高渲染速度,这可以通过alpha测试来实现。

    alpha测试根据当前像素是否满足alpha测试条件(即是否达到一定的透明度)来控制是否绘制该像素,图形程序应用alpha测试可以有效地屏蔽某些像素颜色。与alpha混合相比,alpha测试不将当前像素的颜色与颜色缓冲区中像素的颜色混合,像素要么完全不透明,要么完全透明。由于无需进行颜色缓冲区的读操作和颜色混合,因此alpha测试在速度上要优于alpha混合。

    alpha测试通过激活渲染状态D3DRS_ALPHATESTENABLE来设置,示例代码如下:

    g_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);

    渲染状态D3DRS_ALPHAREF用来设置alpha测试的参考值,alpha测试函数比较当前绘制的像素的alpha值和参考值,如果返回TRUE,则通过测试并绘制像素,反之不予绘制。参考值的取值范围是0x00000000到0x000000ff。

    渲染状态D3DRS_ALPHAFUNC用来设置alpha测试函数,alpha测试函数属于D3DCMPFUNC枚举类型,默认状态为D3DCMP_ALWAYS。下列代码设置alpha测试函数为D3DCMP_GREATER,表示测试点像素的alpha值大于设置的alpha参考值时则返回TRUE:

    g_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
    g_device->SetRenderState(D3DRS_ALPHAREF, 0x00000081);
    g_device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);

    已知蓝色玻璃的alpha值为浮点值0.5f,等价于两位16进制数0x80,小于程序中设置的alpha测试参考值0x81,并且alpha测试函数被设为D3DCMP_GREATER,所以蓝色玻璃的颜色不会被绘制出来。

    按此在新窗口浏览图片

    按下数字键"1",启用alpha测试。

    按此在新窗口浏览图片

    按下数字键"0",禁用alpha测试。

    源程序:

    #include <d3dx9.h>

    #pragma warning(disable : 4127)

    #define CLASS_NAME    "GameApp"

    #define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

    IDirect3D9*                g_d3d;
    IDirect3DDevice9*        g_device;

    ID3DXMesh*                g_mesh;
    D3DMATERIAL9*            g_mesh_materials;
    IDirect3DTexture9**        g_mesh_textures;
    DWORD                    g_num_materials;

    void setup_world_matrix()
    {
        D3DXMATRIX mat_world;
        D3DXMatrixRotationY(&mat_world, timeGetTime() / 1000.0f);
        g_device->SetTransform(D3DTS_WORLD, &mat_world);
    }

    void setup_view_proj_matrices()
    {
        // setup view matrix

        D3DXVECTOR3 eye(0.0f, 15.0f, -20.0f);
        D3DXVECTOR3 at(0.0f,  0.0f,   0.0f);
        D3DXVECTOR3 up(0.0f,  1.0f,   0.0f);

        D3DXMATRIX mat_view;
        D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
        g_device->SetTransform(D3DTS_VIEW, &mat_view);

        // setup projection matrix
        D3DXMATRIX mat_proj;
        D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);
        g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
    }

    bool init_geometry()
    {
        ID3DXBuffer* material_buffer;

        /*
         D3DXLoadMeshFromXA(
            LPCSTR pFilename,
            DWORD Options,
            LPDIRECT3DDEVICE9 pD3DDevice,
            LPD3DXBUFFER *ppAdjacency,
            LPD3DXBUFFER *ppMaterials,
            LPD3DXBUFFER *ppEffectInstances,
            DWORD *pNumMaterials,
            LPD3DXMESH *ppMesh);
        */

        if(FAILED(D3DXLoadMeshFromX("heli.x", D3DXMESH_SYSTEMMEM, g_device, NULL, &material_buffer, NULL,
                                    &g_num_materials, &g_mesh)))
        {
            MessageBox(NULL, "Could not find heli.x", "ERROR", MB_OK);
            return false;
        }

        D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();

        g_mesh_materials = new D3DMATERIAL9[g_num_materials];
        g_mesh_textures     = new IDirect3DTexture9*[g_num_materials];

        for(DWORD i = 0; i < g_num_materials; i++)
        {
            g_mesh_materials[i] = xmaterials[i].MatD3D;

            // set ambient reflected coefficient, because .x file do not set it.
            g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse;

            g_mesh_textures[i] = NULL;

            if(xmaterials[i].pTextureFilename != NULL && strlen(xmaterials[i].pTextureFilename) > 0)    
                D3DXCreateTextureFromFile(g_device, xmaterials[i].pTextureFilename, &g_mesh_textures[i]);    
        }

        material_buffer->Release();

        return true;
    }

    bool init_d3d(HWND hwnd)
    {
        g_d3d = Direct3DCreate9(D3D_SDK_VERSION);

        if(g_d3d == NULL)
            return false;

        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));

        d3dpp.Windowed                    = TRUE;
        d3dpp.SwapEffect                = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat            = D3DFMT_UNKNOWN;
        d3dpp.EnableAutoDepthStencil    = TRUE;
        d3dpp.AutoDepthStencilFormat    = D3DFMT_D16;

        if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_device)))
        {
            return false;
        }
        
        if(! init_geometry())
            return false;

        setup_view_proj_matrices();    

        g_device->SetRenderState(D3DRS_ZENABLE,            TRUE);
        g_device->SetRenderState(D3DRS_ZFUNC,            D3DCMP_LESS);
        g_device->SetRenderState(D3DRS_ZWRITEENABLE,    TRUE);

        g_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
        g_device->SetRenderState(D3DRS_ALPHAREF,        0x00000081);
        g_device->SetRenderState(D3DRS_ALPHAFUNC,        D3DCMP_GREATER);    

        g_device->SetRenderState(D3DRS_AMBIENT, 0xFFFFBB55);
        
        return true;
    }

    void cleanup()
    {
        delete[] g_mesh_materials;

        if(g_mesh_textures)
        {
            for(DWORD i = 0; i < g_num_materials; i++)
                release_com(g_mesh_textures[i]);

            delete[] g_mesh_textures;
        }
        
        release_com(g_mesh);
        release_com(g_device);
        release_com(g_d3d);
    }

    void render()
    {
        g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);

        g_device->BeginScene();

        setup_world_matrix();

        // render opaque object first
        for(DWORD i = 0; i < g_num_materials; i++)
        {
            if(g_mesh_materials[i].Diffuse.a == 1.0f)
            {
                g_device->SetMaterial(&g_mesh_materials[i]);
                g_device->SetTexture(0, g_mesh_textures[i]);

                g_mesh->DrawSubset(i);
            }        
        }        

        // render transparent object second
        for(DWORD i = 0; i < g_num_materials; i++)
        {
            if(g_mesh_materials[i].Diffuse.a != 1.0f)
            {
                g_device->SetMaterial(&g_mesh_materials[i]);
                g_device->SetTexture(0, g_mesh_textures[i]);

                g_mesh->DrawSubset(i);
            }        
        }        
        
        g_device->EndScene();

        g_device->Present(NULL, NULL, NULL, NULL);
    }

    LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
        case WM_KEYDOWN:
            switch(wParam)
            {
            case 48: // press key "0", disable alpha test.
                g_device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
                break;

            case 49: // press key "1", enable alpha test.
                g_device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
                break;

            case VK_ESCAPE:
                DestroyWindow(hwnd);
                break;
            }    

            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }

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

    int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
    {
        WNDCLASSEX wc;

        wc.cbSize            = sizeof(WNDCLASSEX);
        wc.style            = CS_CLASSDC;
        wc.lpfnWndProc        = WinProc;
        wc.cbClsExtra        = 0;
        wc.cbWndExtra        = 0;
        wc.hInstance        = inst;
        wc.hIcon            = NULL;
        wc.hCursor            = NULL;
        wc.hbrBackground    = NULL;
        wc.lpszMenuName        = NULL;
        wc.lpszClassName    = CLASS_NAME;
        wc.hIconSm            = NULL;

        if(! RegisterClassEx(&wc))
            return -1;

        HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 640, 480,
                                 NULL, NULL, wc.hInstance, NULL);    

        if(hwnd == NULL)
            return -1;

        if(init_d3d(hwnd))
        {
            ShowWindow(hwnd, SW_SHOWDEFAULT);
            UpdateWindow(hwnd);

            MSG msg;
            ZeroMemory(&msg, sizeof(msg));

            while(msg.message != WM_QUIT)
            {
                if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                    
                render();
                Sleep(10);
            }
        }

        cleanup();
        UnregisterClass(CLASS_NAME, wc.hInstance);    

        return 0;
    }
      
    [B][URL=http://www.cppblog.com/Files/changingnow/AlphaTest.rar]下载示例工程[/URL][/B]

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2009/4/27 10:19:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/25 23:07:24

    本主题贴数9,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    265.625ms