디시인사이드 갤러리

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

갤러리 본문 영역

적분시리즈: 6. 직선, 사각형 그리기

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.30 12:47:31
조회 796 추천 0 댓글 2


그래픽 처리를 제대로 하자면, 미리 준비되어있는 그림파일을 화면을 그리는 것 말고도, 직선을 그리는 것이나, 사각형을 그리는 것 등등이 필요하다.
이번에는 직선과 사각형 그리는 것을 구현해보자.

D3D에서는 직선을 쉽게 그릴 수 있도록 ID3DXLine이라는 인터페이스를 제공한다.
ID3DXLine은 D3DXCreateLine함수를 이용하여 간단히 만들수 있다.

LPD3DXLINE pline;
D3DXCreateLine(pd3dd, &pline);

참, 쉽죠?

ID3DXLine으로 직선을 그리는 순서는 다음과 같다.

1. ID3DXLine::Begin함수로 그리기를 준비한다.
2. ID3DXLine::Draw함수로 직선을 그리고 싶은 만큼 그린다.
3. ID3DXLine::End함수로 그리기를 마친다.

ID3DXSprite 인터페이스와 사용법이 매우 비슷하므로, 쉽게 쉽게 쓸 수 있을 것이다.
(근데 사실 Begin/End함수를 호출안하고 Draw함수를 호출해도 된다. 그럴 경우에는 Draw함수 내부에서 알아서 Begin/End함수를 호출해준다.)
ID3DXSprite와 마찬가지로, ID3DXLine도 장치를 잃었을 경우에는 OnLostDevice함수를 호출해 해제하고, 장치를 복구했을 때는 Device함수를 호출해 복구시켜줘야 한다.

자, ID3DXLine::Draw함수를 자세히 뜯어보자.
HRESULT Draw(  CONST D3DXVECTOR2* pVertexList,  DWORD dwVertexListCount,  D3DCOLOR Color );

pVertexList는 점들의 배열이다. 그냥 직선을 그릴거라면 점이 2개면 족하겠지만, 직선이 계속계속 이어진다면 얘기는달라진다.  pVertexList[0]~pVertexList[1]을 잇는 직선을 그리고,pVertexList[1]~pVertexList[2]를 잇는 직선을 그리고,pVertexList[2]~pVertexList[3], ...,pVertexList[dwVertexListCount-2]~pVertexList[deVertexListCount-1]을 잇는직선까지 주루룩 그린다.
dwVertexListCount는 예상했던것처럼, 점들의 숫자이다.
Color는 당연히 직선의 색깔!

근데, 이것만으로는 좀 밋밋하다. 직선 굵기도 바꾸고 모양도 바꾸고 하고 싶은데... 그건 어떻게 해야할까

SetWidth(float 선의 굵기)
SetPattern(DWORD 패턴)
SetPatternScale(flaot 패턴의 스케일)
등등의 함수들이 준비되어 있다. 근데 이런 직선의 특징을 바꾸는 함수는 Begin함수가 시작되기 전에 호출되어야 한다. 즉, 이미 Begin함수가 호출되었으면, 직선의 특징을 바꿀수 없다는 것이다. 이 점 유의하자.

SetPattern함수를 자세히 살펴보자. 패턴을 지정해줄수 있는데 어떻게 지정해 줄수 있을까?
패턴 지정은 비트를 이용해서 한다. DWORD는 32비트를 가진다. 우리는 이 32개의 비트를 1 또는 0으로 설정해가면서 패턴의 모양을 만들수 있다. 1은 칠해지는거고, 0은 안 칠해지는 거다.

꽉찬 직선: 11111111111111111111111111111111 (0xFFFFFFFF)
점선(. . . . . . ): 10101010101010101010101010101010 (0x55555555)
파선(- - - - - ): 11110000111100001111000011110000 (0x0F0F0F0F)
쇄선(- . - . - .): 11110010111100101111001011110010 (0x4F4F4F4F)
(비트 배열은 최하위비트에서 최상위비트순이다.)

예를 들어서 몇개만 대충 써봤는데, 2^32가지 무늬가 나올수 있으니 자유롭게 생각해보시라요.
SetPattern함수로 패턴을 지정했으면, SetPatternScale함수로 꼭 스케일을 지정해 주자. 1.0이 기본스케일이고, 커질수록 패턴전체가 길어지고, 작아질수록 패턴이 짧아진다.

