Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DirectX.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.15 Mб
Скачать

Урок 10. Различные шейдеры DirectX11

В предыдущем уроке мы произвели обзор языка HLSL. В этом уроке мы разберем пару конкретных примеров шейдеров.

Шейдеры

В этом уроке, как и в предыдущем мы не будем разбирать код приложения. Мы рассмотрим код самих шейдеров. Единственный случай, когда мы обратимся к коду приложения – это когда мы будем назначать различные шейдеры различным объектам. В приложении два вида шейдеров и вы должны представлять, как назначать их объектам, наподобие материалов.

Шейдер для эффекта bump

Эффект bump широко используется  для детализации поверхности модели текстурой выпуклостей, еще называемой normalmap. Шейдер для этого эффекта на рисунке имеет шар под номером два. Рассмотрим код пиксельного шейдера этого эффекта:

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

// Pixel Shader

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

float4 PS1( VS_OUTPUT input ) : SV_Target

{

     input.Tex.y*=4.0f;

      float3 bump=txDiffuse[1].Sample(samLinear,input.Tex)*2.0f - 1.0f;

      float shine=dot((float3)input.L0,normalize(bump)); shine+=dot((float3)input.L1,normalize(bump));

      float4 ambient=txDiffuse[0].Sample(samLinear,input.Tex)*input.Diffuse;

      return ambient*(shine*0.5f)+pow(shine,4) * input.Diffuse*0.1f+ambient*0.5f+float4(0.1f,0,0.1f,0);

}

Во первых, на что стоит обратить внимание здесь, это то, что в шейдере используется две текстуры – одна это обычная текстура поверхности txDiffuse[1] и другая текстура для образования выпуклой фактуры поверхности txDiffuse[0]. Эта текстура имеет определенный формат наложения цветов, расположенный таким образом, чтобы цвет из этой текстуры мог использоваться как вектор. Таким образом, основная операция освещения для эффекта bump это вычисление параметра shine, который получается умножением двух векторов – первый вектор input.L0 — это вектор от текущей вершины до точки камеры, — а второй вектор берется из цвета текстуры. При этом используется два источника освещения, таким образом передается два вектора для них L0 и L1.

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

Шейдер для эффекта металлической поверхности

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

Таким образом, главное что отличает металлический эффект освещения от обычного, диффузного – это то, что правило – чем прямее угол падения луча на предмет, тем он светлее – для металлов не сохраняется. Здесь действует другое правило – участок металлического предмета светлее всего в тех местах, где луч, проведенный из точки зрения наблюдателя к поверхности металла, отражаясь попадет на источник освещения. И наоборот, если такой луч попадет не на источник света, а куда-нибудь еще, то значит в этих местах металл темный.

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

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

// Vertex Shader

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

VS_OUTPUT VS( float4 Pos : POSITION, float4 Normal : NORMAL, float2 Tex: TEXCOORD)

{

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=float4(0.0f,0.0f,0.0f,0);

      float4 lviewvec=normalize(vView-Pos);

float4 lviewvec=mul(View,float4(0,0,1,0));    

 

      for (int i=0; i<2; i++)

      {

      float3 lpos=(float3)vLightPosition[i];

      float a=dot(normalize(Normal),normalize(lpos-(float3)Pos));

      float b=dot(normalize(Normal),(float3)lviewvec);

      float c=1.0f/(1.0f+(a-b)*(a-b)*5); c=pow(c,5);

      output.Color+=vLightColor[i]*c;

      }

output.N=Normal;

      output.L=lviewvec;

}

Разберем код вершинного шейдера для эффекта металла. Переменная, хранящая интенсивность цвета здесь – output.Color. Эта переменная наполняется в два прохода: каждый проход для одного из источников освещения. Каждый источник освещения может иметь свой цвет. Основная операция для освещения здесь – вычисление коэффициентов a и b. Коэффициент a обозначает угол между нормалью и источником освещения. Коэффициент b обозначает угол между нормалью и точкой наблюдателя. Если углы совпадают, и эти два числа равны значит угол падения равен углу отражения, и в такой точке металл должен обладать ярким свечением. Если коэффициенты различаются, значит углы разные и источник света в данной точке и под данными углами либо не отражается совсем, либо отражается лишь слегка. Теперь разберем пиксельныйшейдер для нашего эффекта:

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

// Pixel Shader 0

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

float4 PS0( VS_OUTPUT input ) : SV_Target

{

      float3 refl=reflect((float3)input.L,(float3)input.N);

      return input.Color+txCube.Sample(samLinear,refl)*0.8f+float4(0.1f,0,0.1f,0);

}

Так как эффект блеска источников освещения уже рассчитан, то, вообщем, мы могли бы просто сделать returninput.Color; Однако металл может отражать и что-то еще кроме источников света, поэтому в этом примере добавлена карта отражения, представленная в виде кубической текстуры. Для того, чтобы осуществить выборку из кубической текстуры, — в отличие от двухмерной текстуры, в которой нужно для выборки двухкомпонентный вектор, — в кубической текстуре нужно для выборки обычный трехкомпонентный вектор. Причем этот вектор должен быть рассчитан встроенной функцией reflect. В общем, наш пиксельный шейдер для металлической поверхности получился компактным и прозрачным. Это произошло благодаря тому, что большая часть эффекта металлической поверхности была рассчитана в вершинномшейдере.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]