Очень хочу написать игру с кучей класных эффектов но уже давно мучаясь и пришол к выводу что неопходимый код я написать не смогу.
А именно что мне нужно : берётся два изображения одно чёрно-белое другое цветное в итоге получается такая вещь
цветное изображение становится прозрачным в зависимости от интенсивности белого на чёрно-белом изображении то есть чветное изображение становится градиентно-прозрачным надеюсь меня поняли и дадут пару советов или строчек кода ЗАРАНЕЕ СПАСИБО!
p.s. пишу под колибри исключительно на assembler'е
Помогите написать игру )
-
Мы не часть этого мира , мы его творцы
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
Спасибо большое , но если не сложно , ты мог бы дать пару коментариев по поводу того как это получается. Просто я никогда не мог понять механизм прозрачности, и в любом случае встраивая код в прогу мне придётся его подправить под неё .
Мы не часть этого мира , мы его творцы
Да, да. Мне тоже интересно. Желательно побольше комментариев, если можно.chaykin wrote:Спасибо большое , но если не сложно , ты мог бы дать пару коментариев по поводу того как это получается. Просто я никогда не мог понять механизм прозрачности, и в любом случае встраивая код в прогу мне придётся его подправить под неё .
Вообщето вывод с помощью Альфа канала немного сложнее чем в предложенном коде. Приходится смешивать фоновую точку с точкой выводимой картинки, учитывая значение Альфа канала для точки.
А вообще смешивание производится по цветам (семплам) - точка в случае вывода функциями 7 и 65 (esi=24), выглядит разложенной в памяти так (от младщего байта к старшему):
Итого имея три числа: B (Background - фон), S (Sample - семпл цвета) и T (Transparency - прозрачность или Альфа канал), вычисляем конечное значение по формуле:
St = S*T + (1-T)*B
St - получившийся семпл
Соответственно для каждой точки нужно выполнить три таких вычисления.
З.Ы. Поскольку выполнять умножение каждого семпла очень расточительная вещь в плане производительности (команды mul и dev выполняются много тактов), то ее можно попытаться заменить сдвиговыми операциями shl, shr, rol, ror (если это возможно). Или придумать еще что-нибудь. Но оптимизация это уже отдельный разговор.
А вообще смешивание производится по цветам (семплам) - точка в случае вывода функциями 7 и 65 (esi=24), выглядит разложенной в памяти так (от младщего байта к старшему):
Code: Select all
pixel1:
.blue db 0xFF
.green db 0xFF
.red db 0xFF
St = S*T + (1-T)*B
St - получившийся семпл
Соответственно для каждой точки нужно выполнить три таких вычисления.
З.Ы. Поскольку выполнять умножение каждого семпла очень расточительная вещь в плане производительности (команды mul и dev выполняются много тактов), то ее можно попытаться заменить сдвиговыми операциями shl, shr, rol, ror (если это возможно). Или придумать еще что-нибудь. Но оптимизация это уже отдельный разговор.
Функция принимает 2 цвета, в edx содержится основной цвет + альфа канал, в edi цвет фона. Хотя это условно, главное что есть 2 цвета и в результате они смешиваются в указанной пропорции.
Немного дальше функция извлекает альфа канал (прозрачность, в данном случае 1 байт - значения от 0 до 255)
А дальше идет смешивание цветов в указанной пропорции, для каждого цвета (R,G,B) отдельно
Формула для смешивания в общем виде такая:
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
Code: Select all
;input:
; edx = transparent color
; edi = background color
;output:
; edx = combine color
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
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.
У тебя формула сложней, а дает тот-же результат по сути. ИМХО надо стремиться к оптимизации.
заметил один недостаток в функции, правда он почему-то особо не мешал работе программы. Было так:
Желательно сделать так:
St = S*T + (1-T)*B
При оптимизации желательно избавится от операций с дробными числами, вот здесь 1-T, потому лучше всего все числа привести к целочисленным, допустим умножить все и разделить на 256.
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
--------------------
Очень полезная и нужная инфа. Большое спасибо.
-----------------------------------------------------------------------------------------
So far, so good, so what ...
-----------------------------------------------------------------------------------------
--------------------
Очень полезная и нужная инфа. Большое спасибо.
-----------------------------------------------------------------------------------------
So far, so good, so what ...
-----------------------------------------------------------------------------------------
Вот написал кусок кода по формуле Mario, так как она попроще. Вродебы всё правильно, но я не уверен. С матиматикой и программированием, у меня туго, поэтому если не трудно, кто ни-будь проверьте и поправьте. Вообщем как сказали великие Beatles, в одной из своих песен - " Help, i need some body help".
---------------------------------------------------------------------------------------------------------------------------------------------
I am android. In my head creazy chip. My head fetch down... fetch down... fetch down... over...
---------------------------------------------------------------------------------------------------------------------------------------------
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)Констркуция:
Замечательно заменяется на:
4) Дальше:
вообще не в тему.
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
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 - это вопрос оптимизации, поэтому это не сильно важно, но нужно. Я оптимизирую во вторую очередь.
На счёт neg eax - это вопрос оптимизации, поэтому это не сильно важно, но нужно. Я оптимизирую во вторую очередь.
А как?Mario wrote:4) Дальше:
вообще не в тему.Code: Select all
rol eax,8 ; S*T or edx,eax ; S*T + (1-T)*B ; ST = edx
Приблизительно так (ниже) для вычисления единичного семпла. Для трех семплов надо три раза вызвать, для обработки всего пикселя.
За 100% работоспособность не ручаюсь - не проверял работу.
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
Большое спасибо, буду разбираться.
М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