디시인사이드 갤러리

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

갤러리 본문 영역

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

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.22 23:15:30
조회 445 추천 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 47777 65
2895147 77개 해외 무관사무실 68% 도청 등 보안장비 미흡 발명도둑잡기(118.216) 02:40 4 0
2895146 박혁거세 발명도둑잡기(118.216) 02:37 6 0
2895145 Z-A 일주일 기다리자 꽃길 포켓몬스터레전드 Z-A... 오늘 저녘이면 넥도리아2025(220.74) 02:14 6 0
2895143 피크민 아기 발명도둑잡기(118.216) 02:00 9 0
2895142 아 개씨발 모기 ♥덩냥이♥갤로그로 이동합니다. 01:51 14 0
2895141 트레이더로 20조 번 러시아 수학자 발명도둑잡기(118.216) 01:50 9 0
2895138 그 혹시 뒷세계 밤문화 아시는분 있으신가요 ㅇㅅㅇ 궁금한게 많네요 [2] ㅇㅇ(223.38) 01:33 22 0
2895134 오늘 출근 하시는 분 부자 되실 듯 발명도둑잡기(118.216) 01:25 9 0
2895124 음악 책과 SAT 점수 [2] 발명도둑잡기(118.216) 01:10 12 0
2895122 안예은 AHN YE EUN - 열 달 아흐레 1009 [1] 발명도둑잡기(118.216) 00:37 10 0
2895121 노시계도 놀란 찢시계 논란 ㄷㅅㄷ [1] ♥덩냥이♥갤로그로 이동합니다. 00:36 16 0
2895120 23억 로또 당첨되고 실제 사용처 정리해봤음... [1] ㅇㅇ(223.38) 00:36 22 0
2895118 murmulator 발명도둑잡기(118.216) 00:05 10 0
2895116 PICO-56 65c02 컴퓨터 발명도둑잡기(118.216) 00:04 10 0
2895114 라스베리파이 피코로 286 만들기 발명도둑잡기(118.216) 00:02 15 0
2895111 주 4.5일제를 왜 반대하는거임? [1] 야옹아저씨갤로그로 이동합니다. 10.09 28 0
2895110 성소수자는 미인계에 약한 것 같아 보인다. [1] 발명도둑잡기(118.216) 10.09 23 0
2895108 글 쓰고 자거 싶은데.. 이미 체력이.. [2] ♥덩냥이♥갤로그로 이동합니다. 10.09 30 0
2895107 오랜만에 왔는데 갤이 더 씹창이 나있구나 [5] 아스카영원히사랑해갤로그로 이동합니다. 10.09 43 0
2895106 날벌레들은 모기약으로 안 죽넹.. [3] ♥덩냥이♥갤로그로 이동합니다. 10.09 34 0
2895104 귀국하면 집가서 택배 뜯어야 됨 [1] 류류(122.197) 10.09 19 0
2895103 나트륨찡은 요즘 어디 갤에서 노냐 [1] 류류(122.197) 10.09 22 0
2895102 키 140대 고스로리 찍지못했음 ㅇㅅㅇ 류류(122.197) 10.09 12 0
2895101 모기가 하나도 없어서 완전 개꿀이였음 류류(122.197) 10.09 12 0
2895100 140대 고스로리녀 돈주고 함 떡치자 라고 할걸 류류(122.197) 10.09 16 0
2895099 [냥덩칼럼] 삶은 죽음으로 시작된다 [5] ♥덩냥이♥갤로그로 이동합니다. 10.09 38 0
2895098 귀국하면 피부과 가야겠다 류류(122.197) 10.09 13 0
2895097 마지막날에 키 140대에 호리호리한 고스로리 코스녀봤음 [2] 류류(122.197) 10.09 24 0
2895096 한투증 api 웹소켓 자꾸 데이터 보내다가 마는데 [2] 밀우갤로그로 이동합니다. 10.09 23 0
2895095 내일 헨조센으로 귀국 류류(122.197) 10.09 13 0
2895093 모기 느낌.. 심상치 않당.. [2] ♥덩냥이♥갤로그로 이동합니다. 10.09 28 0
2895087 박시영, 충격적인 얘기입니다. 미국이 사회주의가 될 수 도 있다? 발명도둑잡기(118.216) 10.09 14 0
2895086 한국사람들은 한국이 어떤 위치에 있는지 모른다 발명도둑잡기(118.216) 10.09 17 0
2895085 몰랐는데 이재명 되게 서민적이네 [1] 칸예갤로그로 이동합니다. 10.09 36 0
2895084 파이썬 망해간다. [3] 프갤러(59.16) 10.09 52 0
2895083 따당이 얼굴 봤는데 초고수임 [5] ♥덩냥이♥갤로그로 이동합니다. 10.09 46 0
2895082 김민지 선수의 주종목 400m에 도전한다 진짜 승부 과연 결과는? 발명도둑잡기(118.216) 10.09 16 0
2895081 따당이 개발자 점수 몇점인가요 ㅇㅅㅇ [7] 따당갤로그로 이동합니다. 10.09 69 0
2895080 동아시아 유일 자국어로 타자 치는 나라🇰-1f1f7; 발명도둑잡기(118.216) 10.09 19 0
2895079 '시빌 워' 현실화?…'이민자 단속' 軍 투입에 두쪽난 미국 [1] 발명도둑잡기(118.216) 10.09 18 0
2895077 시카고로 북진한 텍사스군.. '160년 만의' 내전 위기 발명도둑잡기(118.216) 10.09 11 0
2895074 김민지 vs 김동현 100m 발명도둑잡기(118.216) 10.09 19 0
2895072 이제 하다하다 k오_피가 상륙했노 질문 받는다 ㅇㅇ(39.7) 10.09 16 0
2895068 사람이 언제 죽는다고 생각하나? [2] ♥덩냥이♥갤로그로 이동합니다. 10.09 41 0
2895067 때로는 좋은건 가까이 있다 [2] chironpractor갤로그로 이동합니다. 10.09 38 0
2895066 내일 출근 안하면 개추 ㅋㅋ [1] 루도그담당(118.235) 10.09 27 1
2895062 저녁 발명도둑잡기(118.216) 10.09 15 0
2895060 대학생들도 코딩할때 AI쓰나? [2] 프갤러(121.143) 10.09 39 0
2895056 한글날 기념 소녀시대-Run Devil Run 발명도둑잡기(118.216) 10.09 19 0
뉴스 '친한친구' 템페스트, 추석에도 열일 모드…꽃도령 변신에 컴백 스포일러까지 완벽 접수 디시트렌드 10.08
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2