디시인사이드 갤러리

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

갤러리 본문 영역

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

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.22 23:15:30
조회 444 추천 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
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 공개연애가 득보다 실인 것 같은 스타는? 운영자 25/10/06 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47729 65
2894849 'ㅎㅂ' 윤 공주 실시간 라방킴ㄱㄱ ㅇㅇ(183.96) 10:32 0 0
2894848 공무원인데 개발자 일 배우는거 추천하냐? [3] 프갤러(124.57) 10:16 12 0
2894847 게임 개발하려고 객체지향 이론 3년 공부했다 ㅇㅇ(211.235) 10:11 9 1
2894846 지뢰계 발명도둑잡기(118.216) 10:09 7 0
2894845 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥덩냥이♥갤로그로 이동합니다. 09:56 9 0
2894843 야한노래가 성경험 촉진 발명도둑잡기(118.216) 09:39 17 0
2894842 美 노랫말 33%에 '술' '마약' 들어간다 발명도둑잡기(118.216) 09:36 14 0
2894840 연휴라 일도 없고 게임한다고 개발일 이틀쉬는중 [2] ㅆㅇㅆ(124.216) 08:43 29 0
2894839 참취..ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08:15 17 0
2894838 스타트, 중소 기업 개발자분들 워라벨 어때요? [3] 프갤러(39.112) 08:10 33 0
2894837 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08:06 13 0
2894836 하루 한 번 헤르미온느 찬양 헤르 미온느갤로그로 이동합니다. 08:05 17 0
2894835 Ada왜바이럴하는거잉? moo토낑7920(220.122) 08:05 22 0
2894833 웹 말고 다른 개발하는 사람들도 좀 잇나 [1] ㅇㅇ갤로그로 이동합니다. 07:37 29 0
2894827 근데 웹개발 하다가 임베 가는게 가능함? [6] 물단또갤로그로 이동합니다. 06:52 52 0
2894826 강화유리 필름 1+1 다음주에 온다. 넥도리아2025(112.170) 06:45 11 0
2894805 성공했다. 브레이버갤로그로 이동합니다. 03:19 35 0
2894800 나님 고객님은 모두의 고객입니다. 브레이버갤로그로 이동합니다. 02:32 49 0
2894794 나님 분해 시작합니다. 브레이버갤로그로 이동합니다. 02:05 53 0
2894792 이런것도 물경력임? [3] 프갤러(218.153) 01:40 59 0
2894782 러스트 담론을 해체하다 책을 객관적으로 업댓 예정 나르시갤로그로 이동합니다. 01:10 27 1
2894781 앞으로 러스트 씨부리는 것들은 ㅇㅇ(49.165) 01:06 30 0
2894780 러스트 담론을 해체하다: 5.6 개발 툴체인의 기술적 과제와 생산성 나르시갤로그로 이동합니다. 01:05 23 0
2894779 Ada 프로그래밍: 3.3.1 숫자 리터럴 나르시갤로그로 이동합니다. 00:56 23 0
2894778 Ada 프로그래밍: 3.3 리터럴 (Literals) 나르시갤로그로 이동합니다. 00:56 19 0
2894777 Ada 프로그래밍: 3.2 예약어 (reserved words) 나르시갤로그로 이동합니다. 00:55 17 0
2894776 Ada 프로그래밍: 3.1 식별자 (identifier) 나르시갤로그로 이동합니다. 00:55 20 0
2894775 Ada 프로그래밍: 3. 어휘 요소 나르시갤로그로 이동합니다. 00:54 25 0
2894772 근데 중소 AI는 자체개발 아니지 ㅇㅇ(106.102) 00:19 34 0
2894771 요즘 러스트 하는새끼들은 서보가 뭔지도 모르고 ㅇㅇ(49.165) 00:13 38 0
2894770 홍대가는중 개멍청한유라갤로그로 이동합니다. 00:04 35 0
2894768 방금 핫한 알고리즘이 추천해주었는데 ㅎㅎㅎ 넥도리아2025(112.170) 10.07 25 0
2894767 외롭다.. ㅇㅇ(14.52) 10.07 20 0
2894766 재밌는 루빅스 큐브의 세계 ㅇㅇ(121.168) 10.07 18 0
2894765 이번 추석 연휴 윤석열 배터지게 먹엇다 [2] 야옹아저씨갤로그로 이동합니다. 10.07 44 0
2894764 왜 러슬람은 까이나? [13] ㅇㅇ(49.165) 10.07 58 0
2894762 러슬람 병신새끼들은 [3] ㅇㅇ(49.165) 10.07 45 2
2894760 자연스러운 야동 추천좀 [11] 프갤러(49.142) 10.07 65 0
2894758 저장용 ♥덩냥이♥갤로그로 이동합니다. 10.07 30 0
2894757 나님 프갤 입장. 윤카는 무슨 생각 하실깡? 넥도리아2025(112.170) 10.07 55 0
2894755 극좌국뽕 영포티는 짱국에서도 ㅂㅅ 취급 당하는거 개웃교 ㅋㅅㅋ ♥덩냥이♥갤로그로 이동합니다. 10.07 26 0
2894754 '러스트 의지만 있으면 충분하다'란 말 정정하겠습니다. [7] 프갤러(110.8) 10.07 53 0
2894753 음기 충전 [1] 발명도둑잡기(39.7) 10.07 66 0
2894752 삼고액션빔 [1] ㅇㅇ(223.39) 10.07 35 2
2894749 한반도에 전쟁이 발생했을 경우… 어떻게 살아남아야 할까? [1] 발명도둑잡기(118.216) 10.07 40 0
2894747 핑모 너무 조아❤+ [1] ♥덩냥이♥갤로그로 이동합니다. 10.07 30 0
2894746 아이유 근황 발명도둑잡기(39.7) 10.07 31 0
2894745 갓본은 또 노벨상 받앗넹 벌써 30개 ㄷㅅㄷ [3] ♥덩냥이♥갤로그로 이동합니다. 10.07 41 0
2894744 명절연휴에 일하고와서 써보는 39개월차 개발자 여태다닌 회사 일기 [3] 프갤러(211.193) 10.07 175 1
뉴스 에스파, 내년 홍콩 공연 전석 매진…세 번째 월드 투어 ‘대흥행 예고’ 디시트렌드 10.05
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2