Перенос GLSLPort the GLSL

Важные APIImportant APIs

После переноса кода, который создает и настраивает буферы и объекты шейдеров, следует перенести внутренний код шейдеров из версии GLSL (GL Shader Language) для OpenGL ES 2.0 в HLSL (High-level Shader Language) для Direct3D 11.Once you've moved over the code that creates and configures your buffers and shader objects, it's time to port the code inside those shaders from OpenGL ES 2.0's GL Shader Language (GLSL) to Direct3D 11's High-level Shader Language (HLSL).

В OpenGL ES 2,0 шейдеры возвращают данные после выполнения с помощью встроенных функций, таких как **GL _ **, GL _ фрагколорили **GL _ фрагдата [ n ] ** (где n — это индекс для конкретного целевого объекта прорисовки).In OpenGL ES 2.0, shaders return data after execution using intrinsics such as gl_Position, gl_FragColor, or gl_FragData[n] (where n is the index for a specific render target). В Direct3D нет специфических встроенных элементов, и шейдеры возвращают данные как возвращаемый тип соответствующих функций main().In Direct3D, there are no specific intrinsics, and the shaders return data as the return type of their respective main() functions.

Данные, которые требуется интерполировать между стадиями шейдера, такие как позиция вершины или нормаль, обрабатываются с помощью объявления varying.Data that you want interpolated between shader stages, such as the vertex position or normal, is handled through the use of the varying declaration. Однако в Direct3D такого объявления нет. Вместо этого любые данные, которые требуется передавать между стадиями шейдера, должны быть отмечены с помощью семантики HLSL.However, Direct3D doesn't have this declaration; rather, any data that you want passed between shader stages must be marked with an HLSL semantic. Конкретная выбранная семантика указывает предназначение данных.The specific semantic chosen indicates the purpose of the data, and is. Например, данные вершины, которые требуется интерполировать между шейдером фрагментов, объявляются как:For example, you'd declare vertex data that you want interpolated between the fragment shader as:

float4 vertPos : POSITION;

илиor

float4 vertColor : COLOR;

где семантика POSITION используется, чтобы указать данные позиции вершины.Where POSITION is the semantic used to indicate vertex position data. POSITION представляет также особый случай, поскольку после интерполяции к этому элементу невозможно получить доступ с помощью построителя текстуры.POSITION is also a special case, since after interpolation, it cannot be accessed by the pixel shader. Таким образом, необходимо указать входные данные для шейдера пикселей с _ ПОЛОЖЕНИЕМ SV, а данные с интерполяцией вершин будут помещены в эту переменную.Therefore, you must specify input to the pixel shader with SV_POSITION and the interpolated vertex data will be placed in that variable.

float4 position : SV_POSITION;

Семантики можно объявлять в методах тела (main) шейдеров.Semantics can be declared on the body (main) methods of shaders. Для шейдеров пикселей _ целевой объект ОКП [ n ] , который указывает на целевой объект отрисовки, является обязательным для метода Body.For pixel shaders, SV_TARGET[n], which indicates a render target, is required on the body method. (ОКП _ Целевой объект без числового суффикса по умолчанию отображает целевой индекс 0.)(SV_TARGET without a numeric suffix defaults to render target index 0.)

Также обратите внимание, что шейдеры вершин необходимы для вывода _ семантических значений «значение системы» в ОКП.Also note that vertex shaders are required to output the SV_POSITION system value semantic. Эта семантика преобразует данные о положении вершины в значения координат, где x находится в диапазоне от –1 до 1, y находится в диапазоне от –1 до 1, z делится на исходное значение однородной координаты w (z/w), а w равняется единице, деленной на исходное значение w (1/w).This semantic resolves the vertex position data to coordinate values where x is between -1 and 1, y is between -1 and 1, z is divided by the original homogeneous coordinate w value (z/w), and w is 1 divided by the original w value (1/w). Шейдеры пикселей используют _ семантику «значение системы» в SV для получения расположения пикселя на экране, где x находится в диапазоне 0, ширина целевого объекта прорисовки и y — от 0 до высоты целевого объекта отрисовки (Каждое смещение на 0,5).Pixel shaders use the SV_POSITION system value semantic to retrieve the pixel location on the screen, where x is between 0 and the render target width and y is between 0 and the render target height (each offset by 0.5). На уровне функций 9 _ шейдеров пикселей не удается считать значение значения "ОКП" _ .Feature level 9_x pixel shaders cannot read from the SV_POSITION value.

Буферы констант должны объявляться с ключевым словом cbuffer и связываться с конкретным начальным регистром для подстановки.Constant buffers must be declared with cbuffer and be associated with a specific starting register for lookup.

Direct3D 11: объявление буфера констант HLSLDirect3D 11: An HLSL constant buffer declaration

cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
  matrix mvp;
};