이 정도 지식이면 직선그리는거는 문제 없다. GGame클래스에 LPD3DXLINE m_pline을 멤버변수로 추가하자.
GRET GGame::Create3DDevice(HWND hWnd)
{
    m_pd3d=Direct3DCreate9(D3D_SDK_VERSION);
    if(m_pd3d==NULL)return GRET_ERROR_NOD3D;
    D3DPRESENT_PARAMETERS d3dpp=_getdpp();
    if( FAILED(m_pd3d->CreateDevice(D3DADAPTER_DEFAULT, m_dev.d3ddt, hWnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pd3dd)) )return GRET_ERROR_FAIL;
    if(FAILED( D3DXCreateSprite(m_pd3dd, &m_pspr) ))return GRET_ERROR_FAIL;
    if(FAILED( D3DXCreateLine(m_pd3dd, &m_pline) ))return GRET_ERROR_FAIL;
    m_dev.hwnd=hWnd;
    return 0;
}
Create3DDevice함수에서 D3DXCreateLine함수를 호출해주고,
직선을 그리는 DrawLine함수를 추가해주자.
GRET GGame::DrawLine(int x1, int y1, int x2, int y2, D3DCOLOR color)
{
    D3DXVECTOR2 v[2];
    v[0].x=(float)x1;
    v[0].y=(float)y1;
    v[1].x=(float)x2;
    v[1].y=(float)y2;
    if(FAILED( m_pline->Draw(v, 2, color) ))
    {
        return GRET_ERROR_FAIL;
    }
    return 0;
}

참, 쉽죠?

자, 이제 사각형 그리기로 넘어간다.
불행히도 D3D에서는 사각형을 편리하게 그리는 인터페이스를 제공해주지 않는다.
컴퓨터가 3D를 그릴때 삼각형을 기본단위로 한다. 그래서 삼각형의 기본이 되는 세 점과 삼각형 정보를 토대로 모든 모델들이만들어진다. D3D에서 각각의 이런 점들을 정점(Vertex)라고 부른다. 정점이 3개 모이면 삼각형 하나를 그릴수 있다.정점은 여러가지 정보를 가질 수 있다. 가장 기초적인 위치정보(x,y,z)에서 색깔(diffuse color),법선(normal), 텍스쳐좌표(u, v) 등등등.
D3D에서는 이런 여러가지 정보들을 자유롭게 선택해서 고를수 있게 해 놓았다. 이름하여 Flexible Vertex Format, 줄여서 FVF라고 한다.
D3D에서 정점 배열을 가지고 삼각형들을 그리는 단계는 다음과 같다.
1. IDirect3DDevice9::SetFVF로 FVF를 설정한다.
2. IDirect3DDevice9::DrawPrimitiveUp으로 그린다.

사각형을 그리는 데에는 위치정보하고 색깔 정도만 있으면 된다.

m_pd3dd->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
D3DFVF_XYZRHW는 정점이 위치정보(x, y, z, w)를 가진다는 것을 나타낸다. 그리고 D3DFVF_XYZRHW로 설정된 위치정보들은 행렬변환을 거치지 않는다.
D3DFVF_DIFFUSE는 색깔(diffuse color)을 가진다는 것을 나타낸다.

이제, 이 포맷에 맞춰서 정점 배열을 만들어야 한다.
struct Vertex{
 float x, y, z, w; // D3DFVF_XYZRHW 위치정보
 D3DCOLOR color; // D3DFVF_DIFFUSE 색깔
};
Vertex v[4]={
 {x1, y1, 1.f, 1.f, color1}, //z에는 아무값이 들어가도 상관없다.
 {x2, y2, 1.f, 1.f, color2}, //w에도 아무값이 들어가도 상관없지만, 4개의 w값이 다 같아야 한다.
 {x3, y3, 1.f, 1.f, color3},
 {x4, y4, 1.f, 1.f, color4},
}; //정점 4개 배열을 만든다.
m_pd3dd->DrawPrimitiveUp(D3DPT_TRIANGLESTRIP, 2, v, sizeof(Vertex)); // 정점 배열을 가지고 삼각형들을 그린다.

