디시인사이드 갤러리

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

갤러리 본문 영역

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

∫ 2t dt=t²+c갤로그로 이동합니다. 2009.11.30 12:47:31
조회 794 추천 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 47796 65
2895224 양당제 만드는 선거제도를 안고치면 미국처럼 내전난다 발명도둑잡기(118.235) 20:18 0 0
2895223 핸들 인형 삿음 야옹아저씨갤로그로 이동합니다. 20:17 1 0
2895222 아오시발 한국 오자마자 모기 보네 류류(110.70) 20:16 1 0
2895221 찢두순 압도적 효능감 미춋당⭐ ♥덩냥이♥갤로그로 이동합니다. 20:15 6 0
2895220 내 글 왜 짜름? 프갤러(222.121) 20:08 8 0
2895218 햄버거에 눅눅한 양파 = 음식물쓰레기 ♥덩냥이♥갤로그로 이동합니다. 19:45 12 0
2895216 찢두순 vs 좌청래 내전반발 찢두순 극대노? ♥덩냥이♥갤로그로 이동합니다. 19:39 9 0
2895213 극좌무능 찢두순 관세협상 대참사 때문에 벌써 국민세금 3.4조 증발 ♥덩냥이♥갤로그로 이동합니다. 19:34 18 0
2895210 북괴정은의 탈모전개 [2] ♥덩냥이♥갤로그로 이동합니다. 19:31 16 0
2895209 극좌단체 민노총 선거범죄 [2] ♥덩냥이♥갤로그로 이동합니다. 19:30 12 0
2895207 흠.. 나님 칼럼쓰고 싶은데 체력이 애매하넹 ♥덩냥이♥갤로그로 이동합니다. 19:26 8 0
2895205 냥덩이 ㅂㅅ 새끼 또 가짜뉴스 발명도둑잡기(211.246) 19:13 15 0
2895204 프갤이랑 뉴프로랑 글리젠 비슷하군요 헬마스터갤로그로 이동합니다. 18:54 18 0
2895203 ■요즘 신입 대세포폴이 뭐에요? [1] ㅇㅇ갤로그로 이동합니다. 18:30 26 0
2895202 칼집에서 검 뽑는거 루도그담당(58.239) 18:28 28 0
2895201 대재명 찬양자들 이재명 까기 바쁘군 ㅋㅋ [1] 나르시갤로그로 이동합니다. 17:57 16 0
2895200 같은말을 해도 목적에 따라 달라짐 ♥덩냥이♥갤로그로 이동합니다. 17:47 20 0
2895198 이재명 때문에 친중공산국가로 찍힌듯;; 한국여권가치 39위 수직하락 [1] ♥덩냥이♥갤로그로 이동합니다. 17:16 42 0
2895196 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ ♥덩냥이♥갤로그로 이동합니다. 16:38 25 0
2895195 스프링 jpa 고수분들 질문드립니다 프갤러(219.255) 16:35 24 0
2895194 네카라쿠배 신입 합격자 평균 스펙이 어느정도임? [1] 프갤러(118.235) 16:33 42 0
2895193 C언어가 근본인 이유 [2] ㅇㅇ갤로그로 이동합니다. 16:27 53 0
2895192 지진 나기전에 출국 했음 ㅅㄱ [2] 류류(61.218) 16:00 39 0
2895191 이재명이 대통령된 후로 공산주의 같은 정책을 못 펼치는구나 ㅎㅎ [1] 나르시갤로그로 이동합니다. 15:01 36 0
2895190 현 정부 경제 정책을 시스템 아키텍처 관점에서 보니 드는 생각 [2] 나르시갤로그로 이동합니다. 14:58 52 1
2895189 주가, 환율 착시 효과 나르시갤로그로 이동합니다. 14:47 46 0
2895188 일본 지진때문에 정상화 당하고 있네 [3] 루도그담당(58.239) 14:14 83 0
2895187 앱히키는 씨발놈임 프갤러(118.235) 13:52 29 0
2895185 자료구조를 직접 구현할 일은 별로 없긴 하지만 개념은 중요함 [4] 프갤러(223.39) 13:38 94 1
2895184 스프링 같은 씹좆좆쓰지말고 [2] 루도그담당(58.239) 13:36 63 0
2895183 웹하는데 리액트 앱 라우터 방법도 모르면서 [2] ㅆㅇㅆ찡갤로그로 이동합니다. 13:28 62 0
2895182 C 공부세팅 완 [7] ㅇㅇ갤로그로 이동합니다. 13:27 78 0
2895181 딥시크 야무진데? [3] ㅇㅇ갤로그로 이동합니다. 13:19 47 0
2895180 항상 느끼지만 호기심을 가지는 건 좋다만 그 호기심을 타인에게 강요를 [6] ㅆㅇㅆ(124.216) 13:10 74 0
2895179 예전에 대학원서 리눅스 배울때 느꼈지만 리눅스의 공짜는 공짜는 아님 ㅆㅇㅆ(124.216) 13:05 42 0
2895178 자료구조 거의 쓸 데 없긴하지. 쓸데 있다는 애들은 저수준 하는애들이고 [2] ㅆㅇㅆ(124.216) 13:02 81 0
2895177 IPEA 정보처리기사협회 전산실 면접보러오라는데 프갤러(220.65) 12:33 22 0
2895176 자료구조란걸 배웠는데 그래서 뭐 어쩌란거고 제가 뭘 배운건가요?? [5] ㅇㅇ(223.38) 12:23 87 0
2895175 짱깨들이 관광으로 한국에 도움이 된다고? [2] ♥덩냥이♥갤로그로 이동합니다. 12:22 38 0
2895174 넷플릭스도 유튜브 정도의 검색기능이 없군요 [2] 헬마스터갤로그로 이동합니다. 12:19 32 0
2895172 요즘 리눅스 데스크톱은 오히려 능지가 떨어지는거같음 [4] 파란빤스갤로그로 이동합니다. 11:55 54 0
2895168 극우추적단을 알아보쟈⭐+ ♥덩냥이♥갤로그로 이동합니다. 11:22 33 0
2895167 ❤✨☀⭐⚡☘⛩나님 시작합니당⛩☘⚡⭐☀✨❤ [2] ♥덩냥이♥갤로그로 이동합니다. 11:14 50 0
2895160 아잇씨팔 또 쓰레기 같은 타입스크립트 보려니 속이 울렁거립니다. 프갤러(218.154) 09:03 42 0
2895159 대추 ㅇㅅㅇ [1] 헤르 미온느갤로그로 이동합니다. 08:55 35 0
2895158 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08:53 29 1
2895157 아침부터 움직이니까 속이 안좋네요 프갤러(218.154) 08:52 21 0
2895156 하루 한 번 헤르미온느 찬양 [2] 헤르 미온느갤로그로 이동합니다. 08:52 56 0
2895154 ai 를 무시하는 사람과 의존하는 사람 모두 위험합니다 [4] 프갤러(223.39) 07:36 66 1
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

디시미디어

디시이슈

1/2