Статьи / Первый шейдер

Первый шейдер


Отправить ссылку:

Первый шейдер.

Для начала поставим себе цель – имея все эти данные, написать шейдер, который будет просто и без изысков выводить одним цветом на экран наш меш. То есть, пока даже нет никакой речи о расчёте освещения и чего-либо ещё.
Чтобы уметь писать шейдеры, надо знать, как происходит вывод на экран графики.
Итак, выполним нашу задачу сначала обычными средствами. Что у нас есть? Меш который представлен одним полигоном(треугольником). Предположим, что координаты его вершин равны предположим: А(0,10,10) В(0,0,10) С(5, 0, 0). Ну и само собой у нас есть три матрицы: мировая, вида и проекции. Не будем перечислять данные, хранимые в них. Отметим лишь, что меш и камера в пространстве должны выглядеть так, как на рисунке:
камера в пространстве
Для удобства, экран, на который будет выводиться изображение, имеет разрешение 300 на 200. В общем, виде без использования шейдера код будет выглядеть:

//ставим матрицу вида
pMainDirect3DDevice -> SetTransform (D3DTS_VIEW, &MatrixView); 
//ставим мировую матрицу
pMainDirect3DDevice -> SetTransform( D3DTS_WORLD,&MatrixWorld ); 
//ставим матрицу проекции
pMainDirect3DDevice -> SetTransform( D3DTS_PROJECTION, &MatrixProjection ); 
//рисуем модель
for( k = 0; k < amountSubsets; k++) 
{ 
  pMesh -> DrawSubset(k);
}
//выводим нарисованное на экран
pMainDirect3DDevice -> Present( NULL, NULL, NULL, NULL );
На экране результат операции будет выглядеть так:
unick-soft изображение треугольника на экране
Настал момент разобраться, как это получилось. Откроем Маткад или подобную программу и посчитаем в ней произведение трёх наших матриц в таком порядке: Мировая*Вида*Проекции. Запомним результат. Возьмём одну из вершин меша, предположим С с координатами (5, 0, 0). Координаты (5, 0, 0) - это вектор. Умножим произведение матриц на этот вектор. Что мы получим? Тоже вектор. Самое интересное чему равны координаты этого вектора. Первые две из них будут равны (забудем пока о третьей) 0 и 50. Если мы сделаем тоже самое над двумя другими вершинами, то мы получим для B: (0 и 0) , для А: (75 и 0). А теперь дружно посмотрели на рисунок. Поняли принцип? Если нет, то поясню. Наш экран это двухмерная система координат с центром в центре(извиняюсь за тафтологию). Поэтому, чтобы получить вершину С по оси Х мы откладываем 0, а по оси Y откладываем 50. И так же для других двух вершин. Компьютер, имея эти три пиксела на экране остальные пикселы между ними достраивает сам.
Примечание: Если у вершин разные цвета, то он строит остальные пикселы с таким цветом, что получается плавный переход между вершинами(интерполируе их):
unick-soft треугольник c градиентной заливкой
То, что до этого момента делал компьютер, теперь нам, вручную, нужно будет делать в шейдере. Замечу, что произведение трёх матриц придётся считать перед запуском шейдера:
Вот собственно код шейдера:
// произведение матриц запишется в эту 
// переменную и будет храниться в константных регистрах
float4x4 worldViewProj; 

struct OUTPUT_DATA  
{
  float4 pos  : POSITION;
};

struct INPUT_DATA
{ 
  float4 Pos  : POSITION; 
};

OUTPUT_DATA  ShaderFunc(INPUT_DATA input)
{
    //обнуляем данные
    OUTPUT_DATA  Out = (OUTPUT_DATA)0; 
    //умножаем произведение матриц на позицию
    Out.pos = mul(input.Pos, worldViewProj); 
    // возвращаем новую вершину
    return Out; 
}

//необходимо для работы шейдера
technique Transform   
{ 
    pass P0    
    {
        VertexShader = compile vs_1_1 ShaderFunc();
    }
}

Слова POSITION в структурах OUTPUT_DATA и INPUT_DATA обязательны. Ну, вот и всё. Поздравляю с первым шейдером. В следующий раз мы будем постепенно усложнять его. Я не описываю, как заставить работать этот код в приложении – вы можете сами найти это в интернете.
Успехов!
При полном или частичном копировании необходимо указывать ссылку на данную статью.

Гузенко Юрий.

Юрий (Дата )

Все вопросы и предложения высылайте на адрес soft_support@list.ru. Необходимо в заголовке указать название статьи.

Оставь свой отзыв


Ответьте на вопрос (ответ маленькими буквами)* :
4 + 6 - пять(ответ цифрами)


Дата: 03.02.09