zoukankan      html  css  js  c++  java
  • DirectX 龙书 混合 理解

    关于SetTextureStageState()这个函数,此文的理解有误,怕误导了别人,特别在这里声明一下,大家可以看最下面的那个连接,那个写的很好,我也是看了那个blog才知道我理解错了。
    下面的代码可以不看了。
     
    再次说说我的理解吧,一个物体是否透明,取决于它的材质,可以理解,在现实中,玻璃这种材质是透明的,而木头这种材质是不透明的,而材质中的diffuse,diffuse中的alpha就是用来调整这个材质的透明度。
    SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);这句话是说,现在要画的这个物体,它的alpha来自于颜色,比如这个地方的茶壶,并没有指定它使用什么纹理,而只是指定了它的材质是红色的,且材质的diffsue的alpha值是可调用的,所以它是透明的,而如果使用
    SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);的话,茶壶就不会有透明的效果,因为这句话是说,茶壶的透明度将来自纹理的alpha通道,因为之前设置的纹理是木板墙图片,这个图片没有alpha通道,默认值是0xffffffff,而在这个地方调整的alpha值是茶壶材质的alpha,与纹理的alpha不相干,所以,不管怎么调整这个alpha值,茶壶它都不会变的透明!
    View Code
    bool DXSetup()
    {
    /*******************************************************************************************
    * 背景墙
    ******************************************************************************************
    */

    // 创建顶点
    g_pd3dDevice->CreateVertexBuffer(
    6 * sizeof(DX7Vertex),
    D3DUSAGE_WRITEONLY,
    DX7Vertex::FVF,
    D3DPOOL_MANAGED,
    &BkGndQuad,
    0);

    DX7Vertex* v;
    BkGndQuad->Lock(0, 0, (void**)&v, 0);

    // quad built from two triangles, note texture coordinates:
    v[0] = DX7Vertex(-6.0f, -6.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
    v[1] = DX7Vertex(-6.0f, 6.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
    v[2] = DX7Vertex( 6.0f, 6.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);

    v[3] = DX7Vertex(-6.0f, -6.0f, 5.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
    v[4] = DX7Vertex( 6.0f, 6.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
    v[5] = DX7Vertex( 6.0f, -6.0f, 5.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
    BkGndQuad->Unlock();

    // 设置过滤器
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); // 设置Mipmaps过滤器

    // 创建并使用纹理
    D3DXCreateTextureFromFile(g_pd3dDevice, "..\\Texture\\256.bmp", &BkGndTex);
    BkGndMtrl = WHITE_MTRL;

    /*******************************************************************************************
    * 物体
    ******************************************************************************************
    */

    // 茶壶材质
    ::ZeroMemory(&TeapotMtrl, sizeof(TeapotMtrl));
    TeapotMtrl.Ambient = RED;
    TeapotMtrl.Diffuse = RED;
    TeapotMtrl.Specular = RED;
    TeapotMtrl.Emissive = BLACK;
    TeapotMtrl.Power = 10.0f;

    // 茶壶物体
    D3DXCreateTeapot(g_pd3dDevice, &Teapot, NULL); // 画一个茶壶

    // 灯光默认为True
    //g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);

    // 设置摄影机
    D3DXVECTOR3 position(0.0f, 0.0f, -3.0f);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX camera;
    D3DXMatrixLookAtLH(&camera,&position, &target, &up);
    g_pd3dDevice->SetTransform(D3DTS_VIEW, &camera);

    /*******************************************************************************************
    * 场景、灯光、摄影机&可视体设置
    ******************************************************************************************
    */

    // 设置灯光
    D3DLIGHT9 dir;
    ::ZeroMemory(&dir, sizeof(dir));
    dir.Type = D3DLIGHT_POINT;
    dir.Diffuse = WHITE;
    dir.Specular = WHITE * 0.3f;
    dir.Ambient = WHITE * 0.6f;
    dir.Position = D3DXVECTOR3(10.0f, 10.0f, -10.0f);
    dir.Range = 100;
    g_pd3dDevice->SetLight(0, &dir);
    g_pd3dDevice->LightEnable(0, true);

    g_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
    g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, true);

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

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


    // 设置投影矩阵
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(
    &proj,
    D3DX_PI * 0.5f, // 90 - degree
    (float)Width / (float)Height,
    1.0f,
    1000.0f);
    g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);

    return true;
    }

    void Render()
    {
    // keyboard message process -->>

    // increase/decrease alpha via keyboard input
    if (::GetAsyncKeyState('A') & 0x8000f)
    TeapotMtrl.Diffuse.a += 0.01f;
    if (::GetAsyncKeyState('S') & 0x8000f)
    TeapotMtrl.Diffuse.a -= 0.01f;

    // force alpha to[0,1] interval
    if (TeapotMtrl.Diffuse.a > 1.0f)
    TeapotMtrl.Diffuse.a = 1.0f;
    if (TeapotMtrl.Diffuse.a < 0.0f)
    TeapotMtrl.Diffuse.a = 0.0f;
    // keyboard message process <<--

    static float angle = 0.0f;
    angle += 0.02f;
    if (angle > 6.48)
    {
    angle = 0;
    }

    g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0x00,200,200,200), 1.0f, 0);
    g_pd3dDevice->BeginScene();
    // rendering of scene objects happens here

    // 画纹理背景墙
    D3DXMATRIX priCode;
    D3DXMatrixIdentity(&priCode);
    g_pd3dDevice->SetTransform(D3DTS_WORLD, &priCode);
    g_pd3dDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1);
    g_pd3dDevice->SetStreamSource(0, BkGndQuad, 0, sizeof(DX7Vertex));
    g_pd3dDevice->SetMaterial(&BkGndMtrl); // 设置材质
    g_pd3dDevice->SetTexture(0, BkGndTex); // 设置纹理
    g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

    // 画Mesh
    g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    g_pd3dDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL);
    g_pd3dDevice->SetMaterial(&TeapotMtrl); // 设置材质(并没有设置纹理,但是效果却是与纹理混合的效果,因为前面设置了纹理)
    Teapot->DrawSubset(0);
    g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);

    g_pd3dDevice->EndScene();
    g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
    }


    说说我对SetTextureStageState这个函数的理解,在这个例子中只出现了下面这两种用法
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

    首先关于混合,用下面的函数
    g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    指定了源混合因子与目标混合因子,画茶壶的时候调用
    g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    将混合应用打开
    画茶壶的时候,用公式:OutputPixel=SourcePixel 叉乘 SourceBlendFactor + DestPixel 叉乘 DestBlendFactor来计算目标像素的值

    现在,在场景中只画出一个灰色的背景墙和一个茶壶(先不画木板纹理墙),灰色的背景墙的颜色值为D3DCOLOR_ARGB(0x00,200,200,200)
    使用SetRenderState()指定源与目标混合因子,但是,此时不使用SetTextureStageState()这个函数,OK,来画一个茶壶吧,像上面贴的代码中那样,使用A和S键可以控制这个茶壶的透明度。

    现在,在刚才的场景中增加画一个木板纹理墙,使用SetRenderState()指定源与目标混合因子,还是不使用SetTextureStageState()这个函数,这个时候你会发现,A与S键无法控制茶壶的透明度了!
    现在把SetTextureStageState()调用打开(Setup中调用,或者画茶壶之前调用都行)
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
    这个时候再运行,发现A与S键又可以控制茶壶的透明度了!

    OK,小结一下,SetTextureStageState(),这个函数的设置就是与那个纹理背景墙相关的!我和理解如下:
    先说说不使用SetTextureStageState()这个函数的情况吧。
    我的纹理背景墙的图片是没有alpha通道的,它只有24位颜色值,先画纹理背景墙,再画茶壶的时候,要用上面的那个公式来计算输出像素,可是DestPixel是24位的,没有alpha值,而公式中计算的要求是32位的,所以,计算失败!而最终使用的像素颜色值还是茶壶自身的像素颜色值。

    调用SetTextureStageState()这个函数,它的用意就是:
    指定DestPixel的alpha从哪里来的!
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
    这句话是说,在混合的时候,如果目标像素颜色值没有alpha值话,那么,目标像素的alpha值将从它的颜色值中计算出来!这样,画茶壶的时候,用公式来计算混合出的目标颜色时,目标像素就有了alpha值,而公式计算有效!就出现了茶壶在纹理背景墙上可以调整透明度!
    而g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);这句话,就是说,使用D3DTSS_ALPHAARG1指定的值,即,D3DTA_DIFFUSE.

    OK,那什么,不画背景纹理墙,只画一个灰色背景的时候,在不使用SetTextureStageState()的情况下就可以调用茶壶的透明度呢,因为灰度的背景墙是有alpha值的,这个地方我设置为0x00,其实,你设置成任何数值,茶壶都是在可以在灰色背景墙上调整透明度的!

    我觉得自己很罗嗦,OK,索性罗嗦到底吧。
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
    g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

    这个函数就是用来指定,那个纹理背景墙中的alpha到底从哪里来的!

    关于这部分内容,这个文章写的很好!

    http://www.cppblog.com/kesalin/archive/2008/03/23/45183.html

  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/emyueguang/p/2290266.html
Copyright © 2011-2022 走看看