Общая путаница с использованием файлов .fx и шейдеров в DirectX9 в C ++ - как именно вы устанавливаете соединение с приложением? - PullRequest
3 голосов
/ 31 января 2012

Ну, в принципе, я не совсем уверен, как правильно использовать методы Set и Get Parameter в DX для использования файлов .fx. Я имею в виду, что нигде не могу найти хорошего учебника. У меня даже была книга о D3D9 и хотя я получил большую часть этого, я все еще не могу использовать файлы эффектов. Что еще хуже, образцы DirectX, предоставляемые Microsoft, упакованы с некоторыми классами DX Utility от Microsoft и всевозможными другими ненужными осложнениями, и я не могу понять это через 2k строк кода. Я имею в виду, что я понял основную идею (загрузка, начало, цикл с проходами, конец), но кто-нибудь может, пожалуйста, указать мне на хороший учебник на каком-то простом примере. Главное, я не понять, как работать с параметрами эффекта: (

Ответы [ 2 ]

3 голосов
/ 11 февраля 2013

Вот справочный лист, который я написал, когда впервые учился использовать шейдеры HLSL в DirectX9.Возможно, это поможет.

В ПРИЛОЖЕНИИ:
Объявите необходимые переменные:

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 голос
/ 01 февраля 2012

Можете ли вы быть более конкретным в отношении проблем?

Основная идея с параметрами API for Effect - загрузить файл .fx и затем использовать ID3DXEffect::GetParameterByName() или GetParameterBySemantic(), чтобы получить D3DXHANDLE для параметров, которые вы хотите изменить во время выполнения. Затем в цикле рендеринга вы можете установить значения для этих параметров, используя семейство функций ID3DXEffect::SetXXX() (которое вы используете, зависит от типа параметра, который вы устанавливаете, например, Float, Vector, Matrix), передавая D3DXHANDLE вы получили, когда вы загрузили эффект.

Причиной, по которой вы работаете с D3DXHANDLE s, а не напрямую со строками имен параметров, является производительность - это позволяет выполнять множество сравнений строк в цикле рендеринга для поиска параметров.

Простой пример того, как вы могли бы это использовать, - это определение параметра texture2D с именем diffuseTex в вашем файле .fx. Когда вы загружаете .fx файл, используйте

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

и затем в цикле рендеринга установите соответствующую диффузную текстуру для каждой модели, которую вы рисуете, используя

LPDIRECT3DTEXTURE9 diffuseTexturePtr = GetMeTheRightTexturePlease(); ID3DXEffect::SetTexture(diffuseTexHandle, diffuseTexturePtr);

...