{"id":86,"date":"2013-09-07T17:27:00","date_gmt":"2013-09-07T17:27:00","guid":{"rendered":"https:\/\/blogs.scummvm.org\/t0by\/?p=86"},"modified":"2022-05-24T17:28:41","modified_gmt":"2022-05-24T17:28:41","slug":"blending","status":"publish","type":"post","link":"https:\/\/blogs.scummvm.org\/t0by\/2013\/09\/07\/blending\/","title":{"rendered":"Blending"},"content":{"rendered":"<p>Let-s spend a few words on blending.<\/p>\n<p>Blending is kind of like bringing blitting a step further.<\/p>\n<p>We don\u2019t want to just copy a pixel from source to destination, but we want to combine the source with the destination in peculiar ways.<\/p>\n<p>The most obvious is transparency \u2013 we want to overlay the two colors so that you can still see an hint of the previous color.<\/p>\n<p>But we may also want to perform additive blending, which is kind of what happens when you project two cones of light on the same surface.<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/AdditiveColor.svg_.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-88\" src=\"https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/AdditiveColor.svg_.png\" alt=\"\" width=\"220\" height=\"220\" srcset=\"https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/AdditiveColor.svg_.png 220w, https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/AdditiveColor.svg_-150x150.png 150w\" sizes=\"auto, (max-width: 220px) 100vw, 220px\" \/><\/a> Subtractive blending is the opposite. It\u2019s like when you have two differently-colored light sources and two objects create two shadows. When they meet, you have subtractive blending.<\/p>\n<p><a href=\"https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/220px-SubtractiveColor.svg_.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-89\" src=\"https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/220px-SubtractiveColor.svg_.png\" alt=\"\" width=\"220\" height=\"220\" srcset=\"https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/220px-SubtractiveColor.svg_.png 220w, https:\/\/blogs.scummvm.org\/t0by\/wp-content\/uploads\/sites\/43\/2013\/09\/220px-SubtractiveColor.svg_-150x150.png 150w\" sizes=\"auto, (max-width: 220px) 100vw, 220px\" \/><\/a>WME, in addition to opaque blitting, supports \u201cregular\u201d alpha blending, additive blending and subtractive blending.<br \/>\nEach can have a color modifier as a nice added feature \u2013 basically, the input sprite gets multiplied by the colorMod, which acts kind of like a pair of colored lenses.<\/p>\n<p>Of course, the original uses the ready-made blending options provided by DirectX.<br \/>\nWe, on the other hand, must roll our own.<\/p>\n<p>Here\u2019s some examples.<br \/>\nFor starters, subtractive blending for a single pixel.<br \/>\nThere are two special cases which are useful optimization-wise but could be stripped away.<\/p>\n<pre>void BlittingTools::blendPixelSubtractive(byte *ina, byte *inr, byte *ing, byte *inb, byte *outa, byte *outr, byte *outg, byte *outb) {\r\n    \/*\r\n     * in[argb] = input pixel, a,r,g,b channel;\r\n     * out[argb] = output pixel, a,r,g,b channel;\r\n     *\/\r\n        \/\/ BEGIN OPTIONAL PART\r\n        if (*ina == 0) { \/\/ Fully transparent... let's not waste time on this.\r\n \r\n        } else if (*ina == 255) { \/\/ Fully opaque. Forget\r\n            *outa = *outa;\r\n            *outr = MAX(*outr - *inr, 0);\r\n            *outg = MAX(*outg - *ing, 0);\r\n            *outb = MAX(*outb - *inb, 0);\r\n            return;\r\n        } else {\r\n        \/\/ END OPTIONAL PART\r\n            *outa = *outa;\r\n            *outb = MAX(*outb - (*inb * *ina &gt;&gt; 8), 0);\r\n            *outg = MAX(*outg - (*ing * *ina &gt;&gt; 8), 0);\r\n            *outr = MAX(*outr - (*inr * *ina &gt;&gt; 8), 0);\r\n            \/\/ * ina &gt;&gt; 8 is kind of like * ina \/ 255, ina\r\n            \/\/ goes from 0 - 255, so you end up multiplying by 0...1\r\n            return;\r\n        }\r\n}\r\n<\/pre>\n<p>Another example, additive with colormod.<\/p>\n<pre>void BlittingTools::blendPixelAdditive(byte *ina, byte *inr, byte *ing, byte *inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) {\r\n \r\n        if (*ca != 255) {\r\n            *ina = *ina * *ca &gt;&gt; 8;\r\n        }\r\n \r\n        if (*ina == 0) {\r\n            return;\r\n        } else if (*ina == 255) {\r\n            if (*cb != 255)\r\n                *outb = MIN(*outb + ((*inb * *cb * *ina) &gt;&gt; 16), 255);\r\n            else\r\n                *outb = MIN(*outb + (*inb * *ina &gt;&gt; 8), 255);\r\n \r\n            if (*cg != 255)\r\n                *outg = MIN(*outg + ((*ing * *cg * *ina) &gt;&gt; 16), 255);\r\n            else\r\n                *outg = MIN(*outg + (*ing * *ina &gt;&gt; 8), 255);\r\n \r\n            if (*cr != 255)\r\n                *outr = MIN(*outr + ((*inr * *cr * *ina) &gt;&gt; 16), 255);\r\n            else\r\n                *outr = MIN(*outr + (*inr * *ina &gt;&gt; 8), 255);\r\n        }\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Let-s spend a few words on blending. Blending is kind of like bringing blitting a step further. We don\u2019t want to just copy a pixel from source to destination, but we want to combine the source with the destination in peculiar ways. The most obvious is transparency \u2013 we want to overlay the two colors [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-86","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/posts\/86","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/comments?post=86"}],"version-history":[{"count":2,"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/posts\/86\/revisions"}],"predecessor-version":[{"id":90,"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/posts\/86\/revisions\/90"}],"wp:attachment":[{"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/media?parent=86"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/categories?post=86"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.scummvm.org\/t0by\/wp-json\/wp\/v2\/tags?post=86"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}