Функции рисования 2d графики (библиотеки vectors и buf2d)

Discussing libraries simplifying applications development
  • andrew_programmer
    Я бы в начале функции проверку на выход за границы изменил бы на такую:

    Code: Select all

    if  ( (x>screen.size_x-1) || (y>screen.size_y-1) || (x<0) || (y<0) )
             return;
  • Да, для отдельных пикселей лучше так.
    Эта проверка границ у меня взята из вывода геометрических примитивов. Там просто так отсекать вывод по границам нельзя. Видимо забыл поменять код. Когда дело дойдёт до полной оптимизации функций рисования, то я всеми этими вещами займусь.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • что-бы не мигало и быстрее выводило при прорисовке добавил возможность вывода через буфер. Появилось 5 функций для работы с буфером (создание, удаление, очистка, вывод на экран, установка активного буфера). Пока поддерживается только 1 буфер, но в будущем можно будет расширить их число.
    Старый вариант работы, с выводом на экран тоже возможен. В архиве 2 программы используют буфер, остальные рисуют напрямую в экран.
    Шрифт вроде стал работать быстрее.
    Attachments
    vectors_091005.7z (22.14 KiB)
    Downloaded 427 times
  • переделал еще 1 пример под буфер, точно быстрее выводит :D
    Attachments
    bug_buf.7z (6.13 KiB)
    еще 1 пример с буфером
    Downloaded 423 times
  • вообще супер! =)
    И мы уже давно не пешки,
    Мы пули, мы орлы, и решки!
    Война ютит бинарный код,
    Умри, или иди вперед!
  • В коде попиксельного рисования в буфере желательно заменить вот это:

    Code: Select all

    drawpixel_buf:
      bt bx,15
      jc @f
      bt cx,15
      jc @f
      cmp bx,word[active_buffer_w]
      jge @f
      cmp cx,word[active_buffer_h]
      jge @f
      push edi esi
      mov edi,dword[active_buffer] ;ptr - pointer to buffer
      mov esi,ebx ;esi=coord x
      imul esi,3 	;x*3
      add edi,esi	;ptr+x*3
    
      xor esi,esi
      mov si,word[active_buffer_w] ;size x
      imul esi,ecx ;size_x*y	
      imul esi,3	;size_x*y*3
      add edi,esi	;ptr+x*3+size_x*y*3
      mov word[edi],dx ;
      ror edx,16		
      mov byte[edi+2],dl
      ror edx,16
      pop esi edi
      @@:
      ret
    
    хотя бы на это

    Code: Select all

     drawpixel_buf:
      bt bx,15
      jc @f
      bt cx,15
      jc @f
      cmp bx,word[active_buffer_w]
      jge @f
      cmp cx,word[active_buffer_h]
      jge @f
      push esi
      xor esi,esi
      mov si,word[active_buffer_w] ;size x
      imul esi,ecx	;size_x*y
      add esi,ebx	;size_x*y+x
      lea esi,[esi+esi*2] ;(size_x*y+x)*3
      add esi,dword[active_buffer] ;ptr+(size_x*y+x)*3
      
      mov word[esi],dx ;
      ror edx,16		
      mov byte[esi+2],dl
      ror edx,16
      pop esi
      @@:
      ret
    
    Небольшие рекомендации.
    В коде попиксельного рисования отдельного вида кривой желательно сделать как можно меньше обращений к системной памяти. То есть желательно отказаться от push/pop для функции попиксельного рисования. Перед вызовом drawpixel_buf необходимые параметры поместить в регистры(указатель на буфер, его ширина и высота). Если последовательно рисуется множество точек одной кривой, то заранее размещённые в регистрах параметры дадут очень существенное ускорение работы. Скорость работы регистровой памяти значительно выше, чем системной.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • Добавлю пять копеек:
    1) Если условно разбить буфер на знакоместа определенного размера (например, 50х50 пикселов) и дополнительно использовав область для хранения признака обновления знакоместа, можно немного ускорить вывод обновляя только те знакоместа, в которые производился вывод. Конечно при вызове перерисовки окна нужно перерисовывать весь буфер, но потом достаточно только перерисовывать изменения. Особенно заметна будет разница в скорости на полноэкранных приложениях, при обновлении небольших участков.
    2) Имеет смысл сделать буфер чуть большим отображаемого куска на экране, иначе у жучары части пропадают в некоторых ракурсах.
  • andrew_programmer согласен что не оптимально, перекомпилировал, работает. Только не пойму как вместо умножения на 3 написано:

    Code: Select all

      lea esi,[esi+esi*2] ;(size_x*y+x)*3
    почему не так:

    Code: Select all

      imul esi,3
    или так:

    Code: Select all

      lea esi,[esi*3] ;(size_x*y+x)*3
  • IgorA wrote: почему не так:

    Code: Select all

      imul esi,3
    или так:

    Code: Select all

      lea esi,[esi*3] ;(size_x*y+x)*3
    1. Потому что IMUL теоретически медленней.
    2. Потому что Зубков.

    Code: Select all

    Команда LEA
    LEA можно использовать (кроме прямого назначения — вычисления адреса сложно адресуемой переменной) для следующих двух ситуаций:
    
    быстрое умножение 
            lea        еах,[еах*2]     ; ЕАХ = ЕАХ * 2 (shl eax,1 лучше)
    
            lea        еах,[еах+еах*2]  ; ЕАХ = ЕАХ * 3
            lea        еах,[еах*4]      ; ЕАХ = ЕАХ * 4 (shl eax,2 лучше)
    
            lea        еах,[еах+еах*4]  ; ЕАХ = ЕАХ * 5
            lea        еах,[еах+еах*8]  ; ЕАХ = ЕАХ * 9
    
    трехоперандное сложение 
            lea        ecx,[eax+ebx]    ; ЕСХ = ЕАХ * ЕВХ
    
    Единственный недостаток LEA — увеличивается вероятность AGI с предыдущей командой (см. ниже).
    
  • почему не так:
    imul esi,3
    Потому что так на умножение уйдёт минимум 10 тактов. А при помощи командыlea esi,[esi+2*esi] всего 2-3 такта.
    почему не так:
    imul esi,3
    или так:
    lea esi,[esi*3] ;(size_x*y+x)*3
    С учётом того, что команда lea может выполняться одновременно с другой командой в любом конвеере, получается, что по скорости кода lea esi,[esi*3] =imul esi,3

    Для процессора умножение на 2 в степени n - это просто сдвиг на n бит влево. Операция сложения, также как и команда lea тоже может выполняться в любом конвеере. В общем вычисление адреса вместе с занесением его в ESI занимает минимум 2-3 такта, против минимум 10 в случае с imul.
    KolibriOS-перспективная ос!
    Kolibri is best operation system in the world!
  • Сделал 3 изменения:
    1) исправил функцию рисования точки в буфере, как сказал andrew_programmer
    2) доработал алгоритм отсечения кривых, когда они попадают на верхнюю и на левую границу окна
    3) можно использовать несколько отдельных буферов (номера принимают функции на входе, максимум 8 буферов, хотя при необходимости можно добавить)

    Дописал справку, под новые функции.
    Attachments
    vectors_091007.7z (24.08 KiB)
    Downloaded 405 times
  • в документации опечаточка. нужно исправить "длинна" на "длина"
  • IgorA
    Делай больше коментариев в коде, и перед каждой функцией желатьельно, полез посмотреть - все равно что в IDA посмотрел, найдется мало желающих помогать в разработке.
  • Albom
    Исправлю
    Ghost
    Я более подробно пробовал писать в документации. Но могу и в коде больше коментов написать. Если писать комментарии в коде, то в какой кодировке лучше OEM или ANSI?
    Ghost wrote:больше коментариев в коде, и перед каждой функцией желатьельно
    Имеешь в виду саму библиотеку или ее использование. Или и то и другое?
  • Who is online

    Users browsing this forum: No registered users and 5 guests