Здесь буфер констант использует регистр b0 для сохранения упакованного буфера.Here, the constant buffer uses register b0 to hold the packed buffer. Все регистры называются в форме b # .All registers are referred to in the form b#. Дополнительные сведения о реализации буферов констант, регистров и упаковке данных в HLSL см. в разделе Константы шейдера (HLSL).For more information on the HLSL implementation of constant buffers, registers, and data packing, read Shader Constants (HLSL).

InstructionsInstructions

Шаг1. Перенос вершинного шейдераStep 1: Port the vertex shader

В нашем простом примере OpenGL ES 2.0 вершинный шейдер имеет три входных параметра: постоянная матрица модель-представление-проекция 4×4 и два вектора с 4 координатами.In our simple OpenGL ES 2.0 example, the vertex shader has three inputs: a constant model-view-projection 4x4 matrix, and two 4-coordinate vectors. Эти два вектора содержат позицию вершины и ее цвет.These two vectors contain the vertex position and its color. Шейдер преобразует вектор позиции в координаты перспективы и назначает его позиции GL, _ встроенной для растрирования.The shader transforms the position vector to perspective coordinates and assigns it to the gl_Position intrinsic for rasterization. Цвет вершины также копируется в изменяющуюся переменную для интерполяции при растеризации.The vertex color is copied to a varying variable for interpolation during rasterization, as well.

OpenGL ES 2.0: вершинный шейдер для кубического объекта (GLSL)OpenGL ES 2.0: Vertex shader for the cube object (GLSL)

uniform mat4 u_mvpMatrix; 
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 destColor;

void main()
{           
  gl_Position = u_mvpMatrix * a_position;
  destColor = a_color;
}

Теперь в Direct3D матрица констант проекции модельного представления содержится в буфере констант, упакованном в регистре b0, а позиция и цвет вершины конкретно помечаются соответствующей семантикой HLSL: POSITION и COLOR.Now, in Direct3D, the constant model-view-projection matrix is contained in a constant buffer packed at register b0, and the vertex position and color are specifically marked with the appropriate respective HLSL semantics: POSITION and COLOR. Поскольку наш макет входных данных указывает конкретное упорядочение значений этих двух векторов, вы должны создать содержащую их структуру и объявить ее как тип для входного параметра в функции тела шейдера (main).Since our input layout indicates a specific arrangement of these two vertex values, you create a struct to hold them and declare it as the type for the input parameter on the shader body function (main). (Можно также указать их как отдельные параметры, но это приведет к сложностям.) Вы также должны задать для этой стадии выходной тип, содержащий интерполированную позицию и цвет, и объявить его как возвращаемое значение для функции тела в вершинном шейдере.(You could also specify them as two individual parameters, but that could get cumbersome.) You also specify an output type for this stage, which contains the interpolated position and color, and declare it as the return value for the body function of the vertex shader.

Direct3D 11: вершинный шейдер для кубического объекта (HLSL)Direct3D 11: Vertex shader for the cube object (HLSL)

cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
  matrix mvp;
};

// Per-vertex data used as input to the vertex shader.
struct VertexShaderInput
{
  float3 pos : POSITION;
  float3 color : COLOR;
};

// Per-vertex color data passed through the pixel shader.
struct PixelShaderInput
{
  float3 pos : SV_POSITION;
  float3 color : COLOR;
};

PixelShaderInput main(VertexShaderInput input)
{
  PixelShaderInput output;
  float4 pos = float4(input.pos, 1.0f); // add the w-coordinate

  pos = mul(mvp, projection);
  output.pos = pos;

  output.color = input.color;

  return output;
}

Выходной тип данных PixelShaderInput заполняется при растеризации и предоставляется шейдеру фрагментов (пиксельному шейдеру).The output data type, PixelShaderInput, is populated during rasterization and provided to the fragment (pixel) shader.

Шаг 2. Перенос шейдера фрагментовStep 2: Port the fragment shader

Наш пример шейдера фрагментов в GLSL чрезвычайно прост: Предоставьте _ встроенную фрагколор GL с использованием значения цвета с интерполяцией.Our example fragment shader in GLSL is extremely simple: provide the gl_FragColor intrinsic with the interpolated color value. OpenGL ES 2.0 запишет его в целевой объект отрисовки по умолчанию.OpenGL ES 2.0 will write it to the default render target.

OpenGL ES 2.0: шейдер фрагментов для кубического объекта (GLSL)OpenGL ES 2.0: Fragment shader for the cube object (GLSL)

varying vec4 destColor;

void main()
{
  gl_FragColor = destColor;
} 

