Быстрый попиксельный вывод массива

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Быстрый попиксельный вывод массива

Сообщение D8M » 25.06.2006 (Вс) 0:14

Здраствуйте. Надеюсь в этот раз вы мне сможете помочь :)
Вот мой вопрос:
У меня есть массив (большой, 600х600 пикселов). Мне нужно попиксельно вывести содержимое этого массива на некоторый объект. Средства вб (PSet) работаею очень медленно. SetPixel работает, хотя и бысрее псета,но тоже медленно. Я реализовал вывод через DIB с прямой записью в граффические данные. Работает во много раз быстрее SetPixel. Отрисовка происходит менее чем за секунду (Pset~20 сек , SetPixel~6 сек). Теперь вопрос, как можно еще сильнее ускорить отрисовку? Здесь на форуме видел реплику о "прямой записи в память"... Как это реализовать?
Я не прошу готовую программу :) Просто подскажите. И что можно изменить в моем примере?
Вложения
gfx_test.rar
(1.74 Кб) Скачиваний: 268

Lumen
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 841
Зарегистрирован: 03.12.2005 (Сб) 16:09
Откуда: Брянск

Сообщение Lumen » 25.06.2006 (Вс) 0:24

Если знаком с Delphi и ассемблером, то советую почитать вот это:
Запись пиксела напрямую в видеопамять
Подпись проходит рефакторинг

Twister
Теоретик
Теоретик
Аватара пользователя
 
Сообщения: 2251
Зарегистрирован: 28.06.2005 (Вт) 12:32
Откуда: Алматы

Сообщение Twister » 25.06.2006 (Вс) 0:28

http://www.dotfix.net/module.php?module=@6e786b36726e7776636b75 писал(а):Данный модуль предназначен для демонстрации того, как можно
в DOS записать информацию о пикселе непосредственно в видеопамять
минуя прерывания BIOS.
А я все практикую лечение травами...

Lumen
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 841
Зарегистрирован: 03.12.2005 (Сб) 16:09
Откуда: Брянск

Сообщение Lumen » 25.06.2006 (Вс) 0:37

Ой... :oops:
Не обратил внимания. Честно говоря сам не пробовал, просто всплыло в памяти при виде темы поста. Не бейте сильно...
Подпись проходит рефакторинг

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 25.06.2006 (Вс) 0:55

Гм... :? Оно конечно весело! Спасибо. Но моя паскаль (это он?) не понимать! :oops: Можно на вб? Собственно "прямая запись в память" нужна только в том случае если нельзя будет без этого обойтись. Можно ли, как-то ускорить тот пример который дал я?

VT
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 22
Зарегистрирован: 22.06.2006 (Чт) 16:31
Откуда: Санкт-Петербург

Сообщение VT » 25.06.2006 (Вс) 1:04

Я реализовал вывод через DIB с прямой записью в граффические данные.
Посмотрел, реализовано через SetDIBitsToDevice.

Есть мощнее.
CreateDIBSection.
Эта функция возвращает указатель на данные диба, в который можно писать напрямую.
Но бяка в том, что в VB такой доступ требует некоторых приемов: надо создать массив, ссылающийся на этот самый указатель. По этому поводу есть статья.
А чтобы то, что было записано в диб, появилось на экране, надо всего лишь вызвать метод Refresh того объекта, в который этот диб выбран.

И еще замечу, что в этой самой программе долго происходит заполнение массива. А SetDiBitsToDevice выполняется моментально.

ALX_2002
Мега гуру
Мега гуру
 
Сообщения: 2054
Зарегистрирован: 25.11.2002 (Пн) 20:03

Сообщение ALX_2002 » 25.06.2006 (Вс) 8:49

http://bbs.vbstreets.ru/viewtopic.php?t=22245&highlight=
Я когда то тоже такое делал. Там примерчик есть. :roll:

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 25.06.2006 (Вс) 9:49

VT писал(а):
Я реализовал вывод через DIB с прямой записью в граффические данные.
Посмотрел, реализовано через SetDIBitsToDevice.

Есть мощнее.
CreateDIBSection.
Эта функция возвращает указатель на данные диба, в который можно писать напрямую.
Но бяка в том, что в VB такой доступ требует некоторых приемов: надо создать массив, ссылающийся на этот самый указатель. По этому поводу есть статья.
А чтобы то, что было записано в диб, появилось на экране, надо всего лишь вызвать метод Refresh того объекта, в который этот диб выбран.

