Archived

This topic is now archived and is closed to further replies.

Dismantler

Fade to Black in 16 bit color mode

Recommended Posts

Alpha blending will do the trick. Just take a black bitmap (or use 0 to blend into in your Fade() function) and start put over top your image. Then make the black bitmap (or whatever) more opaque until the screen has faded.

Share this post


Link to post
Share on other sites
Alpha-Blending is probably your only choice. But it is very slow. There are tutorials on how to do this on this site in the reference section. I think you could also use gamma controls to fade the screen (it''s a lot faster than software alpha-blending) but there is no support for this in the HEL.

Share this post


Link to post
Share on other sites
I thought the SNES only used something like 256 onscreen at once anyway? So I don''t see why it would be a problem.

By the way, alpha-blending will be far less slow if you keep your video buffers in system memory, although not as fast as running the graphics in video memory and avoiding alpha blending

Share this post


Link to post
Share on other sites
Yeah, I used gamma stuff. No offense (if any) but it's ugly... It makes the colors look weird and stuff. I wanted to try assembler as seen on one of the sites tutorials here is the code:

  
_asm
{
xor eax, eax // Initialize the variables. This is VC++ 6

xor ebx, ebx // inline Assembler. Mostly this is designed

mov ecx, xheight // for a DirectDraw locked surface.

xor edx, edx
mov esi, ddsdSource.lpddsprimary // This variable should be the pointer to the source surface.

mov edi, ddsdDest.lpddsprimary // This variable should be the pointer to the dest surface.


heightLoop16bit565:
push ecx
mov ecx, xwidth
widthLoop16bit565:
mov ax, [esi] // Reads the 16-bit pixel (this is designed for 565 RGB).

test ax, ax // Tests it with an AND to itself. Sets flags, basically.

jz exLoop16bit565 // Skips if pure black (transparent in my game). Use cmp ax, value

// if black isn't transparent for you. Take out this line and the previous

// if you don't need a transparent additive effect.

mov dx, [edi]
and edx, 63454 // Take out the last bits of red, green, and blue.

and eax, 63454 // This ensures the last bits aren't used by the colors.

add eax, edx // This is necessary later on. Total source and dest up into a 32-bit register.


mov ebx, eax // EBX is going to be used as our temporary register here.

and ebx, 65536 // AND it by 65536, which strips out all but the last bit if it overflowed past the max.

jz noRedLoop16bitAAB565 // Skips the next line if an overflow did not occur.

or eax, 63488 // This OR turns on all the red bits.


noRedLoop16bitAAB565:
mov ebx, eax // We do the same thing to green.

and ebx, 2048 // Oh and don't worry about bit 17 being turned on in red,

jz noGreenLoop16bitAAB565 // that will be solved later.

or eax, 2016

noGreenLoop16bitAAB565:
mov ebx, eax // Finally we process blue.

and ebx, 32 // Almost done here!

jz noBlueLoop16bitAAB565
or eax, 31

noBlueLoop16bitAAB565:
mov [edi], ax // Move the latter 16-bits of the pixel into the destination.


exLoop16bit565:
add esi, 2 // Add 2 bytes to the source pointer, to go to the next pixel.

add edi, 2 // Ditto with the destination pointer.

dec ecx // Decrease ECX. As you may have noticed, height was PUSHed in ECX,

// and we did that to make room for width. x86 needs more registers.

jnz widthLoop16bit565 // If we aren't out of pixels on that row, go back for another pixel.

pop ecx // Pulls the height from the stack. Height is now in ECX for a sec.

add esi, ipitchsrc // ipitchsrc should be the pitch DirectDraw gave you in Lock()

add edi, ipitchdest // minus twice the source width. ipitchdest should be the same thing for

dec ecx // the destination surface. We're almost done, now we are decreasing

jnz heightLoop16bit565 // the height and looping back for the next row.

}