HRESULT DrawPrimitiveUP(  D3DPRIMITIVETYPE PrimitiveType,  UINT PrimitiveCount,  CONST void* pVertexStreamZeroData,  UINT VertexStreamZeroStride );
PrimitiveType은 정점으로 무엇을 그릴것인지를 결정한다. 점을 그릴 수도 있고, 선을 그릴 수도 있고, 삼각형을그릴수도 있고, 여러 가지가 있지만 우리는 연결된 삼각형들을 그릴것이므로 D3DPT_TRIANGLESTRIP을 사용한다.
PrimitiveCount는 그릴 도형의 갯수이다. 우리는 삼각형 2개를 그릴것이므로 2라고 한다.
pVertexStreamZeroData는 정점 배열의 포인터이다. v를 넣어준다.
VertexStreamZeroStride는 정점 하나의 크기(바이트수)이다. sizeof(Vertex)를 넣어준다.
이렇게 하면 아마 아래와 같은 도형이 출력될 것이다.

194BCA0C4B127B58A312BB
D3DPT_TRIANGLESTRIP은 위처럼 v[0], v[1], v[2]를 이어서 하나의 삼각형을 만들고, 또 v[1], v[2], v[3]을 이어서 하나의삼각형을 만들고,... v[n-1], v[n], v[n+1]을 이어서 하나의 삼각형을 만들어, 총 n개의 삼각형을 그린다.
마찬가지로 삼각형을 그리지만, D3DPT_TRIANGLELIST는 v[0], v[1], v[2]를 이어서 하나의 삼각형을만들고, v[3], v[4], v[5]를 이어서 하나의 삼각형을 만들고, ... v[3n-3], v[3n-2], v[3n-1]를이어서 하나의 삼각형을 만들어, 총 n개의 삼각형을 그린다.

자, 이제 직접 구현해보자.

GRET GGame::DrawRectangle(int x, int y, int w, int h,
                D3DCOLOR color1, D3DCOLOR color2, D3DCOLOR color3, D3DCOLOR color4)
{
    if(!m_pd3dd)return GRET_ERROR_NODEVICE;
    m_pspr->End(); //m_pd3dd로 도형을 그리려면 m_pspr으로 그리는 것을 끝내야한다.
    m_pd3dd->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
    struct{
        float x, y, z, w; //D3DFVF_XYZRHW 위치정보
        D3DCOLOR color; //D3DFVF_DIFFUSE 색깔
    } vert[4]={
        x-0.5f, y-0.5f, 1.f, 1.f, color1,
        x+w-0.5f, y-0.5f, 1.f, 1.f, color2,
        x-0.5f, y+h-0.5f, 1.f, 1.f, color3,
        x+w-0.5f, y+h-0.5f, 1.f, 1.f, color4
    };
    HRESULT hr=m_pd3dd->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vert, 20);
    m_pspr->Begin(D3DXSPRITE_ALPHABLEND);
    return 0;
}

별로 특별하게 어려운 부분은 없다.
근데 그리기전에 m_pspr->End를 호출해주는것. 중요하다.
ID3DXSprite는 내부적으로 우리가 사각형을 그리는 과정과 비슷하게 구현되어있고, IDirect3DDevice9의 여러상태를 변화시킨다. 그렇기에 ID3DXSprite로 그리고 있는 상태에서 또 IDirect3DDevice9를 사용하여 사각형을그리려고 하면 충돌이 발생할 수 있다. (원하는 대로 사각형이 그려지지 않을 것이다.) 그러므로 IDirect3DDevice9로그리기를 할때에는 ID3DXSprite로 그리던것을 마쳐야 한다.
그리고 함수 끝 부분에서 다시 ID3DXSprite::Begin함수를 호출하여 다시 스프라이트 그리기를 준비한다.