И еще замечу, что в этой самой программе долго происходит заполнение массива. А SetDiBitsToDevice выполняется моментально.


А в чем разница между записью в указатель диба(тот же массив) и обычной записью в массив? Почему заполнение массива происходит долго? Как можно быстрее?

2ALX_2002:
В том примере на который ты дал ссылку проиходит такоеже, как и у меня заполнение массива PicBits :)

Debugger
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1667
Зарегистрирован: 17.06.2006 (Сб) 15:11

Сообщение Debugger » 25.06.2006 (Вс) 9:55

Что-то ниччё не понял... Всё на паскале, блин..

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.06.2006 (Вс) 13:25

Об работе с DIB-секциями, см. http://mix.web.ur.ru/rotate.html и сопутствующий тред.
Изображение

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 25.06.2006 (Вс) 14:01

Снова. :( Здесь на форуме так принято давать линки которые второстепенно относяться к теме? Ты смотрел тот пример что я дал? Нет, конечно же не смотрел. Там прямая запись в битмап. Все максимально оптимизировано (по-моему). А вопрос был: можно ли еще быстрее?

Да и еще разве сложение происходит быстрее чем умножение?
Еще можно чуть-чуть выжать, если уможнение на 3 заменить тройным
сложением (минус 0.8 сек на 30 циклов).

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 25.06.2006 (Вс) 14:39

Разумеется, сложение быстрее умножения.

Код: Выделить всё
Public Sub draw()
  Dim yc As Long, xc As Long
  Dim bi24BitInfo As BITMAPINFO, bDWords() As Long
 
  With bi24BitInfo.bmiHeader
    .biSize = Len(bi24BitInfo)
   
    .biBitCount = 32
    .biCompression = BI_RGB
    .biPlanes = 1
   
    .biWidth = 300
    .biHeight = 608
   
    ReDim bDWords(0 To .biWidth - 1, 0 To .biHeight - 1)
  End With
 
 
  For yc = LBound(bDWords, 2) To UBound(bDWords, 2)
    For xc = LBound(bDWords, 1) To UBound(bDWords, 1)
      bDWords(xc, yc) = ((vbRed And &HFF0000) \ &H1000000) Or (vbRed And &HFF00&) Or ((vbRed And &HFF&) * &H10000)
    Next xc
  Next yc
 
  SetDIBitsToDevice mfrm.hdc, 0, 0, bi24BitInfo.bmiHeader.biWidth, bi24BitInfo.bmiHeader.biHeight, 0, 0, 0, bi24BitInfo.bmiHeader.biHeight, bDWords(LBound(bDWords, 1), LBound(bDWords, 2)), bi24BitInfo, DIB_RGB_COLORS
End Sub
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

VT
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 22
Зарегистрирован: 22.06.2006 (Чт) 16:31
Откуда: Санкт-Петербург

Сообщение VT » 25.06.2006 (Вс) 14:54

Почему заполнение массива происходит долго? Как можно быстрее?
Я имел в виду процесс заполнения массива, а не вывод его на экран.

Цитирую код.
Код: Выделить всё
Sub draw()
    Dim yc As Integer, xc As Integer
   
    Dim bi24BitInfo As BITMAPINFO, bBytes() As Byte, Cnt As Long
    With bi24BitInfo.bmiHeader
        .biBitCount = 24
        .biCompression = BI_RGB
        .biPlanes = 1
        .biSize = 40
        .biWidth = 608
        .biHeight = 608
    End With
    ReDim bBytes(1 To bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight * 3) As Byte
   
    'заполнение массива
    For yc = 0 To 607
        For xc = 0 To 607
            GFX_SET_PIXEL_DIB bBytes, xc, yc, vbRed, bi24BitInfo.bmiHeader.biWidth
        Next xc
    Next yc
   
    'вывод на экран
    SetDIBitsToDevice mfrm.hdc, 0, 0, bi24BitInfo.bmiHeader.biWidth, bi24BitInfo.bmiHeader.biHeight, 0, 0, 0, bi24BitInfo.bmiHeader.biHeight, bBytes(1), bi24BitInfo, DIB_RGB_COLORS
End Sub

Sub GFX_SET_PIXEL_DIB(ByRef obj() As Byte, ByVal sX As Long, ByVal sY As Long, zColor As Long, hWidth As Long)
    Dim dibX As Long, dibY As Long
    Dim cNum As Long
    Dim R As Byte, G As Byte, B As Byte
   
    dibX = sX + 1: dibY = hWidth - sY
    cNum = (hWidth * (dibY - 1) + dibX) * 3 - 2
    R = zColor \ 65536
    G = (zColor And 65535) \ 256
    B = zColor And 255
   
    obj(cNum) = R
    obj(cNum + 2) = B
    obj(cNum + 1) = G
End Sub
Во-первых. Чтобы быстрее происходило заполнение, надо вынести код процедуры прямо в цикл. Муторно, но поможет. (в варианте от GSerg сделано)
Во-вторых. Зачем для каждого пикселя разбивать vbRed на компоненты, если это можно сделать вне цикла. (в варианте от GSerg не сделано, но реально как правило цвета различны и сделать это не представляется возможным)
В-третьих. Сделать из двухмерного цикла одномерный и не считать произведение ширины на игрек (в варианте от GSerg не сделано, хотя умножение ушло из явного кода в неявный)
И последнее. Скомпилировать, желательно с оптимизацией Remove Array Bounds Checks. (компиляция сильно ускоряет, до 10 раз)

Заполнение можно еще ускорить, если заполнить красным только первую строчку рисунка, а затем все остальные копировать из первой путем CopyMemory. Это даст ускорение в ~3 раза.

И тогда это будет работать в мгновение ока. И по хорошему, действительно НЕ нужно никаких хитростей с CreateDIBSection.

Однако, использование CreateDIBSection позволит еще немного ускорить, так как не потребуется вызов SetDIBitsToDevice и не будет лишнего копирования.

Ну и напоследок. Вот это
Код: Выделить всё
1 to bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight * 3
неверно. Сделай ширину картинки не кратной 4 и программа перестанет работать (может сработает, а может вылетит с Access Violation). Причина в том, что ширина массива в байтах должна быть кратна 4. То есть выровнена на границу двойного слова.
Исправить можно так:
Код: Выделить всё
1 to ceil(.biWidth*3 / 4)*4 * .biHeight

public function Ceil(byval Value as double) as long
ceil=-int(-value)
end function
Кстати и код заполнения массива тоже придется поправить.
Можно исправить проще: сделать рисунок глубиной 32 бита, тогда выравнивание будет выполнено всегда автоматом. Так сделано у GSerg.

И последнее.
Внутри процедуры GFX_SET_PIXEL_DIB значения B и R перепутаны местами два раза, и в результате работает правильно.
Первый раз здесь: R = zColor \ 65536 на самом деле возвращает синее;
Второй раз тут: obj(cNum) = R должен писать R туда, где находится синий, но так как в R уже синий, все нормально.
В массиве для каждого пикселя сначала записывается Blue, затем Green и Red. Наоборот по сравнению с байтовым содержимым переменной Long RGBцвет.


Ой! Еще не сразу заметил. Вот здесь
Код: Выделить всё
    dibX = sX + 1: dibY = hWidth - sY
ошибка, которая не даст программе работать, если рисунок не квадратный. Вместо Width там надо сделать Height.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.06.2006 (Вс) 16:40

D8M писал(а):Снова. :( Здесь на форуме так принято давать линки которые второстепенно относяться к теме? Ты смотрел тот пример что я дал? Нет, конечно же не смотрел. Там прямая запись в битмап. Все максимально оптимизировано (по-моему). А вопрос был: можно ли еще быстрее?

А ты мой код смотрел? Нет, конечно же не смотрел. Там показано, что даже при прямой записи в битмап можно получить разницу по скорости в два раза -- всё зависит от того, как именно эту прямую запись организовать.

D8M писал(а):Да и еще разве сложение происходит быстрее чем умножение?
Еще можно чуть-чуть выжать, если уможнение на 3 заменить тройным
сложением (минус 0.8 сек на 30 циклов).

Да, быстрее. А использование массива Long, вместо байтового с умножением на 3 либо тройным сложением -- ещё быстрее.
Изображение

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 25.06.2006 (Вс) 18:40

Ну вот! :) Другое дело! :D

VT
1) Цвета разбиваю на ргб, поскольку красный это просто пример. Каждый пиксел будет иметь свой цвет.
2) Копирование первой строки не подойдет см.1.
3) Диб попробую, но разницы не будет по-моему не будет :wink:
Как я понимаю самая "трудоемкая" часть это зааполнение массива, а не вывод. (твои слова :))

