디시인사이드 갤러리

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

갤러리 본문 영역

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

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.30 12:47:31
조회 795 추천 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/06 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47843 65
2895569 이직준비 어케하냐고 100만번 물었다 [1] 밀우갤로그로 이동합니다. 01:38 13 0
2895565 슬슬 납품준비 끝났으니 자고 나머지 ㅆㅇㅆ(124.216) 00:52 18 0
2895563 캐시카우만 좀 안정되면 게임 계속 [2] ㅆㅇㅆ(124.216) 00:48 32 0
2895562 use client를 쓸때 단순하게 원칙만 정해두면 난 어렵지 않았음 [2] ㅆㅇㅆ(124.216) 00:36 30 0
2895561 개인적으로 나는 클라 출신이라 앱라우팅이 훨 편했음 [2] ㅆㅇㅆ(124.216) 00:32 33 0
2895560 리액트를 해야하나 말아야하나 존나 고민이다 [16] 프갤러(59.26) 00:23 117 0
2895558 이번 의뢰가 인문학계열에서 AI 도입하는데 이 과정에서 [2] ㅆㅇㅆ(124.216) 10.11 44 0
2895557 이번에 잘하면 진짜 연구 용역 될지도 모르겠다 [6] ㅆㅇㅆ(124.216) 10.11 76 1
2895556 강남 인기장소사이트 인기사이트(118.235) 10.11 17 0
2895555 중국하는 중국 chironpractor갤로그로 이동합니다. 10.11 24 0
2895552 업워크 일 3번 받았는데, 업워크쪽은 네이티브 잉글리쉬불가능이면 안받음 ㅆㅇㅆ(124.216) 10.11 28 0
2895550 아까 프리랜서 물어본 프붕인데 [7] 프갤러(218.153) 10.11 77 0
2895549 신상에 관련된거는 몇개 삭제했는데 지가 신고글삭한거는 씨발ㅋㅋㅋ ㅆㅇㅆ(124.216) 10.11 39 0
2895548 계미년에 태어나 살아오며 후회가 참 많다... ㅇㅇ(223.38) 10.11 14 0
2895547 저장용 ♥덩냥이♥갤로그로 이동합니다. 10.11 29 0
2895546 뉴프로가 프갤 먹었다고 함 헬마스터갤로그로 이동합니다. 10.11 30 0
2895545 여긴 도대체 왜 프로그래밍 관련 글이 없음? [2] 프갤러(159.196) 10.11 48 0
2895544 11월초..중순까지 밀릴듯? ♥덩냥이♥갤로그로 이동합니다. 10.11 18 0
2895541 ❤+ 없는 SEX는 공허하단걸 알아야행 [1] ♥덩냥이♥갤로그로 이동합니다. 10.11 28 0
2895540 컴퓨터 잘알 형들 질문점요 [2] ㅇㅇ(106.102) 10.11 29 0
2895539 민폐극좌 영포티는 인간으로 봐주는게 이상한것임 ♥덩냥이♥갤로그로 이동합니다. 10.11 19 0
2895538 [르몽드 살롱] 토마 피게티의 자유 무역 반대론 발명도둑잡기(118.235) 10.11 13 0
2895537 재매이햄 지지자 특징 [1] hrin(118.235) 10.11 34 0
2895536 스웨디시 아다땐 후기 ㅇㅇ(39.7) 10.11 44 0
2895535 이제 슬슬 공기 건조해지는듯? ♥덩냥이♥갤로그로 이동합니다. 10.11 18 0
2895533 음기 충전 발명도둑잡기(118.235) 10.11 22 0
2895531 안 잡아가요? 발명도둑잡기(118.235) 10.11 22 0
2895530 나님 왤케 뽀짝한걸깡? ♥덩냥이♥갤로그로 이동합니다. 10.11 24 0
2895529 트럼프 대통령에 영광 헌정 발명도둑잡기(118.235) 10.11 16 0
2895527 일베 서버 근황 발명도둑잡기(118.235) 10.11 49 0
2895526 ❤✨☀⭐⚡☘⛩수고했어양⛩☘⚡⭐☀✨❤ ♥덩냥이♥갤로그로 이동합니다. 10.11 30 0
2895524 쿠팡이츠 편의점 재고 실시간 업데이트 안됨? ㅇㅅㅇ 프갤러(112.157) 10.11 27 0
2895523 야 너두 버거킹 먹을 수 있어 프갤러(211.234) 10.11 30 0
2895521 이재명 말 안듣는 검사는 싹다 물갈이 해야 맞지 [9] 야옹아저씨갤로그로 이동합니다. 10.11 48 1
2895520 이거다 이거 [2] 발명도둑잡기(118.235) 10.11 48 0
2895517 자신의 존재 의의를 질의응답에서 찾아서 [2] 프갤러(211.235) 10.11 65 0
2895516 경력쫌 되면 위시캣이 제일 안전하고 돈 많이 받는다고 들음 [2] ㅆㅇㅆ(124.216) 10.11 62 0
2895511 프리랜서로 일해보고 싶은데 [4] 프갤러(218.153) 10.11 69 0
2895510 내가 석사수료로 대학원 중퇴한 이유 프갤러(211.235) 10.11 70 0
2895507 저녁은 버거킹이다. [3] 프갤러(223.63) 10.11 47 0
2895504 ㅆㅇㅆ야 난 네가 걱정돼서 하는 소리인데 ㅇㅇ(124.48) 10.11 74 4
2895502 완전 외부인이 본 모습 [3] 프갤러(175.116) 10.11 59 0
2895500 이정도면 통매음 아님 ㅇㅇ? [1] ㅇㅇ(124.48) 10.11 62 0
2895498 ㅆㅇㅆ야 신고글삭 아니잖아 [1] ㅇㅇ(211.235) 10.11 58 1
2895494 악몽이 된 '고수익 해외취업'…캄보디아 감금 한국인 2명 구조 발명도둑잡기(118.235) 10.11 21 0
2895491 닷트윈이거 물건이네 물건 [2] 루도그담당(58.239) 10.11 42 0
2895486 그런데 러스트는 배우고 남 평가질이냐? 프갤러(27.171) 10.11 24 0
2895482 지능 낮은 사람 특징 ㅇㅇ(211.235) 10.11 36 0
2895481 ㅆㅇㅆ 공격자들 중 일부는 극우 심리공작원이다 [1] 발명도둑잡기(118.235) 10.11 42 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

디시미디어

디시이슈

1/2