Page 1 of 2

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

Posted: Mon Sep 07, 2009 6:08 pm
by chaykin
Очень хочу написать игру с кучей класных эффектов но уже давно мучаясь и пришол к выводу что неопходимый код я написать не смогу.
А именно что мне нужно : берётся два изображения одно чёрно-белое другое цветное в итоге получается такая вещь
цветное изображение становится прозрачным в зависимости от интенсивности белого на чёрно-белом изображении то есть чветное изображение становится градиентно-прозрачным :D надеюсь меня поняли и дадут пару советов или строчек кода :D ЗАРАНЕЕ СПАСИБО!
p.s. пишу под колибри исключительно на assembler'е

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

Posted: Mon Sep 07, 2009 7:15 pm
by IgorA

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
может это поможет

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

Posted: Tue Sep 08, 2009 1:50 pm
by chaykin
Спасибо большое :D , но если не сложно , ты мог бы дать пару коментариев по поводу того как это получается. Просто я никогда не мог понять механизм прозрачности, :( и в любом случае встраивая код в прогу мне придётся его подправить под неё .

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

Posted: Tue Sep 08, 2009 7:45 pm
by Rock_maniak_forever
chaykin wrote:Спасибо большое :D , но если не сложно , ты мог бы дать пару коментариев по поводу того как это получается. Просто я никогда не мог понять механизм прозрачности, :( и в любом случае встраивая код в прогу мне придётся его подправить под неё .
Да, да. Мне тоже интересно. Желательно побольше комментариев, если можно.

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

Posted: Tue Sep 08, 2009 9:04 pm
by Mario
Вообщето вывод с помощью Альфа канала немного сложнее чем в предложенном коде. Приходится смешивать фоновую точку с точкой выводимой картинки, учитывая значение Альфа канала для точки.
А вообще смешивание производится по цветам (семплам) - точка в случае вывода функциями 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 (если это возможно). Или придумать еще что-нибудь. Но оптимизация это уже отдельный разговор.

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

Posted: Wed Sep 09, 2009 8:44 am
by IgorA
Функция принимает 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

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

Posted: Wed Sep 09, 2009 9:51 am
by Mario
IgorA wrote:Функция принимает 2 цвета, в edx содержится основной цвет + альфа канал, в edi цвет фона. Хотя это условно, главное что есть 2 цвета и в результате они смешиваются в указанной пропорции.
Да, похоже я проглядел - не увидел данных на входе, вот и решил что без Альфа канала.
Формулу, которую я привел, взял из официальной спецификации PNG.
У тебя формула сложней, а дает тот-же результат по сути. ИМХО надо стремиться к оптимизации.

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

Posted: Wed Sep 09, 2009 3:34 pm
by IgorA
заметил один недостаток в функции, правда он почему-то особо не мешал работе программы. Было так:

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.

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

Posted: Thu Sep 10, 2009 1:21 am
by Rock_maniak_forever
IgorA, Mario
--------------------
Очень полезная и нужная инфа. Большое спасибо. :D

-----------------------------------------------------------------------------------------
So far, so good, so what ...
-----------------------------------------------------------------------------------------

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

Posted: Thu Sep 10, 2009 12:36 pm
by Rock_maniak_forever
Вот написал кусок кода по формуле 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...
---------------------------------------------------------------------------------------------------------------------------------------------

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

Posted: Thu Sep 10, 2009 12:48 pm
by Mario
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
вообще не в тему.

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

Posted: Thu Sep 10, 2009 12:54 pm
by Rock_maniak_forever
Я это и имел ввиду, просто описался.

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

Code: Select all

rol  eax,8           ; S*T
or   edx,eax         ; S*T + (1-T)*B   ; ST = edx
вообще не в тему.
А как?

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

Posted: Thu Sep 10, 2009 1:12 pm
by Mario
Приблизительно так (ниже) для вычисления единичного семпла. Для трех семплов надо три раза вызвать, для обработки всего пикселя.

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% работоспособность не ручаюсь - не проверял работу.

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

Posted: Thu Sep 10, 2009 1:15 pm
by Rock_maniak_forever
Большое спасибо, буду разбираться. :roll:

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

Posted: Sun Sep 13, 2009 10:07 am
by Yaskhan
М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-умножение, которое и дает максимальное ускорение нашей процедуре. Плюс - уже ставшая традицией – обработка сразу четырех байт...