또 하나 눈여겨봐야 할 점은 사각형 좌표에서 0.5씩을 빼주었다는 것이다. 이 0.5를 마법의 숫자라고도 부른다. D3D의좌표체계는 2D처럼 단순하지 않다. x,y,z좌표가 실수이기 때문에, 단순히 정수 하나가 1픽셀에 대응하던것과는 다르게작동된다. 2D에서 하던것처럼 (5, 5)에 점을 하나 찍으려고 하면, 점은 주변 픽셀 4개에 걸쳐서 찍혀진다. 하지만,0.5을 빼줘서 (4.5, 4.5)에 점을 하나 찍으면 원하는 픽셀에 딱 맞게 찍혀진다.
161BB8114B133E25582627
OnDraw함수에서 이번에 만든 함수들을 한 번 써먹어보자.
void MPlayGame::OnDraw()
{
    GGame::GetInstance()->SetLineWidth(4);
    GGame::GetInstance()->DrawLine(10, 10, 60, 60, D3DCOLOR_XRGB(255, 255, 0));
    GGame::GetInstance()->DrawRectangle(100, 30, 300, 200,
        D3DCOLOR_XRGB(255, 0, 0), D3DCOLOR_XRGB(0, 255, 0),
        D3DCOLOR_XRGB(0, 0, 255), D3DCOLOR_XRGB(192, 192, 192));
}

1971281F4B133A7231E241
사각형의 그라데이션이 참 아름답지요?

추천 비추천

0

고정닉 0

0

