融合

1.融合方程

首先绘制那些不需要融合的物体,然后将需要融合的物体按照相对于摄像机的深度进行排序。

融合后的颜色=源像素颜色值*源融合因子 + 目标像素颜色值*目标融合因子 

Direct3D默认下是禁用融合运算的,以下方法可开启融合运算。

Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

2.通过设置绘制状态,可以设置源融合因子和目标融合因子。

Device->SetRenderState(D3DRS_SRCBLEND, value);

Device->SetRenderState(D3DRS_DESTBLEND, value);

3.透明度

Alpha分量主要用于指定像素的透明度。

默认情况下,如果当前设置的纹理拥有一个Alpha通道,Alpha值取自Alpha通道;如果没有Alpha通道,Alpha值取自顶点颜色。我们可以用绘制状态来指定Alpha的来源

     Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

     Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

如下:在后台缓存图片上显示一个半透明的三角形。

#include "d3dUtility.h"

IDirect3DDevice9* Device = 0;  //设备
//ID3DXMesh * teapot=0;
//D3DMATERIAL9 teapotMaterial;
 
const int Width  = 640;
const int Height = 480;

IDirect3DVertexBuffer9* bkVb = 0; //后台顶点缓存
IDirect3DTexture9 * bkTex=0;  //后台纹理
D3DMATERIAL9 bkMaterial;  //后台材质

IDirect3DVertexBuffer9 * fnVb=0; //前置三角形 
D3DMATERIAL9 fnMaterial;

struct Vertex //顶点结构:位置、顶点法线和纹理
{
    Vertex(){}

    Vertex(float x, float y, float z,float nx,float ny,float nz,float u,float v)
    {
        _x = x;     _y = y;  _z = z;
        _nx=nx;_ny=ny;_nz=nz;
        _u=u;_v=v;
    }

    float _x, _y, _z;
    float _nx,_ny,_nz;
    float _u,_v;

