Как установить цвет одного пикселя в текстуре Direct3D? - PullRequest
4 голосов
/ 04 мая 2009

Я пытаюсь нарисовать 2D-изображение на экране в Direct3D, что, как я полагаю, должно быть сделано путем сопоставления текстуры с прямоугольным многоугольником рекламного щита, проецируемым на весь экран. (Я не заинтересован или не могу использовать Direct2D.) Вся информация о текстуре, которую я нашел в SDK, описывает загрузку растрового изображения из файла и назначение текстуры для использования этого растрового изображения, но я пока не нашел способа манипулировать текстура как растровое изображение пиксель за пикселем.

Что мне действительно нравится, так это функция, такая как

void TextureBitmap::SetBitmapPixel(int x, int y, DWORD color);

Если я не могу установить пиксели непосредственно в объекте текстуры, нужно ли сохранять массив DWORD, который является растровым изображением, а затем назначать текстуру этому каждому кадру?

Наконец, хотя я изначально предполагаю, что буду делать это на процессоре, расчеты цвета на пиксель, вероятно, также можно выполнять на графическом процессоре. Является ли код HLSL, который устанавливает цвет отдельного пикселя в текстуре, или пиксельные шейдеры полезны только для изменения пикселей дисплея?

Спасибо.

1 Ответ

4 голосов
/ 04 мая 2009

Во-первых, ваш прямой вопрос:

Технически вы можете установить пиксели в текстуре. Для этого потребуется использовать LockRect и UnlockRect API.

В контексте D3D «блокировка» обычно относится к передаче ресурса из памяти графического процессора в системную память (тем самым отключая его участие в операциях рендеринга). После блокировки вы можете изменить заполненный буфер по своему усмотрению, а затем разблокировать, то есть перенести измененные данные обратно в графический процессор. Обычно блокировка считалась очень дорогой операцией, но, начиная с PCIe 2.0 , это, вероятно, больше не является серьезной проблемой. Вы также можете указать небольшой (даже 1-пиксельный) RECT в качестве второго аргумента для LockRect, тем самым требуя передачи в память незначительного объема данных, и надеяться, что драйвер действительно достаточно умен, чтобы передавать только это (я знаю, для факта что в старых драйверах nVidia это было не так).

Более эффективный (и интенсивный по коду) способ достижения этого - никогда не покидать графический процессор. Если вы создадите текстуру в качестве RenderTarget (то есть укажите D3DUSAGE_RENDERTARGET в качестве аргумента using ), вы можете установить ее в качестве пункта назначения конвейера перед выполнением любых вызовов отрисовки, и написать шейдер (возможно передавая параметры ), чтобы нарисовать ваши пиксели. Такое использование целей рендеринга считается стандартным, и вы сможете найти множество примеров кода вокруг - но, если вы уже не столкнулись с проблемами производительности, я бы сказал, что это излишнее количество для одного 2D билборда.

НТН.

...