원본 첨부파일 1

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 며느리, 사위되면 시댁, 처가에 잘할 것 같은 스타 운영자 25/10/13 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47897 65
2896121 전공지식이 도움되려면 비전공 병신들이 엄두도 못내는데 가야 프갤러(110.8) 00:41 2 0
2896119 결국 오늘도 차단당했구나 ㅇㅇ(124.48) 00:23 10 0
2896118 진짜 다시 무시하고 차단해도 아이피를 계속 바꿔대니 [3] ㅆㅇㅆ(124.216) 00:12 42 0
2896117 학생때 배운거 써본적 거의 없는듯 [3] 루도그담당(58.239) 00:09 38 0
2896115 너가 따라다닌게 1년이 넘음 친구야 인생 낭비라 생각 안하냐 ㅆㅇㅆ(124.216) 00:06 26 0
2896114 갤 분위기 초상났네 [6] 루도그담당(58.239) 00:02 57 0
2896113 진짜 진심으로 안타까운데, 저새끼 계속 내 글마다 댓글달려서 알람울리는게 [2] ㅆㅇㅆ(124.216) 10.13 44 0
2896112 취직했다는 놈이 당장 뭐 말하는 개념마다 빈틈 털려서 딴새끼한테 [1] ㅆㅇㅆ(124.216) 10.13 45 0
2896110 여기서 남 욕한다고 니 인생이 바뀌는게 전혀 아님 124.48아 ㅇㅇ [1] ㅆㅇㅆ(124.216) 10.13 26 0
2896109 [1인,1개] 배달의,민족 30,000원 짜리 쓸 사람 써 ! [1] ㅇㅇ(223.39) 10.13 9 0
2896108 진심 이해가 안가는게 그거임. 내가 저새끼 나이때는 대학원가볼라고 [1] ㅆㅇㅆ(124.216) 10.13 35 0
2896106 자존감이 단단한 사람일수록 자길 내세우지 않는거임 [2] ㅇㅇ(218.149) 10.13 40 0
2896104 쟤 이해가 안 감. 보통 자기가 백수면 노력하지 않나? [3] ㅆㅇㅆ(124.216) 10.13 25 0
2896103 염병하지말고 현실에서 착실하게 살아라.. 좆병신새끼야 [1] ㅇㅇ(218.149) 10.13 17 0
2896102 저새끼는 자존감 채우는 방식 자체가 미숙함 [1] ㅇㅇ(218.149) 10.13 25 0
2896100 앱 웹 개발자는 개인정보 [3] ㅇㅇ(211.187) 10.13 28 0
2896099 '최신' 리액트 쓴다는놈이 Next.js 안써봤다 [1] ㅆㅇㅆ(124.216) 10.13 30 0
2896098 해결법을 다오. [3] 루도그담당(58.239) 10.13 27 0
2896097 웹상에서 자존감 채우려고 하니까 그따위 허영부리며 사는거야 [2] ㅇㅇ(218.149) 10.13 22 0
2896095 딱봐도 실력없어서 과제대행으로 용돈벌이나 하는 사회 최하층민새끼가 [5] ㅇㅇ(218.149) 10.13 25 0
2896093 개인사업자면 홈텍스를 인증해라.. [2] ㅇㅇ(218.149) 10.13 35 0
2896089 진짜 신기하지 않냐? 124.48 점마는 지가 말할수록 백수라는게 드러남 [1] ㅆㅇㅆ(124.216) 10.13 28 0
2896087 124.48 쟤는 거짓말이 너무 티가남. 그게 문제임 [3] ㅆㅇㅆ(124.216) 10.13 38 0
2896086 암만봐도 타임라인 진짜 씹쓰레기 같네 [4] 루도그담당(58.239) 10.13 46 0
2896082 전공에서 배운거 실무에서 얼마나 써먹는중? [6] ㅇㅇ갤로그로 이동합니다. 10.13 54 0
2896081 네트워크는 ㅈㅈ쳤다 ㅈㄴ노잼에어렵네 프갤러(14.43) 10.13 17 0
2896080 너네 아직도 그러고 사냐? 프갤러(59.16) 10.13 20 0
2896078 혹시 치킨한마리 나눔해주실분 계십니까. ㅇㅇ(223.39) 10.13 10 0
2896077 마이크로소프트10년동안 발전보다버그투성이가됬누 타이밍뒷통수한방(1.213) 10.13 8 0
2896075 나 오랜마네 바카라 사이트 들어가서 3번 찍었는데 다맞음 ㅇㅅㅇ ㅇㅇ(223.39) 10.13 8 0
2896074 님들아 백준 알고리즘 풀때 유튜브 영상틀어놓거나 노래들으면서 풀음? 프갤러(123.212) 10.13 12 0
2896073 북괴 김정은 한국에 홍수 일으켜 인명살상 노렸나 충격 ♥덩냥이♥갤로그로 이동합니다. 10.13 11 0
2896071 한우물 진득하고 꾸준하게 팔 수 있는거도 재능인거 같다 [6] chironpractor갤로그로 이동합니다. 10.13 41 0
2896070 야애니 ♥덩냥이♥갤로그로 이동합니다. 10.13 20 0
2896069 [단독] 서울시, 첫 민간인 ‘핵 벙커’ 만든다 발명도둑잡기(118.216) 10.13 15 0
2896068 신문고로 불법주차 신고하는 놈들 중 정상인은 없다는게 팩트임 [11] 야옹아저씨갤로그로 이동합니다. 10.13 39 5
2896067 엔지) 프갤러(211.243) 10.13 16 0
2896065 ‘근무시간 노래방’ 판사, “2차는 애기 보러가자”는 변호사에 “좋죠 형 발명도둑잡기(118.216) 10.13 13 0
2896063 특전사 前단장 "케이블타이 체포용 아냐…끌어내라 지시 못들어" 발명도둑잡기(118.216) 10.13 14 0
2896062 어제 쓰던글 이어서 쓰려다가 피궁해서 못쓰겟당 ♥덩냥이♥갤로그로 이동합니다. 10.13 20 0
2896061 윤석열·김건희 프랑스 방문 때 반려견 동반 위해 '개 의전' 준비 발명도둑잡기(118.216) 10.13 14 0
2896060 잼땅 ♥덩냥이♥갤로그로 이동합니다. 10.13 18 0
2896059 술 끊었더니 되려 피로하네 진짜... 존나 졸리네 ㅇㅇ(223.39) 10.13 14 0
2896057 할 말이 있소 발명도둑잡기(118.216) 10.13 16 0
2896056 독서모임 커플 발명도둑잡기(118.216) 10.13 13 0
2896055 카톡에 야한 사진 올려놓고 친구보고 카톡 음란물 유포로 신고하면 [6] 프갤러(110.8) 10.13 30 0
2896054 환율 1800원 근접 ㄷㅅㄷ 찢두순 ♥덩냥이♥갤로그로 이동합니다. 10.13 39 0
2896053 무능극좌 외교실패 찢두순 국민세금으로 감추기 끝나가는듯? ♥덩냥이♥갤로그로 이동합니다. 10.13 11 0
2896052 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥덩냥이♥갤로그로 이동합니다. 10.13 17 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

디시미디어

디시이슈

1/2