tyomitch
Извени погорячился. :oops: Твой код смотрел, даже все сообщения прочитал. А почему не скачиваються версии выше 5й?
А, как так получаеться что сложение работает быстрее? Умножение это ведь тоже самое. :?

Вот новый код напсал: (основываясь на ваших советах)
Код: Выделить всё
Sub draw()
bitmap_set 'установка инфы о рисунке

    Dim xc As Long
    Dim bBytes() As Long
   
    ReDim bBytes(0 To bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight - 1)
 
  For xc = LBound(bBytes) To UBound(bBytes)
        bBytes(xc) = vbBlue
  Next xc
 
  SetDIBitsToDevice mfrm.hdc, 0, 0, bi24BitInfo.bmiHeader.biWidth, bi24BitInfo.bmiHeader.biHeight, 0, 0, 0, bi24BitInfo.bmiHeader.biHeight, bBytes(0), bi24BitInfo, DIB_RGB_COLORS
End Sub


Прикольно, что R и B опять перепутаны, непойму почему... :?
Как еще можно ускорить?

Ах да. Спасибо GSerg:)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 25.06.2006 (Вс) 18:49

D8M, а можно посмотреть на твою реальную задачу, вместо равномерно-красного сферического коня в вакууме? наверняка там есть какая-то специфика, которая позволит всё дополнительно ускорить.