    static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

struct fnVertex
{
    fnVertex(){}
    fnVertex(float x,float y,float z,D3DCOLOR c)
    {
        _x=x;_y=y;_z=z;_c=c;
    }
    float _x,_y,_z;
    D3DCOLOR _c;
    static const DWORD FVF;
};
const DWORD fnVertex::FVF=D3DFVF_XYZ | D3DFVF_DIFFUSE;

//
// Framework Functions
//
bool Setup()
{
    fnMaterial=d3d::Red_Mtrl;
    fnMaterial.Diffuse.a=0.5f;
    Device->CreateVertexBuffer(               //创建顶点缓存
        12 * sizeof(Vertex), // size in bytes
        D3DUSAGE_WRITEONLY, // flags
        Vertex::FVF,        // vertex format
        D3DPOOL_MANAGED,    // managed memory pool
        &bkVb,          // return create vertex buffer
        0);                 // not used - set to 0

    Vertex* vertices;
    bkVb->Lock(0, 0, (void**)&vertices, 0);        //获取指向顶点缓存内容的指针

    vertices[0] = Vertex(-10.0f, -10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
    vertices[1] = Vertex(-10.0f,  10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
    vertices[2] = Vertex( 10.0f,  10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
                  
    vertices[3] = Vertex(-10.0f, -10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
    vertices[4] = Vertex( 10.0f,  10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
    vertices[5] = Vertex( 10.0f, -10.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

    bkVb->Unlock();

    Device->CreateVertexBuffer(3*sizeof(fnVertex),D3DUSAGE_WRITEONLY,fnVertex::FVF,D3DPOOL_MANAGED,&fnVb,0);
    fnVertex* v;
    fnVb->Lock(0, 0, (void**)&v, 0);
    v[0] = fnVertex(-1.0f, 0.0f, 2.0f, D3DCOLOR_ARGB(128,255,   0,   0));
    v[1] = fnVertex( 0.0f, 1.0f, 2.0f, D3DCOLOR_ARGB(128,  0, 255,   0));
    v[2] = fnVertex( 1.0f, 0.0f, 2.0f, D3DCOLOR_ARGB(128, 0,   0, 255));
    fnVb->Unlock();
    Device->SetRenderState(D3DRS_LIGHTING, false);

    //---begin light
    D3DLIGHT9 light;
    memset(&light,0,sizeof(light));
    light.Type      = D3DLIGHT_DIRECTIONAL;
    light.Diffuse   = d3d::WHITE;
    light.Specular  = d3d::WHITE * 0.2f;
    light.Ambient   = d3d::WHITE * 0.6f;
    light.Direction = D3DXVECTOR3(0.707f, 0.0f, 0.707f);

    Device->SetLight(0,&light);
    Device->LightEnable(0,true);

    Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
    Device->SetRenderState(D3DRS_SPECULARENABLE, true);
    //---end light

    //---begin texture
    D3DXCreateTextureFromFile(Device,"crate.jpg",&bkTex); //加载纹理图像,
    Device->SetTexture(0,bkTex);          //设置当前纹理
    Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); //线性纹理过滤器设置为放大过滤器
    Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); //线性纹理过滤器设置为缩小过滤器
    Device->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_POINT);  //多级渐进纹理过滤器,选择与屏幕尺寸最接近的那一级纹理
    //---end texture


    // use alpha in material's diffuse component for alpha
    Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

    // set blending factors so that alpha component determines transparency
    Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

    //
    // Set camera.
    //

    D3DXVECTOR3 pos(0.0f, 0.0f, -3.0f);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V, &pos, &target, &up);

    Device->SetTransform(D3DTS_VIEW, &V);

    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(   //投影矩阵
            &proj,
            D3DX_PI * 0.5f, // 90 - degree
            (float)Width / (float)Height,
            1.0f,
            1000.0f);
    Device->SetTransform(D3DTS_PROJECTION, &proj); //投影
    return true;
}
void Cleanup()
{
    d3d::Release<IDirect3DVertexBuffer9*>(bkVb);
    d3d::Release<IDirect3DTexture9*>(bkTex);
    d3d::Release<IDirect3DVertexBuffer9*>(fnVb);
}

bool Display(float timeDelta)
{
    if( Device )
    {
        Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
        Device->BeginScene();

        //draw 背景图
        D3DXMATRIX w;
        D3DXMatrixIdentity(&w);
        Device->SetTransform(D3DTS_WORLD, &w);
        Device->SetFVF(Vertex::FVF);
        Device->SetStreamSource(0, bkVb, 0, sizeof(Vertex));
        Device->SetMaterial(&bkMaterial);
        Device->SetTexture(0, bkTex);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); 

        //draw 三角形
         Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
         //D3DXMatrixScaling(&w, 105.0f,105.0f, 105.0f);
        Device->SetFVF(fnVertex::FVF);
        Device->SetStreamSource(0, fnVb, 0, sizeof(fnVertex));
        Device->SetMaterial(&fnMaterial);
        Device->SetTexture(0, 0);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); 

         Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
        Device->EndScene();
        Device->Present(0, 0, 0, 0);
    }
    return true;
}

//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {
    case WM_DESTROY:
        ::PostQuitMessage(0);
        break;
        
    case WM_KEYDOWN:
        if( wParam == VK_ESCAPE )
            ::DestroyWindow(hwnd);
        break;
    }
    return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
                   HINSTANCE prevInstance, 
                   PSTR cmdLine,
                   int showCmd)
{
    if(!d3d::InitD3D(hinstance,
        Width, Height, true, D3DDEVTYPE_HAL, &Device))
    {
        ::MessageBox(0, "InitD3D() - FAILED", 0, 0);
        return 0;
    }
        
    if(!Setup())
    {
        ::MessageBox(0, "Setup() - FAILED", 0, 0);
        return 0;
    }

    d3d::EnterMsgLoop( Display );

    Cleanup();

    Device->Release();

    return 0;
}
main.cpp
原文地址:https://www.cnblogs.com/hometown/p/3659087.html