Поделиться через


Упорядочение состояния в эффекте (Direct3D 10)

При использовании Direct3D 10 состояние эффекта для определенных этапов конвейера организовано следующими структурами:

Состояние конвейера Структура
Сборщик входных данных D3D10_INPUT_ELEMENT_DESC
Растеризация D3D10_RASTERIZER_DESC
Слияние выходных данных D3D10_BLEND_DESC и D3D10_DEPTH_STENCIL_DESC

 

Для этапов шейдера, где количество изменений состояния должно быть более контролируемым приложением, состояние было разделено на состояние буфера констант, состояние выборки и состояние ресурса шейдера. Это позволяет приложению тщательно обновлять только изменяющееся состояние, что повышает производительность, уменьшая объем данных, которые необходимо передать в GPU.

Итак, как упорядочить состояние конвейера в эффекте?

Ответ заключается в том, что порядок не имеет значения. Глобальные переменные не должны находиться в верхней части. Однако все примеры в пакете SDK соответствуют тому же порядку, так как рекомендуется упорядочивать данные так же. Таким образом, это краткое описание порядка данных в примерах пакета SDK DirectX.

Глобальные переменные

Как и стандартная практика C, глобальные переменные объявляются сначала в верхней части файла. Чаще всего это переменные, которые будут инициализированы приложением, а затем используются в эффекте. Иногда они инициализированы и никогда не изменялись, в других случаях они обновляются каждый кадр. Как и правила области функций C, переменные эффекта, объявленные вне области функций эффектов, видны во всем эффекте; любая переменная, объявленная внутри функции эффекта, отображается только в этой функции.

Ниже приведен пример переменных, объявленных в BasicHLSL10.fx.

// Global variables
float4 g_MaterialAmbientColor;      // Material's ambient color

Texture2D g_MeshTexture;            // Color texture for mesh

float    g_fTime;                   // App's time in seconds
float4x4 g_mWorld;                  // World matrix for object
float4x4 g_mWorldViewProjection;    // World * View * Projection matrix


// Texture samplers
SamplerState MeshTextureSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

Синтаксис переменных эффекта более подробно описан в синтаксисе переменной эффектов (Direct3D 10). Синтаксис для сэмплеров текстур эффектов более подробно описан в Типы сэмплеров (DirectX HLSL).

Шейдеры

Шейдеры — это небольшие исполняемые программы. Вы можете рассматривать шейдеры как инкапсулирующее состояние шейдера, так как код HLSL реализует функциональные возможности шейдера. Конвейер использует три различных типа шейдеров.

  • Вершинные шейдеры — работа с данными вершин. Одна вершина на входе дает одну вершину на выходе.
  • Геометрические шейдеры — работают с примитивными данными. Один входящий примитив может дать 0, 1 или несколько выходящих примитивов.
  • Шейдеры пикселей — работают с данными пикселей. Один входной пиксель соответствует одному выходному пикселю (если только пиксель не исключается из отрисовки).

Шейдеры — это локальные функции и следуйте правилам функций стиля C. При компиляции эффекта каждый шейдер компилируется, а указатель на каждую функцию шейдера хранится внутри. Интерфейс ID3D10Effect возвращается при успешной компиляции. На этом этапе скомпилированный эффект находится в промежуточном формате.

Чтобы узнать больше сведений о скомпилированных шейдерах, вам потребуется использовать отражение шейдера. Это фактически означает запрос к среде исполнения с просьбой декомпилировать шейдеры и предоставить информацию о коде шейдера.

struct VS_OUTPUT
{
    float4 Position   : SV_POSITION; // vertex position 
    float4 Diffuse    : COLOR0;      // vertex diffuse color
    float2 TextureUV  : TEXCOORD0;   // vertex texture coords 
};

VS_OUTPUT RenderSceneVS( float4 vPos : POSITION,
                         float3 vNormal : NORMAL,
                         float2 vTexCoord0 : TEXCOORD,
                         uniform int nNumLights,
                         uniform bool bTexture,
                         uniform bool bAnimate )
{
    VS_OUTPUT Output;
    float3 vNormalWorldSpace;
 
    ....    
    
    return Output;    
}


struct PS_OUTPUT
{
    float4 RGBColor : SV_Target;  // Pixel color
};

PS_OUTPUT RenderScenePS( VS_OUTPUT In,
                         uniform bool bTexture ) 
{ 
    PS_OUTPUT Output;

    if( bTexture )
        Output.RGBColor = g_MeshTexture.Sample(MeshTextureSampler, In.TextureUV) * In.Diffuse;
    ....

    return Output;
}

Синтаксис шейдеров эффектов более подробно описан в синтаксисе функции эффектов (Direct3D 10).

Методы и манёвры

Техника — это набор этапов отрисовки (должен быть хотя бы один этап). Каждый проход эффекта (который аналогичен единственному проходу в цикле рендеринга) определяет состояние шейдера и любое другое состояние конвейера, необходимое для отрисовки геометрии.

Ниже приведен пример одного метода (который включает один проход) из BasicHLSL10.fx.

technique10 RenderSceneWithTexture1Light
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, RenderSceneVS( 1, true, true ) ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, RenderScenePS( true ) ) );
    }
}

Синтаксис шейдеров эффектов более подробно описан в синтаксисе метода эффектов (Direct3D 10).

Эффекты (Direct3D 10)