디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

적분시리즈: 3. 다양한 그리기 효과

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.22 23:15:30
조회 438 추천 0 댓글 2


115DF7144B0946A08AAE04

멋진 그래픽을 만드려고 노력하다 보면 알파블렌딩만으로는 원하는 걸 만들지 못할 때가 있다.
그래서 다양한 그래픽 효과를 여기서 추가해보고자 한다.

D3D에서는 Render State라고 해서 렌더링 시에 여러가지 설정을 줄수 있게 해놓았다.
IDirect3DDevice9::SetRenderState로 RenderState를 설정할 수 있고
IDirect3DDevice9::GetRenderState로 RenderState값을 가져올 수 있다.

다음과 같이 쓰면 된다.
SetRenderState( 상태 종류, 설정할 값 );
예를 들자면
m_pd3dd->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
이런 식으로 하면 된다.

여기서는 특히 중요한 몇 개의 설정들을 살펴보겠다.

*D3DRS_ALPHAFUNC
알파채널이 섞인 텍스쳐를 화면에 출력할 때 어떻게 할 것인가?

1. D3DCMP_NEVER : 절대로 출력하지 않는다.
2. D3DCMP_LESS : D3DRS_ALPHAREF 값보다 작으면 출력한다.
3. D3DCMP_EQUAL : D3DRS_ALPHAREF 값과 같으면 출력한다.
4. D3DCMP_LESSEQUAL : D3DRS_ALPHAREF 값과 같거나 작으면 출력한다.
5. D3DCMP_GREATER : D3DRS_ALPHAREF 값보다 크면 출력한다.
6. D3DCMP_NOTEQUAL : D3DRS_ALPHAREF 값과 같지 않으면 출력한다.
7. D3DCMP_GREATEREQUAL : D3DRS_ALPHAREF 값과 같거나 작으면 출력한다.
8. D3DCMP_ALWAYS : 항상 출력한다.


*D3DRS_ALPHAREF
D3DRS_ALPHAFUNC에서 비교대상으로 사용할 값

예를 들어서 알파채널이 100 이상인 부분만 출력하고 싶다면,

SetRenderState(D3DRS_ALPHAREF, 100);
SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
이렇게 하면 된다. 참 쉽죠?

*D3DRS_BLENDOP
텍스쳐가 그려질 때, Dest과 Src를 어떻게 섞을까?
(Dest는 그려질 자리에 원래 있던 그림, Src는 새로 그려질 그림을 말합니다.)

1. D3DBLENDOP_ADD :  Result = Dest + Src
2. D3DBLENDOP_SUBTRACT :  Result = Src - Dest
3. D3DBLENDOP_REVSUBTRACT :  Result = Dest - Src
4. D3DBLENDOP_MIN :  Result = Dest, Src 중 작은 값
5. D3DBLENDOP_MAX :  Result = Dest, Src 중 큰 값


*D3DRS_SRCBLEND, D3DRS_DESTBLEND
Dest과 Src를 섞을때 어떤 값을 곱할까?

1. D3DBLEND_ZERO : 0을 곱한다.
2. D3DBLEND_ONE : 1을 곱한다.
3. D3DBLEND_SRCCOLOR : Src의 R, G, B, A값을 곱한다.
4. D3DBLEND_INVSRCCOLOR : Src의 1-R, 1-G, 1-B, 1-A값을 곱한다.
5. D3DBLEND_SRCALPHA : Src의 Alpha값을 곱한다.
6. D3DBLEND_INVSRCALPHA : Src의 1-Alpha값을 곱한다.
7. D3DBLEND_DESTALPHA : Dest의 Alpha값을 곱한다.
8. D3DBLEND_INVDESTALPHA : Dest의 1-Alpha값을 곱한다.
9. D3DBLEND_DESTCOLOR : Dest의 R, G, B, A값을 곱한다.
10. D3DBLEND_INVDESTCOLOR : Dest의 1-R, 1-G, 1-B, 1-A값을 곱한다.

이 얘기로 충분히 이해가 안 될지도 모른다.
그래서 예를 들어가면서 설명하겠다.

*알파블렌딩을 하고 싶다. 즉 Src의 알파값이 255면 Src가 그대로 나타나고, 127 이면 Src와 Dest가 반반씩 섞여서 나오고, 0 이면 Dest가 그대로 나오게 하고 싶으면?

SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);

그러면 Src에 (알파값)이 곱해지고 Dest에 (1-알파값)이 곱해지고 둘을 더한 것이 결과가 된다.
Result= Src * SrcAlpha + Dest * (1 - SrcAlpha)
그러면 Src의 알파값이 클수록 Src가 진하게 나타나고, 작을수록 Dest가 진하게 나타날것이다.


*블렌딩이고 뭐고 없이 Src를 그대로 화면에 출력하고 싶으면?

SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);

Result = Src * 1 + Dest * 0 이 되어서 결국 Result = Src 가 된다.
Src의 알파값이 어떻든 항상 Src가 그대로 출력되는것이다.


*Dest에 Src를 더해지게 하고 싶으면?

SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);

Result = Src * 1 + Dest * 1

Src의 알파값이 반영되게 하고 싶으면
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
Result = Src * SrcAlpha + Dest * 1 이 되어, 알파값 반영된다.


*Dest에 Src를 마스킹하고 싶으면?
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
Result = Src * 0 + Src * DestColor =  Src*Dest

기타 등등등... 응용방안은 무궁무진하다. 게다가 ID3DXSprite::Draw에 넣어주는 Color값이 기억나는가? 그것까지 이용한다면 더 강력한 그래픽 효과를 사용할수 있을것이다.

Result = Dest * DestBlend + Src * SrcBlend * Color (BlendOp에 따라서 +가 - 나 min, max로 바뀔 수 있는 것도 기억!)

참고:

*D3DRS_ALPHAREF 를 0으로 설정하고 D3DRS_ALPHAFUNC 를 D3DCMP_GREATER로 설정하면
알파채널이 0보다 큰 부분만 출력된다. 근데 D3DRS_ALPHAFUNC 를 D3DCMP_ALWAYS 로 설정해도 어차피 알파채널이 0인 부분은 그리면 출력안되니깐 둘은 같지 않은가?

같지 않다! AlphaFunc에서 걸러진 픽셀들은 SrcBlend, DestBlend에 와보지도 못하지만, AlphaFunc을 통과한 픽셀은 SrcBlend, DestBlend 단계까지 올 수 있다.

예)
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
일때

i)
SetRenderState(D3DRS_ALPHAREF, 0);
SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);

ii)
SetRenderState(D3DALPHAFUNC, D3DRS_ALWAYS);

i)와 ii)경우를 생각해보자.

i)는 알파값이 0인 픽셀들을 걸러져서 그려지지 않으므로, 알파가 0인 부분은 Dest가 그대로 남아있을 것이다.
ii)는 알파값이 0인 픽셀들이 AlphaTest를 통과하고 Result=Dest*0 + Src*1 이므로, 알파값이 0인 부분도 Src가 되어있을것이다.

그리기 모드를 설정하는 함수를 추가해보자. RenderState를 설정하여 무궁무진한 그래픽 효과를 줄수 있지만, 그중에서 주로 쓰이는 몇 가지만 골라봤다.

GRET GGame::SetDrawMode(int mode, int cmode)
{
    if(!m_pd3dd)return GRET_ERROR_NODEVICE;
    m_pspr->Flush();
    m_pd3dd->SetRenderState(D3DRS_COLORWRITEENABLE, cmode);
    switch(mode)
    {
    case DM_Normal: // Result = Src*SrcAlpha + Dest*(1-SrcAlpha)
        m_pd3dd->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        m_pd3dd->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
        m_pd3dd->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
        break;
    case DM_NoBlend: // Result = Src*1 + Dest*0
        m_pd3dd->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
        m_pd3dd->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
        m_pd3dd->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
        break;
    case DM_Add: // Result = Src*SrcAlpha + Dest*1
        m_pd3dd->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        m_pd3dd->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
        m_pd3dd->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
        break;
    case DM_Subtract: // Result = Dest*1 - Src*SrcAlpha
        m_pd3dd->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        m_pd3dd->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
        m_pd3dd->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
        break;
    case DM_Multiply: // Result = Src*DestColor + Dest*0
        m_pd3dd->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
        m_pd3dd->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
        m_pd3dd->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
        break;
    }
    return 0;
}