D8M писал(а):А почему не скачиваються версии выше 5й?

Только что проверил, скачиваются все (1..8)
Изображение

VT
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 22
Зарегистрирован: 22.06.2006 (Чт) 16:31
Откуда: Санкт-Петербург

Сообщение VT » 25.06.2006 (Вс) 19:19

Прикольно, что R и B опять перепутаны, непойму почему...
Попробую объяснить.
В общем причина - разные форматы для одиночного цвета и для пикселя диба.

в массиве пиксель хранится так:
байт B
байт G
байт R
[байт reserved, иногда alpha] - это если 32 бита/пикс.
можно назвать форматом BGRA

Цвет в VB (и в апи, когда не в массиве) хранится так:
байт R
байт G
байт B
байт reserved
Все это засунуто в переменную типа Long
Можно назвать форматом RGBA
По этому bBytes(xc) = vbBlue превращает синий в красный, а красный в синий.

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

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 26.06.2006 (Пн) 13:02

tyomitch
Реальная задача такая:
1) Массив заполнееться фоновым цветом (здесь для примера дан красный)
2) По определенному адресу записываеться 361(19*19) пикселов с цветом тени.
3) По определенному адресу записываеться 361(19*19) пикселов из другого массива содержащего изображения тайлов.
4) После того, как изображение подготовлено (в массиве) происходит его вывод на экран.

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

VT
Про RGBA и BGRA я знал давно, просто я не могу понять зачем они так сделали!? :)

VT
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 22
Зарегистрирован: 22.06.2006 (Чт) 16:31
Откуда: Санкт-Петербург

Сообщение VT » 26.06.2006 (Пн) 14:11

Ну про заполнение фоном я уже писал. CopyMemory поможет. А 19*19 записываться должно быстро, так как 19*19 - это мало. Их можно писать любым способом. Лучше всего CopyMemory, если та картинка соответствует по формату. А заполнять цветом тени можно так же, как с очисткой: заполняем первую строчку прямоугольника тени, остальные CopyMem'им в строчки ниже.

А вообще для таких простых операций может быть лучше использовать методы GDI или даже VB.

Вот например.
Очистка: устанавливаем .BackColor, вызываем .Cls.
Чтоб прямоугольник тени нарисовать, вызываем .Line(x1,y1)-(x2,y2),цветтени,BF

Чтоб рисунок 19*19 вывести из массива, применяем SetDIBitsToDevice с нужными координатами.
Все это лучше делать с включенным AutoRedraw. Так стопудово сработает и мелькать не будет.

А вообще я кое-что подобное недавно делал. Там рисуночки размером 32*32 заполняют почти весь экран. Добился скорости 150fps, и это без учета вызова .Refresh. Вот вложение. Еще есть тема по обсуждению похожей проблемы на вбнете, которую я сам завел.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 26.06.2006 (Пн) 14:26

