Search

'2D'에 해당되는 글 1건

  1. 2006/08/03 옛날에 썼던 FadeIN/OUT 자료

옛날에 썼던 FadeIN/OUT 자료

Game Dev./General 2006/08/03 19:11 Posted by sonee
헐;; 거의 7년전에 올렸던-_- 강좌;;;

2000/01/31 00:04 | sonee ( 손희승 ) | 조회 1222  

안녕하세요.

원래는 타일 스크롤에 대한 강좌를 쓸려구 그랬는데..
이걸 먼저 쓰게 되었네요.
16비트 칼라를 중심으로 설명하겠습니다.

이번에 설명 드릴것은 Fade IN, Fade OUT 이라는건데요.

Fade IN 은 화면이 점점 밝아지는것을 말하고,
Fade OUT 은 화면이 점점 어두워 지는것을 말합니다.

모니터에서 발산하는 건 가산혼합이기 때문에.. 색을 섞을 수록 밝아집니다.
어둡게 찍기 위해서는 R,G,B 값을 줄여야 어두워지고 다시 밝게 찍기 위해서
는 R,G,B 값을 늘려야 밝아집니다.
이제 원리는 알았으니.. 그걸 구현만 하면 되겠지요?

서론은 줄이고 본론부터 들어가겠습니다^^;


구현 방법은 각각의 r,g,b 값을 얻어다가 백분율로 환산해서
계산해주면 되는데요.. 저는 여기서 64 단계를 사용했습니다.
백분율이 아닌 육십사분율--; 이 되겠군요.

한점한점 처리할때에는 r,g,b 값을 마스크를 통해 얻어온다음에
r=r*depth>>6;
g=g*depth>>6;
b=b*depth>>6;
이렇게 계산을 하면 됩니다.
계산한 후에 다시 마스크를 씌운담에, 필요없는부분들을 제거해야
합니다.

한점한점 처리하면 처리속도가 많이 늦어지는데요.. 이를 위해서 2점 처리를
사용하도록 하겠습니다. 음.. 처리 방법은 다 아실듯 싶습니다. WORD 값두개
를 DWORD 로 합친후에 마스크도 DWORD 크기로 하셔서 한점한점 처리하는것과
같이 처리하면 됩니다.

먼저 소스부터 써보겠습니다.

void CBMP::Fade(int depth)
{
DWORD Mask_G,Mask_B,Mask_R;
DWORD r,g,b;
DWORD temp;


if(bColorMode) // 5:6:5 모드인경우
{
Mask_R=0xf800f800;
Mask_G=0x07e007e0;
Mask_B=0x001f001f;
} else
{
Mask_R=0x7c007c00;
Mask_G=0x03e003e0;
Mask_B=0x001f001f;
}
if(depth>64) depth=64;

int next;
WORD *src=Lock(next);
for(int i=0;i {
WORD *pw=src+(next*i);
for(int j=0;j {
// 2점을 한번에 처리하기 위한..
DWORD dwsrc=*((DWORD*)pw);
temp=dwsrc;
r=temp&Mask_R;
r>>=6;
r*=depth;
r=r&Mask_R;
g=temp&Mask_G;
g>>=6;
g*=depth;

g=g&Mask_G;
b=temp&Mask_B;
b*=depth;
b>>=6;

b=b&Mask_B;
*((DWORD*)pw)=r|g|b;
pw+=2;
}
}
Unlock();
}

이렇게 되는데요.
한줄한줄 분석해보면


void CBMP::Fade(int depth)
이건 제가 화면 클래스로 사용하는 CBMP 에서 Fade 라는 함수입니다.
depth 는 0부터 64까지의 단계로 이루어져 있습니다.
{
DWORD Mask_G,Mask_B,Mask_R;
각 컬러 모드에 맞게 마스크 값을 정합니다.

DWORD r,g,b;
여기다가 r,g,b 값을 얻어서 저장해놓구요.

DWORD temp;
이건 현재 컬러값이 저장되는곳입니다.


if(bColorMode) // 5:6:5 모드인경우
말 그대루 5:6:5 모드이면

{
Mask_R=0xf800f800;
마스크 R 값을 두점을 처리할 수 있도록 정합니다.상위 5바이트를 얻어오는
거죠.

Mask_G=0x07e007e0;
마스크 G 값을 정합니다.

Mask_B=0x001f001f;
마스크 B 값을 정하구요.

} else
{
이건 5:5:5 모드일때 사용하는 마스크 값입니다.

Mask_R=0x7c007c00;
Mask_G=0x03e003e0;
Mask_B=0x001f001f;
}
depth 가 64이상이 되면 화면이 이상하게 바뀔테니.. 보정해주구요.
(음수도 보정해야겠죠^^)
if(depth>64) depth=64;

int next;
여기에는 락을하면 얻는 ddsd.lPitch/2 값이 들어갑니다.

WORD *src=Lock(next);
현재 서피스를 락을 한담에

for(int i=0;i {
화면 세로 크기만큼 반복합니다.

WORD *pw=src+(next*i);
현재의 위치를 pw 에 기억해놓구요.

for(int j=0;j두점을 한번에 처리하기 때문에 j+=2 라고 했습니다.

{
// 2점을 한번에 처리하기 위한..
DWORD dwsrc=*((DWORD*)pw);
두점을 얻어오고
temp=dwsrc;
그 값을 temp 에 넣습니다.
r=temp&Mask_R;
r 값을 마스크로 얻어온후에
r>>=6;
그냥 먼저 곱해버리면.. 표현 수의 범위가 넘어가기 때문에 먼저 나눕니다
상위 비트이기 때문에 상관 없죠.. ^^
r*=depth;
밝기를 곱하고
r=r&Mask_R;
다시 마스크를 씌어서 쓰레기값을 청소합니다.

g=temp&Mask_G;
g>>=6;
g*=depth;

g=g&Mask_G;
b=temp&Mask_B;
b*=depth;
b>>=6;

b=b&Mask_B;
*((DWORD*)pw)=r|g|b;
r,g,b 값을 더한후에 대입을 합니다.

pw+=2;
두점 뒤로 갑니다.
}
}
Unlock();
락을 풀어줘야죠.. ^^
}


이상입니다.
사용 방법은

for(int i=64;i>0;i--)
{
back->Fade(i);
Flip();
}

이렇게 쓰시구요. 저기 중간에 동기화를 넣어서 처리하면되겠군요.^^

위는 어둡게 하는거고
밝게하는건

for(int i=0;i<64;i++)
{
back->Fade(i);
Flip();
}

이렇게 하면 됩니다.

제가 글솜씨가 없어서..
이해가 잘 되셨는지 모르겠네요.
그럼.^^

----------------

g 값을 쉬프트 시킬때 한번에 6개를 해주면....
약간 색이 이상해지는군요.
그부분을
g=temp&Mask_G;
g>>=3;
g*=depth;
g>>=3;
g=g&Mask_G;

바꿔주면 됩니다.
두번 쉬프트 하는 과정을 거치는데...
따로 계산해주면 해결되지만.... 위의 소스 사용시 이렇게 변형하시면
괜찮을듯^^  
TAG