Код вершинного шейдера обводки силуэта
17.5.4. Код вершинного шейдера обводки силуэта
Настала пора представить код вершинного шейдера для визуализации силуэта. Основная задача шейдера заключается в определении того, является ли переданная вершина частью силуэта. Если да, то вершинный шейдер осуществляет сдвиг вершины на заданный скаляр в направлении вектора нормали вершины.
// Файл: outline.txt // Описание: Вершинный шейдер, отображающий силуэт
// // Глобальные переменные //
extern matrix WorldViewMatrix; extern matrix ProjMatrix;
static vector Black = {0.0f, 0.0f, 0.0f, 0.0f};
// // Структуры //
struct VS_INPUT { vector position : POSITION; vector normal : NORMAL0; vector faceNormal1 : NORMAL1; vector faceNormal2 : NORMAL2; };
struct VS_OUTPUT { vector position : POSITION; vector diffuse : COLOR; };
// // Точка входа //
VS_OUTPUT Main(VS_INPUT input) { // Обнуляем члены выходной структуры VS_OUTPUT output = (VS_OUTPUT)0;
// Преобразуем местоположение в пространство вида input.position = mul(input.position, WorldViewMatrix);
// Вычисляем вектор направления взгляда на вершину. // Вспомните, что в пространстве вида зритель находится // в начале координат (зритель это то же самое, что и камера). vector eyeToVertex = input.position;
// Преобразуем нормали в пространство вида. Компоненте w // присваиваем нуль, поскольку преобразуем векторы. // Предполагается, что в мировой матрице нет масштабирования input.normal.w = 0.0f; input.faceNormal1.w = 0.0f; input.faceNormal2.w = 0.0f;
input.normal = mul(input.normal, WorldViewMatrix); input.faceNormal1 = mul(input.faceNormal1, WorldViewMatrix); input.faceNormal2 = mul(input.faceNormal2, WorldViewMatrix);
// Вычисляем косинус угла между вектором eyeToVertex // и нормалями граней float dot0 = dot(eyeToVertex, input.faceNormal1); float dot1 = dot(eyeToVertex, input.faceNormal2);
// Если у косинусов разные знаки (один положительный, // а другой отрицательный) значит край является частью // силуэта if((dot0 * dot1) < 0.0f) { // Знаки разные, значит вершина является частью // края силуэта, смещаем позиции вершин на заданный // скаляр в направлении нормали вершины input.position += 0.1f * input.normal; }
// Преобразование в однородное пространство отсечения output.position = mul(input.position, ProjMatrix);
// Устанавливаем цвет силуэта output.diffuse = Black;
return output; }