Простой эффект свечения/размытия HLSL в DirectX9

Я изо всех сил пытался найти какие-либо ресурсы, которые помогли бы мне написать простой шейдер свечения/размытия с использованием языка шейдеров высокого уровня и управляемых библиотек DirectX 9.

Все, что мне нужно сделать, это иметь массив из CustomVertex.TransformedColored вершин, нарисованных в виде простых линий, а затем размытых/светящихся с помощью эффекта HLSL.

Я искал в Интернете около трех дней с некоторыми результатами, но я просто не могу найти действительно хороший учебник или пример. У меня есть базовое понимание HLSL, но я недостаточно понимаю, чтобы понять, как написать этот шейдер (я также прочитал главу о HLSL в трех книгах по DirectX).

Вот некоторый (сокращенный) код:

CustomVertex.TransformedColored[] glowVertices = new CustomVertex.TransformedColored[4];
glowVertices[0] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Cyan.ToArgb());
glowVertices[1] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Blue.ToArgb());
glowVertices[2] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Cyan.ToArgb());
glowVertices[3] = new CustomVertex.TransformedColored(random.Next(this.render.Width), random.Next(this.render.Height), 1, 1, Color.Blue.ToArgb());

this.device.BeginScene();
int passes = this.glowEffect.Begin(0);
for (int i = 0; i < passes; i++)
 {
     this.glowEffect.BeginPass(i);
     this.device.DrawUserPrimitives(PrimitiveType.LineStrip, glowVertices.Length - 1, glowVertices);
     this.glowEffect.EndPass();
 }
 this.glowEffect.End();
 this.device.EndScene();

Думаю, я не столько ищу помощи по какой-то конкретной части HLSL, учитывая количество вопросов и объем кода, который мне придется опубликовать, я действительно просто ищу помощь в поиске ресурсов!


person tbridge    schedule 22.11.2010    source источник


Ответы (1)


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

Чтобы обойти это, основной процесс создания эффекта размытия (например, для свечения или цветения) заключается в отрисовке сцены, которую вы хотите размыть, к цели рендеринга. Затем используйте эту цель рендеринга в качестве текстуры на полноэкранном четырехугольнике, который вы рисуете с помощью шейдера размытия. Простой шейдер размытия берет несколько сэмплов этой текстуры, каждый со слегка смещенной координатой текстуры. В результате получается размытое изображение текстуры.

Обычно вы повторяете этот процесс (теперь рендеринг цели рендеринга на полноэкранном квадрате в другую цель рендеринга), выполняя одно размытие по горизонтали и одно по вертикали, чтобы получить максимальное размытие с наименьшим количеством сэмплов.

Я рекомендую ознакомиться с примером XNA Bloom. Там есть более подробная документация по процессу. Хотя API — это XNA, а не DirectX, они очень похожи и оба используют HLSL.

person Andrew Russell    schedule 22.11.2010
comment
Да, наверное, я не слишком ясно выразился. Я знаю все, что вы сказали, я визуализирую линии в текстуру, применяю ее к четырехугольнику и визуализирую этот четырехугольник с помощью своего HLSL. Я предполагаю, что я ищу аспект HLSL, который будет соответствовать этому. Спасибо за образец Блума, я посмотрю на него :) - person tbridge; 23.11.2010
comment
Пример оказался очень полезным. Наконец, простой/мощный пример HLSL, в котором не было сотен линейных шейдеров. - person tbridge; 23.11.2010