Код: Выделить всё
    Dim xc As Long
    Dim bBytes() As Long
   
    ReDim bBytes(0 To bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight - 1)
 
  For xc = LBound(bBytes) To UBound(bBytes)
        bBytes(xc) = vbBlue
  Next xc
Конкретно этот код можно извратить так:
Код: Выделить всё

    Dim bBytes() As Long
    Dim r() as Byte
    Dim c1(3) as Byte
    Dim c2(3) as Byte
    ReDim bBytes(0 To bi24BitInfo.bmiHeader.biWidth * bi24BitInfo.bmiHeader.biHeight - 1)
    ReDim r(0 To (UBound(bBytes) + 1) * 4 - 1)
    c2(2) = 255 'vbBlue
    r = StrConv(Replace(StrConv(r, vbUnicode), StrConv(c1, vbUnicode), StrConv(c2, vbUnicode)), vbFromUnicode)
    CopyMemory bBytes(0), r(0), UBound(r) + 1
Я так полагаю, будет быстрее. А если еще воспользоваться не стандартным реплейсом, а 11ым отсюда, то будет еще быстрее. Можешь попробовать его модифицировать, чтобы работал непосредственно с байтовыми массивами, тогда StrConv не понадобится.
Лучший способ понять что-то самому — объяснить это другому.

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 26.06.2006 (Пн) 17:46

VT
Вобщем то с начала все делалаось стандартными средствами, но это не совсем удобно, мне нужно сначала подготовить картинку а потом выводить, так-как возможно будет еще какието операции с картинкой. Да и по-моему один SetDIBitsToDevice будет бытрее чем 1024 тайла выводить SetDIBitsToDevice... :) Или нет?
Действительно буду использовать CopyMemory, он похоже бытрее заполняет.
А как фпс измерить?Вставить отрисовку в цикл и каждый раз добавлять к фпс +1, а каждую секунду по таймеру выводить на экран и обнулять?

Antonariy
Ужасы каие! :shock: Твой код отрисовует форму гдето ~ в 25 раз медленее.... :?

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 26.06.2006 (Пн) 19:11

Да уж... :?
Вот и конец, можно забыть о подготовке массива в памяти и последующем его выводе. Провел ряд тестов и был в ужасе. Буду делать, как сказал VT, фон заливать Cls, а тайлы выводить SetDIBitsToDevice.

Вобщем вот этот ужасный тест:
ФПС СПОСОБ
30 - Заполнение массива юзая CopyMemory
125 - SetDIBitsToDevice по одной линии
295 - bbyte(xc) = color прямая запись в каждый пиксел
...и безусловный лидер: :?
9000 - CLS

После этого я решил забыть о предворительной подготовке рисунка в массиве. Ладно еслиб разница была 100 фпс, а так ведь 8700 фпс разницы, это многовато. Поэтому буду юзать cls. ))))

Всем большое спасибо.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Сообщение Mikle » 26.06.2006 (Пн) 19:18

D8M
Глянь тему:
http://bbs.vbstreets.ru/viewtopic.php?t=24007
Тут вывод через SetDIBitsToDevice, а все формирование изображения в процедурах на асме, может поможет?

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 26.06.2006 (Пн) 19:51

Нда, не проверял. :oops:
Лучший способ понять что-то самому — объяснить это другому.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 26.06.2006 (Пн) 20:11

В 19,43 раза :wink:
Лучший способ понять что-то самому — объяснить это другому.

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 26.06.2006 (Пн) 23:07

Mikle
Я это видел :) Я форум читаю изредка :)
Но мне не нужна лишняя дллка. К тому же я вобще забил на DIB секции. Просто я отрисовывал на экран тайлы 32*32. 20*15 тайлов отрисовывалось SetDIBitsToDevice гдето 150 фпс. А потом ради интереса применил BitBlt и получилось 600 фпс :)

Теперь у меня 4 других вопроса:
1)
Свойство autoredraw=true берет 50-100 фпс, если его отключить форма мерцает. Как обновлять форму без мерцания при autoredraw=false?

2)
Как работает cls? Что он делает? Всмысле понятно что заполняет окно фоновым цветом, но как он это делает физизически? Ведь он тоже присваивает цвет попиксельно... Но когда я присваиваю цвет попиксельно получается максимум 500 фпс, а при cls 8000-9000 фпс. Какой механизм работы cls?

3)
Это нормально? 8000 фпс при чистом экране (каждый раз очищаеться) и 600 при затайленом? Стоит ли еще ускорять?

