How to transparency ?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
DeezRamChips
Member
Member
Posts: 132
Joined: Fri Apr 08, 2016 5:03 am
Location: atapio.cpp - why won't you work :(
Contact:

How to transparency ?

Post by DeezRamChips »

Hi everyone ^_^

I would like how to implement tansparency in my code, I've tried a lot of formulas
but none of them worked :/ can someone show me a formula in C that works ?
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: How to transparency ?

Post by Octacone »

OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
DeezRamChips
Member
Member
Posts: 132
Joined: Fri Apr 08, 2016 5:03 am
Location: atapio.cpp - why won't you work :(
Contact:

Re: How to transparency ?

Post by DeezRamChips »

Ik, thansk, I'll trie them ^^
User avatar
Ch4ozz
Member
Member
Posts: 170
Joined: Mon Jul 18, 2016 2:46 pm
Libera.chat IRC: esi

Re: How to transparency ?

Post by Ch4ozz »

You have to access the pixels underneath the new transparent stuff.
Now its pretty simple.

Old code without transparency:

Code: Select all

*(uint32_t*)physbuff = color;
New transparency code:

Code: Select all

physbuff[0] = clamp(color.r + physbuff[0] * (color.a / 255.0f), 0, 255);
physbuff[1] = clamp(color.g + physbuff[1] * (color.a / 255.0f), 0, 255);
physbuff[2] = clamp(color.b + physbuff[2] * (color.a / 255.0f), 0, 255);
physbuff[3] = clamp(physbuff[3] + color.a, 0, 255);
The only problem is that this is hella slow, Im currently thinking about a fast SSE method
Boris
Member
Member
Posts: 145
Joined: Sat Nov 07, 2015 3:12 pm

Re: How to transparency ?

Post by Boris »

If your transparent image is a matrix (T) , the transparency factor also matrix (A) from 0: transparent,1: opaque, and if your background is matrix B, then the resulting image should be B + TxA - BxA. Which means , applying T to a background B does B+=(T-B)xA
SSE helps you doing quick matrix multiplication and additions but you have to do it by parts. ( Google SSE 4x4)
User avatar
DeezRamChips
Member
Member
Posts: 132
Joined: Fri Apr 08, 2016 5:03 am
Location: atapio.cpp - why won't you work :(
Contact:

Re: How to transparency ?

Post by DeezRamChips »

I don't know anything about matrices :(

Haven't learned that already :( :( :(
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to transparency ?

Post by Octocontrabass »

Ch4ozz wrote:New transparency code:
Why are you doing additive blending instead of alpha blending?
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

Re: How to transparency ?

Post by onlyonemac »

DeezRamChips wrote:I don't know anything about matrices :(

Haven't learned that already :( :( :(
Either implement each step separately, then, or learn about matrices. In most cases, matrices are just a practical and meaningful way of representing data and performing operations on it, but you can implement the same algorithm with each value separately (different types of matrix multiplication can get a little messy if you're working with the values separately, though). Just think of matrices like arrays, and matrix operations as operations on arrays (it might help to implement each of the main matrix operations as functions, and call then as necessary to implement an algorithm that works with matrices, rather than worrying about the details of how those operations work and how the data is transformed to the required end result).
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: How to transparency ?

Post by BrightLight »

Well, I implemented alpha blending in the simplest way possible with a cost: I only support 4 different transparency levels, numbered from 1 to 4.
Here's how it works; can be easily converted to C code:

Code: Select all

; alpha_blend_colors:
; Blends two colors
; In\	EAX = Foreground
; In\	EBX = Background
; In\	DL = Number of bits to shift foreground color (1 = less transparent, 4 = most transparent, 0 = no change)
; Out\	EAX = New color
align 16
alpha_blend_colors:
	or dl, dl
	jz .no_change

	cmp dl, 4
	jg .no_change

	push rcx		; my tests have shown that PUSH RCX is a few cycles faster than PUSH CX --
				; -- so this probably gives more performance on slow CPUs and maybe Bochs
				; I thought PUSH CX would be faster because it's less data, but oh well..
	and eax, 0xF0F0F0
	and ebx, 0xF0F0F0

	mov cl, dl
	shr eax, cl
	shr ebx, 1
	and eax, 0x7F7F7F
	and ebx, 0x7F7F7F
	lea eax, [eax+ebx]	; probably faster than add eax, ebx
	pop rcx
	ret

.no_change:
	ret
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: How to transparency ?

Post by Brendan »

Hi,

Just as a reference, the "mathmatically correct" formulas would be:

Code: Select all

resultBlue = (blue1 * alpha + blue2 * (alphaMax - alpha) ) / alphaMax;
resultGreen = (green1 * alpha + green2 * (alphaMax - alpha) ) / alphaMax;
resultRed = (red1 * alpha + red2 * (alphaMax - alpha) ) / alphaMax;
This is only correct for the "no gamma" case. Pixels typically have a gamma of about 2.2, and for that case "correct" becomes:

Code: Select all

resultBlue = pow( (pow(blue1, 1/2.2) * alpha + pow(blue2, 1/2.2) * (alphaMax - alpha)) / alphaMax, 2.2);
Note that (for 8-bit alpha), most people do it wrong, like:

Code: Select all

resultBlue = (blue1 * alpha + blue2 * ~alphaMax) >> 8;
This causes images to be a fraction darker than they should be (because it's dividing by 256 and not dividing by 255, and because of "round towards zero division"); and lack of gamma correction magnifies this error (especially for darker colours); but it's faster than doing "pow()" twice per pixel. ;)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
max
Member
Member
Posts: 616
Joined: Mon Mar 05, 2012 11:23 am
Libera.chat IRC: maxdev
Location: Germany
Contact:

Re: How to transparency ?

Post by max »

Brendan wrote:This causes images to be a fraction darker than they should be (because it's dividing by 256 and not dividing by 255, and because of "round towards zero division"); and lack of gamma correction magnifies this error (especially for darker colours); but it's faster than doing "pow()" twice per pixel. ;)
I love that you always know some hardcore stuff that seemingly few other people know :P
User avatar
Sik
Member
Member
Posts: 251
Joined: Wed Aug 17, 2016 4:55 am

Re: How to transparency ?

Post by Sik »

Brendan wrote:Note that (for 8-bit alpha), most people do it wrong, like:

Code: Select all

resultBlue = (blue1 * alpha + blue2 * ~alphaMax) >> 8;
This causes images to be a fraction darker than they should be (because it's dividing by 256 and not dividing by 255, and because of "round towards zero division"); and lack of gamma correction magnifies this error (especially for darker colours); but it's faster than doing "pow()" twice per pixel. ;)
Just registered to say this:

Code: Select all

dest_a = ~src_a;
result_r = (src_r * src_a + dest_r * dest_a + 0xFF) >> 8;
result_g = (src_g * src_a + dest_g * dest_a + 0xFF) >> 8;
result_b = (src_b * src_a + dest_b * dest_a + 0xFF) >> 8;
Not necessarily the most accurate thing ever but it does prevent the situation of white becoming darker. Essentially all it's doing is mess with the rounding so fully opaque and fully transparent remain intact despite dividing by 256. Remove the * src_a if you want to make it premultiplied alpha instead, and make sure that dest_a is uint8_t (or you'll slam head straight against C's integer promotion rules).

You probably want premultiplied alpha if the image is filtered and scaled upwards anyway (since texture filtering creates values that don't exist and hence has a tendency to make problematic alpha values at the borders)
Post Reply