SetRenderState로 상태를 변경하기 전에 먼저 ID3DXSprite::Flush()를 호출했다. 이 함수는 그동안그려놓았던 것들을 비워주는 함수이다. ID3DXSprite는 Draw하면 그때 바로 화면에 그리는 게 아니라, 차곡차곡모아두었다가 한 번에 화면에 그려준다. 만약에 전에 그리라고 했던것들이 화면에 그려지지 않고 ID3DXSprite내에쌓여있었다면, RenderState를 바꿔주면, 쌓여있던 것들에게까지 전부 영향을 주게 된다. 그러므로 RenderState를바꾸기 전에는 먼저 Flush()를 해줘야 원하는 결과를 얻을수 있다.

SetRenderState(D3DRS_COLORWRITEENABLE, cmode)는 그릴 채널을 선택하는 부분이다. 때때로,텍스쳐의 Red 채널만 그리고 싶다던가, Blue 채널만 그리고 싶다던가 할 때가 있다. 이 때,D3DRS_COLORWRITEENABLE을 변경함으로써 그 소원을 이룰 수 있다.

이제 한 번 테스트를 해보자.

void GGame::OnDraw()
{
    SetDrawMode(DM_Normal);
    m_sprs.DrawSprite(0, 10, 10, D3DCOLOR_ARGB(255, 255, 255, 255));
    SetDrawMode(DM_Add);
    m_sprs.DrawSprite(0, 140, 10, D3DCOLOR_ARGB(255, 255, 255, 255));
    SetDrawMode(DM_Subtract);
    m_sprs.DrawSprite(0, 270, 10, D3DCOLOR_ARGB(255, 255, 255, 255));
    SetDrawMode(DM_Multiply);
    m_sprs.DrawSprite(0, 400, 10, D3DCOLOR_ARGB(255, 255, 255, 255));
    SetDrawMode(DM_NoBlend);
    m_sprs.DrawSprite(0, 530, 10, D3DCOLOR_ARGB(255, 255, 255, 255));
}

추천 비추천

0

고정닉 0

0

원본 첨부파일 1

댓글 영역

