Помогите написать игру )

Everything you can't fit into other forums
  • Code: Select all

    ;input:
    ; edx = transparent color
    ; edi = background color
    ;output:
    ; edx = combine color
    ColSm:
      push eax bx cx si
        mov bx,0x0100 ;---get transparent---
        rol edx,8
        sub bl,dl ;256-pro
        xor ch,ch
        mov cl,dl ;pro
        xor dl,dl
    
        rol edi,16 ;---red---
          rol edx,8
          xor ah,ah
          mov al,dl
          imul ax,bx
          mov si,di
          and si,0xff
          imul si,cx
          add ax,si
          ;shr ax,8
          mov dl,ah
    
        rol edi,8 ;---green---
          rol edx,8
          xor ah,ah
          mov al,dl
          imul ax,bx
          mov si,di
          and si,0xff
          imul si,cx
          add ax,si
          mov dl,ah
    
        rol edi,8 ;---blye---
          rol edx,8
          xor ah,ah
          mov al,dl
          imul ax,bx
          mov si,di
          and si,0xff
          imul si,cx
          add ax,si
          mov dl,ah
    
      pop si cx bx eax
      ret
    может это поможет
  • Спасибо большое :D , но если не сложно , ты мог бы дать пару коментариев по поводу того как это получается. Просто я никогда не мог понять механизм прозрачности, :( и в любом случае встраивая код в прогу мне придётся его подправить под неё .
    Мы не часть этого мира , мы его творцы :)
  • chaykin wrote:Спасибо большое :D , но если не сложно , ты мог бы дать пару коментариев по поводу того как это получается. Просто я никогда не мог понять механизм прозрачности, :( и в любом случае встраивая код в прогу мне придётся его подправить под неё .
    Да, да. Мне тоже интересно. Желательно побольше комментариев, если можно.
  • Вообщето вывод с помощью Альфа канала немного сложнее чем в предложенном коде. Приходится смешивать фоновую точку с точкой выводимой картинки, учитывая значение Альфа канала для точки.
    А вообще смешивание производится по цветам (семплам) - точка в случае вывода функциями 7 и 65 (esi=24), выглядит разложенной в памяти так (от младщего байта к старшему):

    Code: Select all

    pixel1:
    .blue  db 0xFF
    .green db 0xFF
    .red   db 0xFF
    
    Итого имея три числа: B (Background - фон), S (Sample - семпл цвета) и T (Transparency - прозрачность или Альфа канал), вычисляем конечное значение по формуле:

    St = S*T + (1-T)*B

    St - получившийся семпл

    Соответственно для каждой точки нужно выполнить три таких вычисления.

    З.Ы. Поскольку выполнять умножение каждого семпла очень расточительная вещь в плане производительности (команды mul и dev выполняются много тактов), то ее можно попытаться заменить сдвиговыми операциями shl, shr, rol, ror (если это возможно). Или придумать еще что-нибудь. Но оптимизация это уже отдельный разговор.
  • Функция принимает 2 цвета, в edx содержится основной цвет + альфа канал, в edi цвет фона. Хотя это условно, главное что есть 2 цвета и в результате они смешиваются в указанной пропорции.

    Code: Select all

    ;input:
    ; edx = transparent color
    ; edi = background color
    ;output:
    ; edx = combine color
    
    Немного дальше функция извлекает альфа канал (прозрачность, в данном случае 1 байт - значения от 0 до 255)

    Code: Select all

        mov bx,0x0100 ;---get transparent---
        rol edx,8
        sub bl,dl ;256-pro
        xor ch,ch
        mov cl,dl ;pro
        xor dl,dl
    А дальше идет смешивание цветов в указанной пропорции, для каждого цвета (R,G,B) отдельно

    Code: Select all

        rol edi,16 ;---red---
          rol edx,8
          xor ah,ah
          mov al,dl
          imul ax,bx
          mov si,di
          and si,0xff
          imul si,cx
          add ax,si
          ;shr ax,8
          mov dl,ah
    ...
    Формула для смешивания в общем виде такая:
    cn=(c0*pro+c1*(max-pro))/max
    c0 и c1 смешиваемые цвета
    cn новый высчитанный цвет
    pro в какой пропорции смешивать цвета
    max максимальное значение для пропорции
    Возьмем крайние значения:
    pro = 0 тогда цвет будет (c0*0+c1*(max-0))/max = с0*0/max+с1*max/max=c1
    или pro = max тода (c0*max+c1*(max-max))/max = c0*max/max+c1*0/max = c0
    И еще пояснения
    bx = max-pro
    cx = pro
    mov dl,ah - равносильно формуле dl = ax / 256
  • IgorA wrote:Функция принимает 2 цвета, в edx содержится основной цвет + альфа канал, в edi цвет фона. Хотя это условно, главное что есть 2 цвета и в результате они смешиваются в указанной пропорции.
    Да, похоже я проглядел - не увидел данных на входе, вот и решил что без Альфа канала.
    Формулу, которую я привел, взял из официальной спецификации PNG.
    У тебя формула сложней, а дает тот-же результат по сути. ИМХО надо стремиться к оптимизации.
  • заметил один недостаток в функции, правда он почему-то особо не мешал работе программы. Было так:

    Code: Select all

        mov bx,0x0100 ;---get transparent---
        rol edx,8
        sub bl,dl ;256-pro
        xor ch,ch
        mov cl,dl ;pro
        xor dl,dl
    Желательно сделать так:

    Code: Select all

        mov bx,0x00ff ;---get transparent---
        rol edx,8
        sub bl,dl ;255-pro
        xor ch,ch
        mov cl,dl ;pro
        xor dl,dl
    Mario wrote:У тебя формула сложней, а дает тот-же результат по сути. ИМХО надо стремиться к оптимизации.
    Дело в том что это одна и та же самая формула, просто обозначения разные.
    St = S*T + (1-T)*B
    При оптимизации желательно избавится от операций с дробными числами, вот здесь 1-T, потому лучше всего все числа привести к целочисленным, допустим умножить все и разделить на 256.
    Attachments
    color_alfa.7z (1.33 KiB)
    Downloaded 217 times
  • IgorA, Mario
    --------------------
    Очень полезная и нужная инфа. Большое спасибо. :D

    -----------------------------------------------------------------------------------------
    So far, so good, so what ...
    -----------------------------------------------------------------------------------------
  • Вот написал кусок кода по формуле Mario, так как она попроще. Вродебы всё правильно, но я не уверен. С матиматикой и программированием, у меня туго, поэтому если не трудно, кто ни-будь проверьте и поправьте. Вообщем как сказали великие Beatles, в одной из своих песен - " Help, i need some body help".

    Code: Select all

    
    ; Функция получения прозрачности для одного сэмпла.
    
    ;input:
    ; eax = transparent color
    ; edi = background color
    ;output:
    ; edx = combine color
    
    GetPixTransp:  xor  edx,edx         ; edx=0 
                   inc  edx             ; edx=1
                   sub  edx,eax         ; (1-T)
                   and  edx,edi         ; (1-T)*B
                   rol  eax,8           ; S*T
                   or   edx,eax         ; S*T + (1-T)*B   ; ST = edx
    .
    
    ---------------------------------------------------------------------------------------------------------------------------------------------
    I am android. In my head creazy chip. My head fetch down... fetch down... fetch down... over...
    ---------------------------------------------------------------------------------------------------------------------------------------------
    Last edited by Rock_maniak_forever on Thu Sep 10, 2009 1:12 pm, edited 2 times in total.
  • Rock_maniak_forever
    1) для quote= и code= все что после знака равенство надо в кавычки ""
    2) нельзя рассчитывать сразу весь пиксел - надо рассичтывать отдельные составляющие (семплы).
    2)Констркуция:

    Code: Select all

    xor  edx,edx         ; edx=0 
    inc  edx             ; edx=1
    sub  edx,eax         ; (1-T)
    
    Замечательно заменяется на:

    Code: Select all

    neg eax
    
    4) Дальше:

    Code: Select all

    rol  eax,8           ; S*T
    or   edx,eax         ; S*T + (1-T)*B   ; ST = edx
    
    вообще не в тему.
    Last edited by Mario on Thu Sep 10, 2009 12:55 pm, edited 1 time in total.
  • Я это и имел ввиду, просто описался.

    На счёт neg eax - это вопрос оптимизации, поэтому это не сильно важно, но нужно. Я оптимизирую во вторую очередь.
    Mario wrote:4) Дальше:

    Code: Select all

    rol  eax,8           ; S*T
    or   edx,eax         ; S*T + (1-T)*B   ; ST = edx
    
    вообще не в тему.
    А как?
  • Приблизительно так (ниже) для вычисления единичного семпла. Для трех семплов надо три раза вызвать, для обработки всего пикселя.

    Code: Select all

    ;input
    ;al = sample front color
    ;ah = transparent
    ;bl = sample background color
    
    ;output
    ;cl = combine sample
    
    mov bh,ah
    
    xor ecx,ecx
    mov cl,al
    shr ax,8
    imul cx,ax
    
    xor edx,edx
    mov dl,bl
    shr bx,8
    neg bx
    imul dx,bx
    
    add  cx,dx
    
    За 100% работоспособность не ручаюсь - не проверял работу.
  • Большое спасибо, буду разбираться. :roll:
  • Мoжно использовать MMX:
    4. Канал прозрачности (alpha blending) [далее ab] – одно изображение плавно появляется или растворяется поверх другого (также очень часто применяется при работе с видео).

    Формула ab: a = b + (a - b) * alpha

    Где: a – основное изображение
    b – изображение которое накладывается
    alpha – количество градаций(позиций) ab - обычно хватает 0...255.

    переведем это все в MMX-команды:

    a) инициализация регистров

    биты 31...24 23...16 15...8 7...0
    eax = alpha alpha alpha alpha

    movd mm4,eax ; переносим данных из eax в mm4
    punpcklwd mm4,mm4 ; создаем четыре cлова alpha-канала
    psrlw mm4,8 ; переносим старшую часть слов в младшую
    pxor mm7,mm7 ; обнуляем mm7
    б) основная процедура

    movd mm0,[esi] ; загрузить в mm1 четыре байта накладываемого изображения
    movd mm1,[edx] ; загрузить в mm0 четыре байта основного изображения
    punpcklbw mm0,mm7
    punpcklbw mm1,mm7
    psubw mm0,mm1 ; вычитаем из накладываемого, основное изображение
    psllw mm1,8 ; переносим младшую часть слов регистра mm1 в cтаршую
    pmullw mm0,mm4 ; умножаем накладываемое изображение на alpha-канал
    paddw mm1,mm0 ; складываем его с основным
    psrlw mm1,8 ; переносим результат из старшей части слова в младшую
    packuswb mm1,mm1 ; и переводим его в 32 бита
    movd [edi],mm1 ; кладем полученное изображение на экран (в видеобуфер)
    add esi,4
    add edx,4
    add edi,4
    В данном примере используется быстрое 16-битное MMX-умножение, которое и дает максимальное ускорение нашей процедуре. Плюс - уже ставшая традицией – обработка сразу четырех байт...
  • Who is online

    Users browsing this forum: No registered users and 8 guests