В Direct3D все почти так же просто.Direct3D is almost as simple. Единственное существенное различие заключается в том, что функция тела построителя текстуры должна возвращать значение.The only significant difference is that the body function of the pixel shader must return a value. Так как цвет является 4-координатным (RGBA) значением float, вы указываете float4 как тип возвращаемого значения, а затем указываете целевой объект отрисовки по умолчанию как _ семантика целевой системы ОКП.Since the color is a 4-coordinate (RGBA) float value, you indicate float4 as the return type, and then specify the default render target as the SV_TARGET system value semantic.

Direct3D 11: пиксельный шейдер для кубического объекта (HLSL)Direct3D 11: Pixel shader for the cube object (HLSL)

struct PixelShaderInput
{
  float4 pos : SV_POSITION;
  float3 color : COLOR;
};


float4 main(PixelShaderInput input) : SV_TARGET
{
  return float4(input.color, 1.0f);
}

Цвет пикселя для позиции записывается в целевой объект отрисовки.The color for the pixel at the position is written to the render target. Теперь посмотрим, как отобразить содержимое целевого объекта отрисовки, в разделе Рисование на экране.Now, let's see how to display the contents of that render target in Draw to the screen!

Предыдущий шагPrevious step

Перенос буферов вершин и данных Следующий шагPort the vertex buffers and data Next step

Рисование на экране ЗаметкиDraw to the screen Remarks

Понимание семантики HLSL и упаковки буферов констант избавит вас от многих затруднений при отладке, а также обеспечит возможности оптимизации.Understanding HLSL semantics and the packing of constant buffers can save you a bit of a debugging headache, as well as provide optimization opportunities. Если у вас есть возможность, внимательно изучите разделы Синтаксис переменных (HLSL), Введение в буферы в Direct3D 11 и Инструкции: создание буфера констант.If you get a chance, read through Variable Syntax (HLSL), Introduction to Buffers in Direct3D 11, and How to: Create a Constant Buffer. Если нет, вот для начала несколько полезных замечаний о семантике и буферах констант:If not, though, here's a few starting tips to keep in mind about semantics and constant buffers:

  • Всегда тщательно проверяйте код конфигурации вашего обработчика Direct3D, чтобы убедиться, что структуры ваших буферов констант соответствуют объявлениям cbuffer элементов struct в коде HLSL и что скалярные типы компонентов совпадают в обоих объявлениях.Always double check your renderer's Direct3D configuration code to make sure that the structures for your constant buffers match the cbuffer struct declarations in your HLSL, and that the component scalar types match across both declarations.
  • В коде C++ обработчика используйте типы DirectXMath в своих объявлениях буферов констант, чтобы обеспечить правильную упаковку данных.In your renderer's C++ code, use DirectXMath types in your constant buffer declarations to ensure proper data packing.
  • Лучшим способом эффективного использования буферов констант является упорядочение переменных шейдера в буферах констант согласно частоте их обновления.The best way to efficiently use constant buffers is to organize shader variables into constant buffers based on their frequency of update. Например, если имеются однородные данные, которые обновляются с каждым кадром, и другие однородные данные, которые обновляются только при движении камеры, постарайтесь разделить эти данные в двух отдельных буферах констант.For example, if you have some uniform data that is updated once per frame, and other uniform data that is updated only when the camera moves, consider separating that data into two separate constant buffers.
  • Первым источником ошибок при компиляции шейдера (FXC) будет семантика, которую вы забыли применить или применили неверно.Semantics that you have forgotten to apply or which you have applied incorrectly will be your earliest source of shader compilation (FXC) errors. Тщательно проверяйте семантику!Double-check them! Источниками ошибок могут быть документы, поскольку на многих старых страницах и в примерах имеются ссылки на другие версии семантики HLSL, предшествующие версии Direct3D 11.The docs can be a bit confusing, as many older pages and samples refer to different versions of HLSL semantics prior to Direct3D 11.
  • Убедитесь, что вы понимаете, для какого уровня компонентов Direct3D вы разрабатываете каждый свой шейдер.Make sure you know which Direct3D feature level you are targeting for each shader. Семантика для уровня функций 9 _ * отличается от для 11 _ 1.The semantics for feature level 9_* are different from those for 11_1.
  • _Семантика положения SV разрешает связанные данные о расположении после интерполяции для координации значений, где x находится между 0 и шириной целевого объекта прорисовки, y — от 0 до высоты целевого объекта прорисовки, z — на исходном однородном координате w (z/w), а w — на единицу по исходному значению w (1/w).The SV_POSITION semantic resolves the associated post-interpolation position data to coordinate values where x is between 0 and the render target width, y is between 0 and the render target height, z is divided by the original homogeneous coordinate w value (z/w), and w is 1 divided by the original w value (1/w).

Инструкции: перенос простого обработчика OpenGL ES 2.0 в Direct3D 11How to: port a simple OpenGL ES 2.0 renderer to Direct3D 11

Перенос объектов шейдеровPort the shader objects

Перенос буферов вершин и данныхPort the vertex buffers and data

Рисование на экранеDraw to the screen