4)
Что я получу если сделаю все тоже только используя DirectDraw?

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 26.06.2006 (Пн) 23:20

D8M писал(а):К тому же я вобще забил на DIB секции. Просто я отрисовывал на экран тайлы 32*32. 20*15 тайлов отрисовывалось SetDIBitsToDevice гдето 150 фпс. А потом ради интереса применил BitBlt и получилось 600 фпс :)

Разве эти две функции взаимозаменяемы?

D8M писал(а):Свойство autoredraw=true берет 50-100 фпс, если его отключить форма мерцает. Как обновлять форму без мерцания при autoredraw=false?

Рисовать в невидимый буфер, потом отрисовывать картинку целиком. Причём в событии _Paint, а не абы где.

D8M писал(а):Как работает cls? Что он делает? Всмысле понятно что заполняет окно фоновым цветом, но как он это делает физизически? Ведь он тоже присваивает цвет попиксельно... Но когда я присваиваю цвет попиксельно получается максимум 500 фпс, а при cls 8000-9000 фпс. Какой механизм работы cls?

А RtlFillMemory вместо своего цикла -- пробовал?
Изображение

D8M
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 06.07.2005 (Ср) 12:45

Сообщение D8M » 26.06.2006 (Пн) 23:40

tyomitch
Разве эти две функции взаимозаменяемы?

Понятно что нет. :wink: Просто для SetDIBitsToDevice в качестве "картинки" я использовал массив, а для BitBlt я тот же массив сначала рисовал в отдельный hDC, либо в пикчурбокс.

Рисовать в невидимый буфер, потом отрисовывать картинку целиком. Причём в событии _Paint, а не абы где.

Гм... :oops: Что за "невидимый буффер"? И как "отрисовывать картинку целиком"? Названия функций хоть скажи :)

А RtlFillMemory вместо своего цикла -- пробовал?

Так вроде всеравно прийдется каждый элемент массива RtlFillMemory заполнять... Или нет? Как без цикла заполнить сразу весь массив?

Вопрос остается: Насколько быстрее будет DirectDraw? Раз в 5?

И еще вот http://dotfix.net/module.php?module=@6e786b366778717771776231 стоит ли?

VT
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 22
Зарегистрирован: 22.06.2006 (Чт) 16:31
Откуда: Санкт-Петербург

Сообщение VT » 27.06.2006 (Вт) 0:24

Ой. Я еще быстрее очистку нашел.

Я не поверил в такую скорость cls и проверил сам для интереса. Вот что получилось у меня.

Самый первый метод с сабом:
49fps

Второй метод, заполнение массива long'ов
94fps

Третий метод, CopyMemory
94fps

Четвертый метод, cls
1280fps
в 14 раз быстрее, чем заполнением массива long'ов

Пятый метод, Line()-(),,BF
8000 fps!!! :shock:
в 85 раз быстрее, чем заполнением массива long'ов

Ну и для интереса шестой метод. Dib Section, то есть просто очистка массива без вывода на экран.
317fps
тестировал на Lichita, там очистка по CopyMemory


На счет cls'а, как он работает - точно не знаю, но думаю так: Cls просто тупо убирает и удаляет привязанный битмап. Собственно очистка происходит по пришествию очередного WM_PAINT, а если применить графический метод, очистка (а заодно создание нового привязанного битмапа) будет произведена перед его выполнением (при тесте cls это я учел, поставив сразу после .cls вызов .pset).

Почему вообще такое творится?? Не знаю. Может видюха помогает? У меня проц сравнительно слабый (Celeron 1,7ghz), зато видюха мощная (GeForce6600GT)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 27.06.2006 (Вт) 0:42

D8M писал(а):
Рисовать в невидимый буфер, потом отрисовывать картинку целиком. Причём в событии _Paint, а не абы где.

Гм... :oops: Что за "невидимый буффер"? И как "отрисовывать картинку целиком"? Названия функций хоть скажи :)

Дык названия все те же: CreateDIBSection и BitBlt.

D8M писал(а):
А RtlFillMemory вместо своего цикла -- пробовал?

Так вроде всеравно прийдется каждый элемент массива RtlFillMemory заполнять... Или нет? Как без цикла заполнить сразу весь массив?

RtlFillMemory заполняет весь массив за раз.
Изображение

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 11

    TopList