전체 댓글 0
등록순정렬 기준선택
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 가족과 완벽하게 손절해야 할 것 같은 스타는? 운영자 24/06/24 - -
162489 프갤 들어오는 학생넘들은 오바마에게 사죄하라구 & 퇴갤~~ [2] Rhea갤로그로 이동합니다. 09.12.15 63 0
162488 학원도시 노트북의 위엄.JPG [2] Rhea갤로그로 이동합니다. 09.12.15 223 0
162486 다시 질문!!레알 급함.. ㅠ ㅠ [5] C초보(115.161) 09.12.15 65 0
162485 C++ 공부하는 좆은 방법 prismatic갤로그로 이동합니다. 09.12.15 77 0
162484 좀 정직해봐라 [3] ㅇㅇㅃ갤로그로 이동합니다. 09.12.15 105 0
162483 C++ 공부하려면 볼만한 책 [1] 성대아싸(121.137) 09.12.15 106 0
162482 하루미 선생님...♡♡♡♡ [3] Rhea갤로그로 이동합니다. 09.12.15 137 0
162480 항라 고기 고기가 먹고싶다긔! [7] prismatic갤로그로 이동합니다. 09.12.15 43 0
162478 시끄럽다, 니들이 평생 못할 거, 하는 방법이나 알려줌. [1] Rhea갤로그로 이동합니다. 09.12.15 101 0
162477 c랑 c ++대강 마쳤는데 방학동안 뭘 공부해야 좋을까요;; [19] 까북갤로그로 이동합니다. 09.12.15 151 0
162476 갑자기 왠 책 떡밥이냐긔!!! [1] Rhea갤로그로 이동합니다. 09.12.15 81 0
162475 뉴비가 포인터 관련 질문 던져염~ [12] 가상현실갤로그로 이동합니다. 09.12.15 77 0
162474 고딩이 개발한 서울버스라는 어플에 관한 궁금증 [4] 궁구미(180.68) 09.12.15 180 0
162473 밑에 어떤 횽이 c++책으로 성안당 거를 추천했기에 쓰는데; [7] 까북갤로그로 이동합니다. 09.12.15 153 0
162472 어떡해 내가 증명할 수 있는건 이런 것 밖에 없다. [21] (124.56) 09.12.15 186 0
162471 c++책 하나 추천하고자 하네요 [2] ...(124.63) 09.12.15 100 0
162470 알고리즘 잘하는 형들 헬프미! [4] 알고리즘(210.93) 09.12.15 80 0
162469 형들! 씨썊급해 ㅜㅜ 숙제아님.. [5] 씼쌰ㅃ(123.142) 09.12.15 63 0
162468 자주 들려서 눈팅같은것좀 해야겠음. [1] BoA갤로그로 이동합니다. 09.12.15 62 0
162466 숙신도 까이는데 칭송이라고 못 깔꺼야 없지 [2] nRST(61.82) 09.12.15 42 0
162465 칭송받는자가 여자친구가 있는 이유 [1] ㅇㅇㅃ갤로그로 이동합니다. 09.12.15 87 0
162464 sean 횽 irc 소환 [1] 칭송받는자(210.118) 09.12.15 45 0
162463 크리스마스 계획 [5] 칭송받는자(210.118) 09.12.15 91 0
162462 일영사전형 [3] ㅇㅇㅃ갤로그로 이동합니다. 09.12.15 68 0
162461 학교다닐때... [6] 똥구녕향기(211.217) 09.12.15 68 0
162460 이산수학은 원서로 공부하는게 낫지 않나영? [3] 성대아싸(121.137) 09.12.15 118 0
162459 프로그래밍 서적 [24] (124.56) 09.12.15 1428 0
162456 횽들 strstr 함수 구현부좀 봐주세요 ㅠㅠ [16] ㅁㄴㅇㄹ(59.8) 09.12.14 316 0
162455 ㅇ횽, 책 추천책 글 줍세요. [5] 어떡해갤로그로 이동합니다. 09.12.14 153 0
162454 프로그래머가 머 별거냐? ㅋㅋㅋㅋㅋㅋ [7] ㅅㅅ(210.217) 09.12.14 161 0
162453 dll 동적링크에대해서 질문좀... [7] 캐발자갤로그로 이동합니다. 09.12.14 84 0
162452 나 디시한지 3일인데... [1] 똥구녕향기(211.217) 09.12.14 43 0
162451 SKT 광고 생각대로 [1] nRST(61.82) 09.12.14 50 0
162449 지뢰찾기 이럴 경우 확률이 필요한거 맞지? [14] 오호라라라아(203.255) 09.12.14 178 0
162448 테이블 하나 임포트하는데... [2] 아주아슬갤로그로 이동합니다. 09.12.14 79 0
162447 박세안횽은 봄미다 [3] nRST(61.82) 09.12.14 47 0
162446 마지막으로 프갤 형님들 이산수학 교재 혹은 강의 추천 좀 !!! [25] 늅늅늅비비비갤로그로 이동합니다. 09.12.14 234 0
162444 시기_젖절한_위꼴사.jpg [4] 숙신갤로그로 이동합니다. 09.12.14 102 0
162443 LightEach횽 봐봐 [14] 푸바(118.34) 09.12.14 118 0
162442 ... [3] 물속의다이아갤로그로 이동합니다. 09.12.14 51 0
162441 어떡해 일기 #9 :: 공부하면 할수록 두려워짐. [21] 어떡해갤로그로 이동합니다. 09.12.14 1161 0
162440 지앤넷이라는 회사.. [1] 궁금(221.151) 09.12.14 117 0
162439 아 씨 ㅡㅡ [5] H2(222.251) 09.12.14 61 0
162438 네이트온 스킨을 바꿨는데 [6] 숙신갤로그로 이동합니다. 09.12.14 150 0
162437 nRST 보긔 [6] Rhea갤로그로 이동합니다. 09.12.14 133 0
162435 xmldom이 대체 뭐임ㅠㅠㅠㅠㅠㅠ [3] 뭐야(221.160) 09.12.14 80 0
162434 집에 가고 싶음여 아주아슬갤로그로 이동합니다. 09.12.14 42 0
162433 사실 시험공부하려고 컴퓨터 켰는데.. [4] BoA갤로그로 이동합니다. 09.12.14 59 0
162432 횽들 자료구조론 혼자 공부하려고 하는데 교재나 강의 추천좀 !!!!!!! [33] 늅늅늅비비비갤로그로 이동합니다. 09.12.14 276 0
162431 밑에 첫출근글 보니 옛날 생각나네 [4] 박뮤탈갤로그로 이동합니다. 09.12.14 97 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2