关于.fx文件和着色器在C ++中使用DirectX9的一般混淆 - 你究竟如何与应用程序建立连接?

时间:2012-01-31 19:22:11

标签: directx effects hlsl

基本上,我不太确定如何正确使用DX中的Set和Get Parameter方法来使用.fx文件。我的意思是我找不到任何好的教程。我甚至有一本关于D3D9的书虽然我得到了大部分内容,但我仍然无法使用效果文件。更糟糕的是,微软提供的DirectX样本包含了一些由微软提供的DX实用程序类以及各种其他不必要的复杂功能,我无法获得它通过2k行代码。我的意思是我得到了基本的想法(加载,开始,循环传递,结束),但任何人都可以请指出一个简单示例的好教程。主要的是我没有了解如何使用效果参数:(

2 个答案:

答案 0 :(得分:3)

这是我在第一次学习如何在DirectX9中使用HLSL着色器时写回的参考表。也许它会有所帮助。

在申请中:
声明所需的变量:

ID3DXEffect*                shader;


加载.fx文件:

D3DXCreateEffectFromFile(   d3dDevice,
                            _T("filepath.fx"),
                            0,
                            0,
                            0,
                            0,
                            &shader,
                            0
                        );


清理效果对象(有些人使用SAFE_RELEASE宏):

if(shader)
    shader->Release();
shader = nullptr;


使用着色器渲染内容:

void Application::Render()
{
    unsigned passes = 0;
    shader->Begin(&passes,0);
    for(unsigned i=0;i<passes;++i)
    {
        shader->BeginPass(i);

        // Set uniforms
        shader->SetMatrix("gWorld",&theMatrix);
        shader->CommitChanges();    // Not necessary if SetWhatevers are done OUTSIDE of a BeginPass/EndPass pair.

        /* Insert rendering instructions here */
        // BEGIN EXAMPLE:

            d3dDevice->SetVertexDeclaration(vertexDecl);
            d3dDevice->SetStreamSource(0,vertexBuffer,0,sizeof(VERT));

            d3dDevice->SetIndices(indexBuffer);

            d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,numVerts,0,8);

        // END EXAMPLE

        shader->EndPass();
    }
    shader->End();
}


在.FX文件中:
声明制服(您想在应用程序中设置的变量):

float4x4    gWorld      : WORLD;
float4x4    gViewProj   : VIEWPROJECTION;
float       gTime       : TIME;

Texture2D   gDiffuseTexture;                // requires a matching sampler
sampler gDiffuseSampler = sampler_state     // here's the matching sampler
{
    Texture = <gDiffuseTexture>;
    FILTER = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};


定义顶点着色器输入结构:

struct VS_INPUT     // make this match the vertex structure in Application
{
    float3 untransformed_pos        : POSITION0;
    float3 untransformed_nrm        : NORMAL0;
    float4 color                    : COLOR0;
    float2 uv_coords                : TEXCOORD0;
};


定义像素着色器输入结构(顶点着色器输出):

struct PS_INPUT
{
    float4 transformed_pos          : POSITION0;
    float4 transformed_nrm          : NORMAL0;
    float4 color                    : COLOR0;
    float2 uv_coords                : TEXCOORD0;
};


定义顶点着色器:

PS_INPUT    mainVS  (VS_INPUT input)
{
    PS_INPUT output;

    /* Insert shader instructions here */

    return output;
}


定义像素着色器:

float4      mainPS  (PS_INPUT input)    : COLOR
{
    /* Insert shader instructions here */

    return float4(resultColor,1.0f);
}

定义一种技术:

technique myTechnique
{
    // Here is a quick sample
    pass FirstPass
    {
        vertexShader = compile vs_3_0 mainVS();
        pixelShader  = compile ps_3_0 mainPS();

        // Setting a few of the many D3D renderstates via the effect framework
        ShadeMode = FLAT; // flat color interpolation across triangles
        FillMode = SOLID; // no wireframes, no point drawing.
        CullMode = CCW; // cull any counter-clockwise polygons.
    }
}

答案 1 :(得分:1)

你能更具体地了解你遇到问题的地方吗?

效果参数API的基本思想是加载.fx文件,然后使用ID3DXEffect::GetParameterByName()GetParameterBySemantic()检索要在运行时修改的参数的D3DXHANDLE 。然后在渲染循环中,您可以使用ID3DXEffect::SetXXX()函数族设置这些参数的值(您使用的函数取决于您设置的参数的类型,例如Float,Vector,Matrix),传递{ {1}}您在加载效果时检索到了。

使用D3DXHANDLE而非直接使用参数名称字符串的原因是性能 - 它会在渲染循环中保存大量字符串比较以查找参数。

如何使用此功能的一个简单示例是在.fx文件中定义名为D3DXHANDLE的{​​{1}}参数。加载.fx文件时,请使用

texture2D

然后在渲染循环中为使用

绘制的每个模型设置适当的漫反射贴图

diffuseTex D3DXHANDLE diffuseTexHandle = effect->GetParameterByName(NULL, "diffuseTex");