• 深度测试与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.0f15.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/41.0f1.0f500.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(555), 1.0f0);

        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, 200100640480,
                                 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, 00, PM_REMOVE))
                {
                    TranslateMessage(
    &msg);
                    DispatchMessage(
    &msg);
                }
                    
                render();
                Sleep(
    10);
            }
        }

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

        
    return 0;
    }

     

    下载示例工程

  • 相关阅读:
    ASP.NET身份验证机制membership入门——API篇
    测试SQL语句的执行时间
    ASP.NET身份验证机制membership入门——配置篇(2)
    ASP.NET身份验证机制membership入门——配置篇(1)
    ASP.NET身份验证机制membership入门——项目
    ASP.NET用户个性化设置Profile——配置1
    POJ 2762 强连通分量中存在单相连通边 【tarjan+toposort+缩点】.cpp
    POJ 2516 【最小费用最大流】.cpp
    POJ 1904 【强连通分量】.cpp
    POJ 1236 【强连通图+缩点】.cpp
  • 原文地址:https://www.cnblogs.com/wonderKK/p/2266814.html
Copyright © 2020-2023  润新知