Alpha blend till "front to back" rendering

Permalänk

Alpha blend till "front to back" rendering

Jag har gjort en funktion för alpha blending som skulle vara till front to back (rendera de objekt närmast först altså) rendering men jag fick inte äns den till att funka som vanlig bar to front...

Jag läste i SDL:s dokumentation att det skulle se ut så här ungefär:

Er, Eg, Eb - Element color value
Ea - Element alpha value
Cr, Cg, Cb - Canvas color value (before blending)
Ca - Canvas alpha value (before blending)
Cr', Cg', Cb' - Canvas color value (after blending)
Ca' - Canvas alpha value (after blending)
Ca' = 1 - (1 - Ea) * (1 - Ca)
Cr' = (1 - Ea) * Cr + Er
Cg' = (1 - Ea) * Cg + Eg
Cb' = (1 - Ea) * Cb + Eb

Jag gjorde en funktion av de uträkningarna och den blev så här:

unsigned int blend_ftb( unsigned int source, unsigned int target)
{
unsigned int sourcer = (source >> 0) & 0xff;
unsigned int sourceg = (source >> 8) & 0xff;
unsigned int sourceb = (source >> 16) & 0xff;
unsigned int targetr = (target >> 0) & 0xff;
unsigned int targetg = (target >> 8) & 0xff;
unsigned int targetb = (target >> 16) & 0xff;

float sourcea = ((source >> 24) & 0xff)/255.0;
float targeta = ((target >> 24) & 0xff)/255.0;

targeta = 1 - (1 - sourcea) * (1 - targeta);
targetr = (1 - sourcea) * targetr + sourcer;
targetg = (1 - sourcea) * targetg + sourceg;
targetb = (1 - sourcea) * targetb + sourceb;

if (targetr > 0xff) targetr = 0xff;
if (targetg > 0xff) targetg = 0xff;
if (targetb > 0xff) targetb = 0xff;

unsigned int int_targeta = targeta * 255;

return (targetr << 0) |
(targetg << 8) |
(targetb << 16) |
(int_targeta << 24);
}

Jag vet inte om jag har gjort rätt men matar man in 0x11ffffff, 0xff000000 så får man 0xffffffff vilket borde vara fel eftersom då blandas inte ffffff (helt vit) med 000000 ( helt svart) på rätt sätt

vad är felet?

Visa signatur
Permalänk
Medlem

Du har glömt en liten sak

targetr = (1 - sourcea) * targetr + sourcea * sourcer; targetg = (1 - sourcea) * targetg + sourcea * sourceg; targetb = (1 - sourcea) * targetb + sourcea * sourceb;

Visa signatur

Surf/jobbdator: i7 3770K | GA-Z77-D3H | 16 GB | Intel 510 + 750 GB | HD6870 2GB | 30'' | P180B
Server: Phenom X4 9500 | GA-MA78G-DS3H | 8 GB | 5.4 TB | YY-0221
Speldator: IBM PC XT | 8088 4.77 MHz | 640k | 10 MB HDD | EGA | 360k/720k diskett

Permalänk
Citat:

Ursprungligen inskrivet av snq
Du har glömt en liten sak

targetr = (1 - sourcea) * targetr + sourcea * sourcer; targetg = (1 - sourcea) * targetg + sourcea * sourceg; targetb = (1 - sourcea) * targetb + sourcea * sourceb;

Tack så mycket

Nu kan jag vidaregå till det andra problemet.

Det ska ju vara i front to back och det kan ju göras simpelt genom att byta ut alla target mot source. Det ända som inte kommer bytas ut är alla target variablar som tilldelas uträkningarna. Men då sätter man ju ett värde på targeta som då senare kommer användas. Man kan ju förvisso bara byta den till source istället men det blir ju pedagogiskt fel. Hänger ni med?

Hur ska jag göra här då? Jag vill gärna ha det så optimerat som möjligt

Visa signatur
Permalänk
Medlem

Jag hänger då inte riktig med nu, det var länge sen man gjorde nåt med software rendering.. Men jag kan ge dig några tips iaf för att det ska bli lite mer optimerat

1) bort med floatsarna!

unsigned int sourcea = ((source >> 24) & 0xff); unsigned int targeta = ((target >> 24) & 0xff); targeta = 255 - (((255 - sourcea) * (255 - targeta))>>8); targetr = ((255 - sourcea) * targetr + sourcea * sourcer)>>8; targetg = ((255 - sourcea) * targetg + sourcea * sourceg)>>8; targetb = ((255 - sourcea) * targetb + sourcea * sourceb)>>8;

Och så lite till ändringar men det får du lösa själv.. Det är tidigt och jag orkar inte.. Garanterar ej heller att den här koden är korret, som sagt det är tidigt och jag är nyvaken

2) Lägg dit nån check som gör nåt snabbare i fall sourcea eller targeta är 0/255 (då behöver du ju inte blenda nåt)

3) Kolla upp MMX/SSE funktionerna.. Dom är gjorda för exakt sånt här. Använder du dom på rätt sätt (blenda 4 pixels samtidigt, använda prefetching) så kommer det bli minst dubbelt så snabbt. Det tar tid att lära sig men det är väl värd det om man håller på mycket med sånt här och om det ska vara snabbt..
Här har du lite info.. VC stödjer det utan problem, men jag vet inte hur det är med andra compilers.
http://msdn2.microsoft.com/en-us/library/t467de55.aspx

Hoppas det här hjälper nåt

Visa signatur

Surf/jobbdator: i7 3770K | GA-Z77-D3H | 16 GB | Intel 510 + 750 GB | HD6870 2GB | 30'' | P180B
Server: Phenom X4 9500 | GA-MA78G-DS3H | 8 GB | 5.4 TB | YY-0221
Speldator: IBM PC XT | 8088 4.77 MHz | 640k | 10 MB HDD | EGA | 360k/720k diskett

Permalänk

Ok, jag är lite nyvaken också så jag ska kolla upp allting lite senare.

Varför ska det vara bit shifting i uträkningarna?

Vad jag menade på förra inläggetr var när man skulle ändra det till front to back.

Det borde bli nåt sånt här:
targeta = 255 - (((255 - targeta) * (255 - sourcea))>>8);
targetr = ((255 - targeta) * sourcer + targeta * targetr)>>8;
targetg = ((255 - targeta) * sourceg + targeta * targetg)>>8;
targetb = ((255 - targeta) * sourceb + targeta * targetb)>>8;

men då blir det fel om man tilldelar targeta ett värde. Då skulle man ju bara kunna ändra på variablen så att en variabel som inte kommer användas senare i uträkningen, vilket å blir sourcea. Men det förstör ju det pedagogiska i det. Hur kan jag namge variablarna istället för att det ska bli pedagogiskt rätt?

Visa signatur