only problem is, it gives errors saying that (these lines:
  	
mov esi, ddsdSource.lpddsprimary // This variable should be the pointer to the source surface.

mov edi, ddsdDest.lpddsprimary // This variable should be the pointer to the dest surface.



"lpddsprimary" must be a valid union/struct/type. So I can't use that for now, can anyone tell me what I'm supposed to do?

Currently, this is the ugly gamma result that I'm using:

  
//initialize the gamma control so that we can use it.

LPDIRECTDRAWGAMMACONTROL lpDDGammaControl = NULL;

//this structure will be the ramp value that we modify

DDGAMMARAMP DDGammaRamp;

//this structure will hold the old gamma values so that we can reset our video card after our fade is complete.

DDGAMMARAMP DDGammaOld;

lpddsprimary->QueryInterface(IID_IDirectDrawGammaControl,(void **)&lpDDGammaControl);

lpDDGammaControl->GetGammaRamp(0, &DDGammaOld);
lpDDGammaControl->GetGammaRamp(0, &DDGammaRamp);

for(int blackloop=0;blackloop<256;blackloop++)
{

//we wouldn't want to decrement a value unless it's greater than 0

if(DDGammaRamp.red[blackloop] > 0)
{
//set the current value of DDGammaRamp.Red to 0.

DDGammaRamp.red[blackloop]=0;
//now let's update our primary surface with the new gamma setting

lpDDGammaControl->SetGammaRamp(0, &DDGammaRamp);

} //end if


//the routine was a little too fast so this slows it down a bit….


//we wouldn't want to decrement a value unless it's greater than 0

if(DDGammaRamp.green[blackloop] > 0)
{
//set the current value of DDGammaRamp.yellow to 0.

DDGammaRamp.green[blackloop]=0;
lpDDGammaControl->SetGammaRamp(DDSGR_CALIBRATE, &DDGammaRamp);
} //end if


//the routine was a little too fast so this slows it down a bit….


//we wouldn't want to decrement a value unless it's greater than 0

if(DDGammaRamp.blue[blackloop] > 0)
{
//set the current value of DDGammaRamp.Blue to 0.

DDGammaRamp. blue [blackloop]=0;
lpDDGammaControl->SetGammaRamp(DDSGR_CALIBRATE, &DDGammaRamp);

} //end if


//the routine was a little too fast so this slows it down a bit….


} //end for



lpDDGammaControl->SetGammaRamp(0, &DDGammaOld);



Edited by - Dismantler on August 14, 2001 10:37:08 AM

Share this post


Link to post
Share on other sites
Why don''t you pass ddsdSource.lpddsprimary and the other one as pointer parameters? Then use these parameters in the asm code.

If that doesn''t work, why don''t you convert the asm into c?

If that doesn''t work either, I''ve got a question about the gamma:
You check if red/green/blue is above 0. If it is, you set it to 0. If you want it to fade, shouldn''t you decrease the intensities? Otherwise, won''t the screen will go completely black? Tell me if I''m wrong, I''m not working with DirectX, sitting in linux...

Share this post


Link to post
Share on other sites
About the gamma, what I want is for the screen to be completely black, it _is_ called a fade to black... =^] I don''t know what''s wrong with the asm becuase I just copied it off one of the articles here. BTW, I know nothing about assembly +_+.

Share this post


Link to post
Share on other sites
Completely black slowly, or immediately? I suppose slowly, while a fade is slow... If you put all gammas to 0, won''t the screen go black at once?

To make it easier, why not put those two variables (whatever they were called) in two new variables. ptr is the data type the two display pointers are declared as (probably some redefinition of an int). Look in the correct *.h file:

ptr source, dest;

source = lddsrouceblabla...
dest = destination-variable

In the asm-code, replace the two wrong lines:

mov esi, ddsdSource.lpddsprimary
mov edi, ddsdDest.lpddsprimary

with:

mov esi, source
mov edi, dest

BTW, you should learn some asm. It''s really great when you need some high-speed graphics.

Share this post


Link to post
Share on other sites
That ASM code is for additive blending not fading to black! Check out my alpha-blending article here on GameDev. To fade a screen to black you are basically alpha-blending you screen with the color (0,0,0). There is sample code in the article written in C++ so it should be easy to follow. If you want ASM it is in there as well.

The article talks about alpha-blending to images not fading to black. There are some speed-ups that you can use when you know one of the images is all black. You should be able to figure it out once you read the article.

Good luck
hebertjo

Share this post


Link to post
Share on other sites