• Directx11 HelloWorld之HLSL的Effect框架的使用


     

        最近尝试用了下Directx下的Effect框架,作为一初学者初学者,说下为什么我们要使用Effect框架及其好处吧。

        首先Effect最大好处的就是简单,使得编写Shader绘制的程序工作量大大下降。如果不用Effect框架,那么一个个Vertex ShaderGeometry ShaderPixel Shader都要一遍遍的先用D3DX11CompileFromFile得到二进制代码,再分别调CreateVertexShader, CreateGeometryShaderCreatePixelShader等创建ID3D11VertexShader,ID3D11GeometryShader,ID3D11PixelShader等。

        相比之下使用Effect框架的话,在用D3DX11CompileFromFile得到二进制代码后,只需要再调用D3DX11CreateEffectFromMemory得到ID3D11Effect接口便可。

        第二个好处是Effect框架下,Directx中的变量和HLSL中的变量绑定逻辑比较清晰(也可以说简单)。之前的日志说过在不用Effect框架下,HLSL中的变量和Directx应用中的变量的绑定是根据变量的类型和顺序等来绑定的,这种隐式的绑定相当容易出错。而且还要考虑Global VariableConstant Buffer等各种类型。Constant Buffer可能是不同的寄存器中,它也有着一套它自己的变量的更新规则等等。这些都相当的麻烦。而在Effect框架中,一切绑定通过GetVariableByName(),这使得逻辑非常的清晰简单。

        当然还有可能有其他的好处坏处,留着在慢慢发掘。

        下面记录下如何使用DirectxEffect框架。

        在Dirext11中,Effect已经被单独划分出来了。要使用Effect框架,我们要引用相应的静态库。

        首先要在DirectxSDk的安装目录下找到Samples/C++/Effect11,编译目录下的工程,在相应的Samples/C++/Effect11/Debug目录下找到Effects11这个静态库,拷贝这个静态库到自己工程的工作目录下,最后在自己项目中的Linker->Input->Additional Dependencies中输入Effects11.lib,表示要引用这个静态库。这就OK了。

      然后再代码中加入#include <d3dx11effect.h>表示引用这个头文件。

        下面从代码上说下如何在程序中使用Effect框架的几个基本的步骤,这里我们只是绘制几个简单的箱子。

        先看HLSL代码:

    //--------------------------------------------------------------------------------------

    // Constant Buffer Variables

    //--------------------------------------------------------------------------------------

    cbuffer WorldConstantBuffer: register( b0 ) 

    {

        matrix World;

    matrix View;

    matrix Projection;

    }

    //--------------------------------------------------------------------------------------

    struct VS_OUTPUT

    {

        float4 Pos : SV_POSITION;

        float4 Color : COLOR;

    };

    //--------------------------------------------------------------------------------------

    // Vertex Shader

    //--------------------------------------------------------------------------------------

    VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR )

    {

        VS_OUTPUT output = (VS_OUTPUT)0;

        output.Pos = mul( Pos, World );

        output.Pos = mul( output.Pos, View );

        output.Pos = mul( output.Pos, Projection );

        output.Color = Color;

        return output;

    }

    //--------------------------------------------------------------------------------------

    // Pixel Shader

    //--------------------------------------------------------------------------------------

    float4 PS( VS_OUTPUT input ) : SV_Target

    {

        return input.Color;

    }

    technique11 BasicTech

    {

      pass P0

      {

        SetVertexShader( CompileShader( vs_4_0,VS() ) );

        SetGeometryShader( NULL );

        SetPixelShader( CompileShader(ps_4_0,PS() ) );

      }

    }

        基本和非Effect框架一样,只是多了个

    technique11 BasicTech

    {

      pass P0

      {

        SetVertexShader( CompileShader( vs_4_0,VS() ) );

        SetGeometryShader( NULL );

        SetPixelShader( CompileShader(ps_4_0,PS() ) );

      }

    }

        Techniquepass包装起来,pass把渲染管道里面所有需要用到的vertexgeometrypixel包装起来。

     

       看完HLSL代码,再来看看在Direct11中如何使用它们。第一步是在Direct11中先用D3DX11CompileFromFile()编译HLSL代码,再用D3DX11CreateEffectFromMemory生成Effect的接口。

    HRESULT Box::BuildFX()

    {

    HRESULT hr=S_OK;

    ID3DBlob *pBblob=NULL;

    ID3DBlob *pErrorBlob=NULL;

    DWORD shaderFlags=D3DCOMPILE_ENABLE_STRICTNESS;

    hr=D3DX11CompileFromFile(L"Cube.fx",NULL,NULL,NULL,"fx_5_0",shaderFlags,0,NULL,&pBblob,&pErrorBlob,NULL);

    if(FAILED(hr))

    {

    ……

    }

    D3DX11CreateEffectFromMemory(pBblob->GetBufferPointer(),pBblob->GetBufferSize(),0,m_pDevice,&m_pFX);

        ……

    return hr;

    }

        值得注意的是D3DX11CompileFromFile()中的"fx_5_0",Directx11中一定要用"fx_5_0",这个是不向下兼容的,不能用"fx_4_0"及之前版本。

        在得到Effect框架接口后,我们就要绑定HLSLDirectx中的相关变量

    HRESULT Box::BuildFX()

    {

    HRESULT hr=S_OK;

    ID3DBlob *pBblob=NULL;

    ID3DBlob *pErrorBlob=NULL;

    DWORD shaderFlags=D3DCOMPILE_ENABLE_STRICTNESS;

    hr=D3DX11CompileFromFile(L"Cube.fx",NULL,NULL,NULL,"fx_5_0",shaderFlags,0,NULL,&pBblob,&pErrorBlob,NULL);

    if(FAILED(hr))

    {

    if(pErrorBlob->GetBufferPointer())

    {

    char* errorMes=(char*)pErrorBlob->GetBufferPointer();

    //printf(errorMes);

    std::cout<<errorMes<<std::endl;

    return E_FAIL;

    }

    }

    IFR(D3DX11CreateEffectFromMemory(pBblob->GetBufferPointer(),pBblob->GetBufferSize(),0,m_pDevice,&m_pFX));

    m_pTech=m_pFX->GetTechniqueByName("BasicTech");

    m_pWorldMatVar=m_pFX->GetVariableByName("World")->AsMatrix();

    m_pViewMatVar=m_pFX->GetVariableByName("View")->AsMatrix();

    m_pProjMatVar=m_pFX->GetVariableByName("Projection")->AsMatrix();

    return hr;

    }

        上面几个变量的类型分别是ID3DX11Effect *m_pFX;

        ID3DX11EffectTechnique *m_pTech;

        ID3DX11EffectMatrixVariable *m_pWorldMatVar;

        ID3DX11EffectMatrixVariable *m_pViewMatVar;

    ID3DX11EffectMatrixVariable *m_pProjMatVar;

       最后我们要为顶点创建顶点的格式:ID3D11InputLayout

    HRESULT Box::BuildInputLayout()

    {

    HRESULT hr=S_OK;

    // Define the input layout

    D3D11_INPUT_ELEMENT_DESC layout[] =

    {

    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },

    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },

    };

    UINT numElements = ARRAYSIZE( layout );

    // Create the input layout

    D3DX11_PASS_DESC passDesc;

    m_pTech->GetPassByIndex(0)->GetDesc(&passDesc);

    IFR( m_pDevice->CreateInputLayout( layout,numElements,passDesc.pIAInputSignature,passDesc.IAInputSignatureSize, &m_pInputLayout ) );

        // Set the input layout

    m_pContext->IASetInputLayout( m_pInputLayout );

    return hr;

    }

        初始化的工作完成后我们就可以渲染了。先是通过SetMatrix等函数设置HLSL中相应变量的值。然后再遍历technique中所有的pass,通过Apply调用相应passshader状态。

    void Box::Render(const float *glMat,D3DXMATRIX* mView,D3DXMATRIX* mProj)

    {

    m_pWorldMatVar->SetMatrix(glMat);

    m_pViewMatVar->SetMatrix( ((float*)mView) );

    m_pProjMatVar->SetMatrix( ((float*)mProj) );

    D3DX11_TECHNIQUE_DESC techDesc;

    m_pTech->GetDesc(&techDesc);

    for(int i=0;i<techDesc.Passes;i++)

    {

    ID3DX11EffectPass *pass=m_pTech->GetPassByIndex(i);

    pass->Apply(0,m_pContext);

    m_pContext->DrawIndexed( 36, 0, 0 );        // 36 vertices needed for 12 triangles in a triangle list

    }

    return;

    }

       这次主要总结下了Effect框架的相关使用问题和主要的步骤。由于Directx11的代码很长,就不一一贴出来了。

  • 相关阅读:
    通过Flex读写浏览器中的cookie的方法整理
    GXCMS模板说明文档
    iBatis简单入门教程
    深入浅出 JavaScript 中的 this
    第二章(2) CSS
    DWR入门教程
    mysql数据库导入sql文件Mysql导入导出.sql文件的方法
    document.getElementById与getElementByName的区别
    Understanding JavaScript Function Invocation and “this”
    if ( document.all ) 可以简单的判断浏览器是否IE浏览器?
  • 原文地址:https://www.cnblogs.com/bester/p/3255800.html
Copyright © 2020-2023  润新知