• hge source explor 0xC graphics Ⅲ


      这里关于图形模块的内部接口部分

    内部调用接口

      内部接口主要完成:关于固定流水线的设置;dx的初始化;dx的结束

      可以说内部接口已经完成了左右工作,只要进行组合调用即可

    _GfxInit()

      DX的初始化函数

    • Direct3DCreate8 创建接口
    • GetAdapterIdentifier 获得设备信息,在这里可以查询设备能够做到什么
    • PRESENT_PARAMETER 参数的填写
    • CreateDevice 创建设备
    • _AdjustWindow 这个函数原来在window模块里已经考虑过,在这里之所以调用是因为DX要和窗口之间关联,所以DX变化,窗口也随着调整
    • _SetPorjectMatrix 设置投影矩阵
    • D3DXMatirxIdentity 标准化视图矩阵
    • _init_lost 在这个函数中完成顶点缓存、索引缓存、矩阵设置、渲染设置等
    • Gfx_Clear 将窗口清理干净
    bool HGE_Impl::_GfxInit()
    {
        static const char *szFormats[]={"UNKNOWN", "R5G6B5", "X1R5G5B5", "A1R5G5B5", "X8R8G8B8", "A8R8G8B8"};
        D3DADAPTER_IDENTIFIER8 AdID;
        D3DDISPLAYMODE Mode;
        D3DFORMAT Format=D3DFMT_UNKNOWN;
        UINT nModes, i;
        
    // Init D3D
                                
        pD3D=Direct3DCreate8(120); // D3D_SDK_VERSION
        if(pD3D==NULL)
        {
            _PostError("Can't create D3D interface");
            return false;
        }
    
    // Get adapter info
    
        pD3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, D3DENUM_NO_WHQL_LEVEL, &AdID);
        System_Log("D3D Driver: %s",AdID.Driver);
        System_Log("Description: %s",AdID.Description);
        System_Log("Version: %d.%d.%d.%d",
                HIWORD(AdID.DriverVersion.HighPart),
                LOWORD(AdID.DriverVersion.HighPart),
                HIWORD(AdID.DriverVersion.LowPart),
                LOWORD(AdID.DriverVersion.LowPart));
    
    // Set up Windowed presentation parameters
        
        if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Mode)) || Mode.Format==D3DFMT_UNKNOWN) 
        {
            _PostError("Can't determine desktop video mode");
            if(bWindowed) return false;
        }
        
        ZeroMemory(&d3dppW, sizeof(d3dppW));
    
        d3dppW.BackBufferWidth  = nScreenWidth;
        d3dppW.BackBufferHeight = nScreenHeight;
        d3dppW.BackBufferFormat = Mode.Format;
        d3dppW.BackBufferCount  = 1;
        d3dppW.MultiSampleType  = D3DMULTISAMPLE_NONE;
        d3dppW.hDeviceWindow    = hwnd;
        d3dppW.Windowed         = TRUE;
    
        if(nHGEFPS==HGEFPS_VSYNC) d3dppW.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
        else                      d3dppW.SwapEffect = D3DSWAPEFFECT_COPY;
    
        if(bZBuffer)
        {
            d3dppW.EnableAutoDepthStencil = TRUE;
            d3dppW.AutoDepthStencilFormat = D3DFMT_D16;
        }
    
    // Set up Full Screen presentation parameters
    
        nModes=pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT);
    
        for(i=0; i<nModes; i++)
        {
            pD3D->EnumAdapterModes(D3DADAPTER_DEFAULT, i, &Mode);
            if(Mode.Width != (UINT)nScreenWidth || Mode.Height != (UINT)nScreenHeight) continue;
            if(nScreenBPP==16 && (_format_id(Mode.Format) > _format_id(D3DFMT_A1R5G5B5))) continue;
            if(_format_id(Mode.Format) > _format_id(Format)) Format=Mode.Format;
        }
    
        if(Format == D3DFMT_UNKNOWN)
        {
            _PostError("Can't find appropriate full screen video mode");
            if(!bWindowed) return false;
        }
    
        ZeroMemory(&d3dppFS, sizeof(d3dppFS));
    
        d3dppFS.BackBufferWidth  = nScreenWidth;
        d3dppFS.BackBufferHeight = nScreenHeight;
        d3dppFS.BackBufferFormat = Format;
        d3dppFS.BackBufferCount  = 1;
        d3dppFS.MultiSampleType  = D3DMULTISAMPLE_NONE;
        d3dppFS.hDeviceWindow    = hwnd;
        d3dppFS.Windowed         = FALSE;
    
        d3dppFS.SwapEffect       = D3DSWAPEFFECT_FLIP;
        d3dppFS.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    
        if(nHGEFPS==HGEFPS_VSYNC) d3dppFS.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
        else                      d3dppFS.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    
        if(bZBuffer)
        {
            d3dppFS.EnableAutoDepthStencil = TRUE;
            d3dppFS.AutoDepthStencilFormat = D3DFMT_D16;
        }
    
        d3dpp = bWindowed ? &d3dppW : &d3dppFS;
    
        if(_format_id(d3dpp->BackBufferFormat) < 4) nScreenBPP=16;
        else nScreenBPP=32;
        
    // Create D3D Device
    
        if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      d3dpp, &pD3DDevice ) ) )
        {
            _PostError("Can't create D3D device");
            return false;
        }
    
        _AdjustWindow();
    
        System_Log("Mode: %d x %d x %s
    ",nScreenWidth,nScreenHeight,szFormats[_format_id(Format)]);
    
    // Create vertex batch buffer
    
        VertArray=0;
        textures=0;
    
    // Init all stuff that can be lost
    
        _SetProjectionMatrix(nScreenWidth, nScreenHeight);
        D3DXMatrixIdentity(&matView);
        
        if(!_init_lost()) return false;
    
        Gfx_Clear(0);
    
        return true;
    }
    _GfxInit

    _init_lost()    重要!重要!重要!

      在这个函数中实现:顶点缓存、索引缓存、矩阵设置、渲染设置

    • GetRenderTarget & GetDepthStencilSurface
    • 将渲染对象列表中的对象都导入:D3DXCreateTexture & CreateDepthStencilSurface
    • CreateVertexBuffer 创建顶点缓存
    • SetVertexShader 设置顶点格式
    • SetStreamSource 设置顶点缓存
    • CreateIndexBuffer 创建索引缓存
    • IDirect3DIndexBuffer9::Lock  锁定索引缓冲区
    • 初始化索引,这里设置为 {0,1,2 2,3,0}的方式两个两个三角形渲染
    • IDirect3DIndexBuffer9::Unlock 解除索引缓冲区的锁定
    • SetIndices 设定索引缓冲区 
    • 接下来设置渲染参数
    • SetRenderState: D3DRS_CULLMODE,D3DRS_LIGHTING,D3DRS_ALPHABLENDENABLE,D3DRS_SRCBLEND,D3DRS_DESTBLEND,D3DRS_ALPHATESTENABLE,D3DRS_ALPHAREF,D3DRS_ALPHAFUNC
    • SetTextureStageState: D3DTSS_COLOROP,D3DTSS_COLORARG1,D3DTSS_COLORARG1,D3DTSS_COLORARG2,D3DTSS_ALPHAOP,D3DTSS_ALPHAARG1,D3DTSS_ALPHAARG2,D3DTSS_MIPFILTER,D3DTSS_MAGFILTER,D3DTSS_MINFILTER
    • 设置当前的需要渲染的图元个数
    • 设置当前需要渲染的图元类型
    • 设置当前BlendMode
    • 设置当前的纹理
    • SetTransform: D3DTS_VIEW,D3DTS_PROJECTION
    bool HGE_Impl::_init_lost()
    {
        CRenderTargetList *target=pTargets;
    
    // Store render target
    
        pScreenSurf=0;
        pScreenDepth=0;
    
        pD3DDevice->GetRenderTarget(&pScreenSurf);
        pD3DDevice->GetDepthStencilSurface(&pScreenDepth);
        
        while(target)
        {
            if(target->pTex)
                D3DXCreateTexture(pD3DDevice, target->width, target->height, 1, D3DUSAGE_RENDERTARGET,
                                  d3dpp->BackBufferFormat, D3DPOOL_DEFAULT, &target->pTex);
            if(target->pDepth)
                pD3DDevice->CreateDepthStencilSurface(target->width, target->height,
                                                      D3DFMT_D16, D3DMULTISAMPLE_NONE, &target->pDepth);
            target=target->next;
        }
    
    // Create Vertex buffer
        
        if( FAILED (pD3DDevice->CreateVertexBuffer(VERTEX_BUFFER_SIZE*sizeof(hgeVertex),
                                                  D3DUSAGE_WRITEONLY,
                                                  D3DFVF_HGEVERTEX,
                                                  D3DPOOL_DEFAULT, &pVB )))
        {
            _PostError("Can't create D3D vertex buffer");
            return false;
        }
    
        pD3DDevice->SetVertexShader( D3DFVF_HGEVERTEX );
        pD3DDevice->SetStreamSource( 0, pVB, sizeof(hgeVertex) );
    
    // Create and setup Index buffer
    
        if( FAILED( pD3DDevice->CreateIndexBuffer(VERTEX_BUFFER_SIZE*6/4*sizeof(WORD),
                                                  D3DUSAGE_WRITEONLY,
                                                  D3DFMT_INDEX16,
                                                  D3DPOOL_DEFAULT, &pIB ) ) )
        {
            _PostError("Can't create D3D index buffer");
            return false;
        }
    
        WORD *pIndices, n=0;
        if( FAILED( pIB->Lock( 0, 0, (BYTE**)&pIndices, 0 ) ) )
        {
            _PostError("Can't lock D3D index buffer");
            return false;
        }
    
        for(int i=0; i<VERTEX_BUFFER_SIZE/4; i++) {
            *pIndices++=n;
            *pIndices++=n+1;
            *pIndices++=n+2;
            *pIndices++=n+2;
            *pIndices++=n+3;
            *pIndices++=n;
            n+=4;
        }
    
        pIB->Unlock();
        pD3DDevice->SetIndices(pIB,0);
    
    // Set common render states
    
        //pD3DDevice->SetRenderState( D3DRS_LASTPIXEL, FALSE );
        pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
        pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
        
        pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,   TRUE );
        pD3DDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
        pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
    
        pD3DDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
        pD3DDevice->SetRenderState( D3DRS_ALPHAREF,        0x01 );
        pD3DDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
    
        pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
        pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
        pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    
        pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
        pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
        pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
    
        pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
    
        if(bTextureFilter)
        {
            pD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
            pD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_LINEAR);
        }
        else
        {
            pD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_POINT);
            pD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_POINT);
        }
    
        nPrim=0;
        CurPrimType=HGEPRIM_QUADS;
        CurBlendMode = BLEND_DEFAULT;
        CurTexture = NULL;
    
        pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
        pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);
    
        return true;
    }
    _init_lost

    _GfxDone()

      DX结束工作

    • 删除所有的渲染对象:纹理、表面、本身
    • 重新设置索引缓存,并释放现在的索引缓存
    • 解除对顶点缓存的锁定并释放顶点缓存
    • 释放D3D设备
    • 释放D3D接口
    void HGE_Impl::_GfxDone()
    {
        CRenderTargetList *target=pTargets, *next_target;
        
        while(textures)    Texture_Free(textures->tex);
    
        if(pScreenSurf) { pScreenSurf->Release(); pScreenSurf=0; }
        if(pScreenDepth) { pScreenDepth->Release(); pScreenDepth=0; }
    
        while(target)
        {
            if(target->pTex) target->pTex->Release();
            if(target->pDepth) target->pDepth->Release();
            next_target=target->next;
            delete target;
            target=next_target;
        }
        pTargets=0;
    
        if(pIB)
        {
            pD3DDevice->SetIndices(NULL,0);
            pIB->Release();
            pIB=0;
        }
        if(pVB)
        {
            if(VertArray) {    pVB->Unlock(); VertArray=0;    }
            pD3DDevice->SetStreamSource( 0, NULL, sizeof(hgeVertex) );
            pVB->Release();
            pVB=0;
        }
        if(pD3DDevice) { pD3DDevice->Release(); pD3DDevice=0; }
        if(pD3D) { pD3D->Release(); pD3D=0; }
    }
    _GfxDone

    _GfxRestore()

      对于DX的复位操作 Reset

    • 将当前的所有的渲染对象的纹理、表面释放
    • 释放定点缓存和索引缓存
    • IDirect3DDevice8::Reset
    • _init_lost
    bool HGE_Impl::_GfxRestore()
    {
        CRenderTargetList *target=pTargets;
    
        //if(!pD3DDevice) return false;
        //if(pD3DDevice->TestCooperativeLevel() == D3DERR_DEVICELOST) return;
    
        if(pScreenSurf) pScreenSurf->Release();
        if(pScreenDepth) pScreenDepth->Release();
    
        while(target)
        {
            if(target->pTex) target->pTex->Release();
            if(target->pDepth) target->pDepth->Release();
            target=target->next;
        }
    
        if(pIB)
        {
            pD3DDevice->SetIndices(NULL,0);
            pIB->Release();
        }
        if(pVB)
        {
            pD3DDevice->SetStreamSource( 0, NULL, sizeof(hgeVertex) );
            pVB->Release();
        }
    
        pD3DDevice->Reset(d3dpp);
    
        if(!_init_lost()) return false;
    
        if(procGfxRestoreFunc) return procGfxRestoreFunc();
    
        return true;
    }
    _GfxRestore

    _render_batch(bool bEndScene)

      批渲染,就是将在顶点缓存中的数据全部渲染

    • 如果有顶点缓存的情况下才进行下面的步骤
    • 对顶点缓存接触锁定
    • 如果有图元要渲染,根据图元来分别渲染
    • 渲染完图元之后通过参数判定是否要释放定点缓存
    void HGE_Impl::_render_batch(bool bEndScene)
    {
        if(VertArray)
        {
            pVB->Unlock();
            
            if(nPrim)
            {
                switch(CurPrimType)
                {
                    case HGEPRIM_QUADS:
                        pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, nPrim<<2, 0, nPrim<<1);
                        break;
    
                    case HGEPRIM_TRIPLES:
                        pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, nPrim);
                        break;
    
                    case HGEPRIM_LINES:
                        pD3DDevice->DrawPrimitive(D3DPT_LINELIST, 0, nPrim);
                        break;
                }
    
                nPrim=0;
            }
    
            if(bEndScene) VertArray = 0;
            else pVB->Lock( 0, 0, (BYTE**)&VertArray, 0 );
        }
    }
    _render_batch

    _SetBlendMode(int blend)

      设置Blend Mode

    • 如果需要的模式和当前的模式不同则设置为参数形式:
    • BLEND_ALPHABLEND
    • BLEND_ZWRITE
    • BLEND_COLORADD
    void HGE_Impl::_SetBlendMode(int blend)
    {
        if((blend & BLEND_ALPHABLEND) != (CurBlendMode & BLEND_ALPHABLEND))
        {
            if(blend & BLEND_ALPHABLEND) pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            else pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
        }
    
        if((blend & BLEND_ZWRITE) != (CurBlendMode & BLEND_ZWRITE))
        {
            if(blend & BLEND_ZWRITE) pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
            else pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
        }            
        
        if((blend & BLEND_COLORADD) != (CurBlendMode & BLEND_COLORADD))
        {
            if(blend & BLEND_COLORADD) pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
            else pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
        }
    
        CurBlendMode = blend;
    }
    _SetBlendMode

    _SetProjectionMatrix(int width, int height)

      设置投影矩阵

    • 通过矩阵操作设置投影矩阵
    void HGE_Impl::_SetProjectionMatrix(int width, int height)
    {
        D3DXMATRIX tmp;
        D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f);
        D3DXMatrixTranslation(&tmp, -0.5f, height+0.5f, 0.0f);
        D3DXMatrixMultiply(&matProj, &matProj, &tmp);
        D3DXMatrixOrthoOffCenterLH(&tmp, 0, (float)width, 0, (float)height, 0.0f, 1.0f);
        D3DXMatrixMultiply(&matProj, &matProj, &tmp);
    }
    _SetProjectionMatrix

    _format_id(D3DFORMAT fmt)

      获得模式

    • 预定了几个模式,判断给定的模式是否在其中并返回
    int HGE_Impl::_format_id(D3DFORMAT fmt)
    {
        switch(fmt) {
            case D3DFMT_R5G6B5:        return 1;
            case D3DFMT_X1R5G5B5:    return 2;
            case D3DFMT_A1R5G5B5:    return 3;
            case D3DFMT_X8R8G8B8:    return 4;
            case D3DFMT_A8R8G8B8:    return 5;
            default:                return 0;
        }
    }
    _format_id

  • 相关阅读:
    【2021-04-15】台上一分钟,背后十年功
    【2021-04-14】买了人生中的第一个车位
    计算机网络实验部分
    乘积最大子数组
    计算各个位数不同的数字个数
    周总结
    最长回文子序列
    最长回文串
    回文子串
    拼图
  • 原文地址:https://www.cnblogs.com/yoru/p/5515666.html
Copyright © 2020-2023  润新知