Potrzebowałem uzyskać jak najprostszym sposobem efekt alpha blendingu, a z racji, że nie miałem o tym pojęcia, i nadal zbytnio nie mam o grafice 2/3D próbowałem zaczerpnąć informacji w niezliczonych zasobach sieciowych ;)
Szukałem jakiegoś prostego sposobu wyznaczania średniej wartości składowej koloru danego piksela. W różnych źródłach znalazłem kilka różnych działań obliczających tą wartość, od bardzo prostych i wydajnych, to złożonych i ociężałych.
Poniżej kilka znalezionych wersji ;)
Mała legenda: r to wynikowa średnia wartość danej składowej koloru, s jest składowa źródłowa, a d docelowa, blend to stopień przenikalności z przedziału 0...255
.
Pierwsze znaleziony wynik to:
r = (blend * ((s + 64) - d)) / 256 + d - (blend / 4) |
Jak widać czyste samobójstwo i zarzynanie procesora, tyle operacji, a w tym dwa dzielenia, z czego jeden można by buforować.
Następnie było kilka ciekawych wyników, ale nie różniły one się specjalnie od tych znalezionych przypadkiem w źródłach Mesa 3D, biblioteki graficznej 3D.
Szybkie, mniej dokładne:
r = (s * blend + d * inv + 1) >> 8 |
Powolniejsze, dokładniejsze:
r = (s * blend + d * inv) / 255 |
gdzie inv to 'odwrócony' blend:
Inv = 255 - blend |
Idąc dalej, typowe działanie szeroko stosowane:
r = ((s - d) * blend) / 255 + d |
Jak wiadomo dzielenie jest dosyć kosztowną operacją w porównaniu do pozostałych prostych działań, dlatego niektórzy zamiast dzielenia wykorzystują przesunięcia bitowe, które są o wiele szybsze niż inne operacje.
x / 255 = ((x << 8) + x + 256) >> 16 |
No i wreszcie dochodzimy do najbardziej optymalnej metody:
r = (s - d) * (blend/255) + d |
Wartość blend/255
jest stała dla danej wartości przeźroczystości, przez co możemy ja zbuforować i w pętli obliczającej kolory wszystkich pikselów obrazka wykonujemy tylko bardzo proste i szybkie działanie (s - d) * x + d
, które nosi nazwę interpolacji liniowej.
Warto jeszcze wspomnieć, że w obecnych kartach graficznych interpolacja liniowa wykonywana jest w GPU w jednym cyklu/rozkazie.
Temat ten zahaczyłem głównie z powodu braku w wxImage jakiejś prostej funkcji do uzyskania blendingu danego obrazka z innym, bądź jakimś kolorem, co bardzo mi się przydałoby.
Może patcha napisze, bo aktualnie można jedynie pokombinować z alpha i nakładaniem dwóch obrazków na kontekście urządzenia ;)
Hej, co do liczenia na procesorze to możesz również się skusić na użycie jednostek SSE. W bibliotekach Microsoftu są intrinsic’i do tego: http://msdn.microsoft.com/en-us/library/y0dh78ez(VS.80).aspx – może się przyda
Ogólnie to masz ciekawy blog :)
Pozdrawiam
Ciekawe, choc w asmie sie malo bawie :(
A blog jak devblog, w sumie tez nic ciekawego sie nie dzieje, bo nie ma czasu i tematow :P