반응형

http://www.silverwolf.co.kr/4876




파일을 기본으로 해 텍스처를 생성 한다.

구문

HRESULT D3DXCreateTextureFromFile(      

    LPDIRECT3DDEVICE9 pDevice,    LPCTSTR pSrcFile,    LPDIRECT3DTEXTURE9 *ppTexture );

파라미터

pDevice
[in] IDirect3DDevice9 인터페이스의 포인터. 텍스처에 관련지을 수 있는 장치를 나타낸다.
pSrcFile
[in] 파일명을 지정하는 캐릭터 라인의 포인터. 컴파일러의 설정이 Unicode 를 요구하고 있는 경우, 데이터 타입 LPCTSTR 는 LPCWSTR 가 된다. 그 이외의 경우는, 이 캐릭터 라인의 데이터 타입은 LPCSTR 가 된다. 「주의」를 참조할것.
ppTexture
[out] 생성 된 큐브 텍스처 개체를 나타내는,IDirect3DTexture9 인터페이스의 포인터 주소.

반환값

성공했을 경우는,D3D_OK 를 돌려준다.

실패했을 경우는, 다음의 몇개의 값을 돌려준다.

D3DERR_NOTAVAILABLE이 장치는, 조회된 테크닉을 지원 하고 있지 않다.
D3DERR_OUTOFVIDEOMEMORYMicrosoft? Direct3D? 가 처리를 실시하는데 충분한 디스플레이 메모리가 없다.
D3DERR_INVALIDCALL메서드의 호출이 무효이다. 예를 들어, 메서드의 파라미터에 무효인 값이 설정되어 있는 경우 등이다.
D3DXERR_INVALIDDATA데이터가 무효이다.
E_OUTOFMEMORYDirect3D 가 호출을 완료하기 위한 충분한 메모리를 할당할 수가 없었다.

주의

컴파일러의 설정에 의해 함수의 버전도 정해진다. Unicode 가 정의되고 있는 경우, 이 함수의 호출은 D3DXCreateTextureFromFileW 가 된다. 그 이외의 경우는 ANSI 캐릭터 라인을 사용하므로, 이 함수의 호출은 D3DXCreateTextureFromFileA 가 된다.

이 함수가 지원 하고 있는 파일 포맷은,. bmp,. dds,. dib,. jpg,. png, 및 . tga 이다.

이 함수는 D3DXCreateTextureFromFileExW(pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppTexture)와 동일하다.

밉맵 된 텍스처의 각 레벨에는, 로드 된 텍스처가 자동적으로 저장 된다.

밉맵 된 텍스처에 이미지를 로드할 때, 장치에 따라서는, 1x1 의 이미지로 변환하지 못하고, 함수가 실패하는 일이 있다. 이러한 경우는, 이미지를 수동으로 로드할 필요가 있다.

이 함수를 사용해 생성 한 리소스는, D3DPOOL_MANAGED 로 나타나는 메모리 클래스에 배치된다.

D3DXCreateTextureFromFile 를 사용해 최적인 퍼포먼스를 얻으려면 , 다음 일을 실시한다.

  1. 이미지의 스케일링 및 포맷 변환을 로드시에 실시하면, 처리에 시간이 걸리는 경우가 있다. 이미지는, 사용할 때의 포맷 및 해상도로 보존한다. 타겟 하드웨어로 처리할 수 있는 것이 2 의 거듭제곱의 넓이만의 경우는, 2 의 거듭제곱의 넓이를 사용해 이미지를 생성 해 보존한다.
  2. Microsoft DirectDraw? 표면 (DDS) 파일의 사용을 검토한다. Microsoft DirectX? 9.0 텍스트 포맷은 모두 DDS 파일을 사용해 표현할 수 있기 (위해)때문에, DDS 파일은 Direct3D extension (D3DX)에 있어 읽기나 들이마셔. 또, DDS 파일에 밉맵을 보존할 수가 있어 임의의 밉맵 생성 알고리즘을 사용해 이미지를 생성 할 수 있다.
  3. 함수의 정보

    헤더d3dx9tex.h
    임포트 라이브러리
    d3dx9.lib
    최저한의 operating systemWindows 98

    참조

    D3DXCreateTextureFromFileEx ,텍스처의 색변환


반응형

'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글

모션 블러(Motion Blur)  (0) 2013.01.25
인스턴싱 (Instancing)  (1) 2013.01.25
다중스트림 셰이더  (0) 2013.01.21
D3DVERTEXELEMENT9 사용법  (0) 2013.01.21
Fast Object Picking  (0) 2013.01.19
반응형


http://blog.daum.net/naganolacpp/37


다중스트림셰이더.zip



g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_COLORVALUE(0.0f,0.0f,1.0f,1.0f), 1.0f, 0 );

g_pd3dDevice->BeginScene();

 

g_pEffect->SetTechnique( "Technique0" );

setTechniqueVariables();

 

UINT uPasses;
g_pEffect->Begin( &uPasses, 0 );
   
for( UINT uPass = 0; uPass < uPasses; ++uPass )
{
       g_pEffect->BeginPass( uPass );

      

       // 단일 스트림 사용

       //g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof(Vertex) );
       g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

     

       // 다중 스트림 사용
       g_pd3dDevice->SetVertexDeclaration( g_vertex_declaration );

      /* SetFVF와 SetvertexDeclaration은 같이 쓸경우 주의해야한다.

          잘못하면 괴물이 출력된다*/
       g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer0, 0, sizeof(Vertex0) );
       g_pd3dDevice->SetStreamSource( 1, g_pVertexBuffer1, 0, sizeof(Vertex1) );

       // 인덱스 버퍼 Set  
       g_ib->SetIndices();

 

       // 출력
       g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 4, 0, 2 );

       

       g_pEffect->EndPass();

}
 
g_pEffect->End();

 

g_pd3dDevice->EndScene();

g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

 

/*

이건 사용된 버택스  버퍼 데이터

*/

struct Vertex0
{
 float x, y;
 float tu, tv;
};

struct Vertex1
{
 float z; 
};
Vertex0 g_quadVertices0[] =
{
 {-1.0f,-1.0f,  0.0f,1.0f },
 { 1.0f,-1.0f,  1.0f,1.0f },
 {-1.0f, 1.0f,  0.0f,0.0f },
 { 1.0f, 1.0f,  1.0f,0.0f }   
};

Vertex1 g_quadVertices1[] =
{
 { 0.0f },
 { 0.0f },
 { 0.0f },
 { 0.0f }   
};
D3DVERTEXELEMENT9 g_vertex_description[]=

 { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
 { 0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
 
 { 1, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1 },
 D3DDECL_END()
};

*/


반응형

'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글

인스턴싱 (Instancing)  (1) 2013.01.25
D3DXCreateTextureFromFile 함수  (0) 2013.01.22
D3DVERTEXELEMENT9 사용법  (0) 2013.01.21
Fast Object Picking  (0) 2013.01.19
게임 이펙트에서의 D3DRS_ZWRITEENABLE의 사용  (1) 2013.01.19
반응형

아래 내용에 덧붙이자면


동일한 정점구조를 동시에 멀티로 세팅하고 싶을때 사용하거나


그냥 일반적으로 사용하기도 한다


멀티로 사용할때는 


LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer0 = NULL;

LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer1 = NULL;


처럼 멀티로 돌릴 개수만큼 정점버퍼를 생성해줘야한다






http://blog.naver.com/red_n_hot/60004005539


LPDIRECT3DVERTEXDECLARATION9       m_pVertexDeclaration;

 

//ㄴ  버텍스 정의하는 변수!?  를 만들어 주고

 

D3DVERTEXELEMENT9 dwDecl3[] = 
{
    {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_POSITION, 0},
  D3DDECL_END()
};

 

//ㄴ 정점선언 이랄까나.. 

 

첫번째인자 스트림 몇번째인지 

두번째 옵셋~!? 시작(0)으로부터  @@??  아니아니... 어디서부터 사용할껀지.. ex)12바이트 까지 사용됬삼

세번째 타입  얼마나 사용할껀지 ex) D3DDECLTYPE_FLOAT3

네번째 메써드  디퍼트!? 디포트!?  몰라 이건

다섯번째 어떻게 사용할찌..  ex)  D3DDECLUSAGE_POSITION   포지션에대한

여섯번째 ex)텍스트 인덱스에 사용

 

typedef struct D3DVERTEXELEMENT9 {
    WORD Stream;
    WORD Offset;
    BYTE Type;
    BYTE Method;
    BYTE Usage;
    BYTE UsageIndex;
} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9;

//-----------------------------

//---------------------------------

struct CUSTOMVERTEX
{
 FLOAT x, y, z; // 공간상의 위치값
};

 

//ㄴ 사용하던데로 만들어 놓는다.

 

 pd3dDevice->CreateVertexDeclaration(dwDecl3, &m_pVertexDeclaration);

 pd3dDevice->SetVertexDeclaration(m_pVertexDeclaration);

 

//ㄴ 다이렉트엑스 sdk 레퍼런스에 요롷게 사용하랜다.

 pd3dDevice->CreateVertexBuffer( 
       8*sizeof(CUSTOMVERTEX),  // 버퍼 
       D3DUSAGE_WRITEONLY,   // 만들어진 버퍼의 성격 (읽기전용)   
       NULL,   // 버퍼 포맷(구조)
       D3DPOOL_DEFAULT,   // 메모리를 어느 영역에 할당할 것인가?
       &m_pTriVB, NULL );

 

//ㄴ 여기서 겁나 해멧삼..   기존 FVF 포멧을 요구하는데..  NULL  제로 값을 넣어주면 포멧 무시하겠단다.

 

 

CUSTOMVERTEX v[] =

 {

                { -1,  1,  1 },            /// v0

                {  1,  1,  1 },            /// v1

                {  1,  1, -1 },            /// v2

                { -1,  1, -1 },            /// v3

 


                { -1, -1,  1 },            /// v4

                {  1, -1,  1 },            /// v5

                {  1, -1, -1 },            /// v6

                { -1, -1, -1 },            /// v7

  };

//ㄴ 요래요래 값을 넣어주고

 

VOID* pVertices;

 m_pTriVB->Lock( 0, sizeof(v), (void**)&pVertices, 0 );
 memcpy( pVertices, v, sizeof(v) );

 m_pTriVB->Unlock();

 

//ㄴ 하던데로 하면됨

 

 

 

//-------------------------------그리는곳-----------------------------------

 

  pd3dDevice->SetStreamSource(0, m_pTriVB, 0, sizeof(CUSTOMVERTEX));

 

  pd3dDevice->SetIndices( m_pTriLB );

 

//ㄴ FVF 로 했던데로 하면된다.

//pd3dDevice->SetFVF( CUSTOMVERTEX::FVF ); 이런거 안해줘도됨






위 포스트ㅏ에 덧붙이자만..


_pD3dDevice->SetVertexDeclaration( _pDecl ); 은 써야함

반응형
반응형


http://gamedevforever.tistory.com/261


Posted by 김포프

예제코드 다운받기


  • C#과 XNA를 이용해서 만들었습니다.

  • XNA를 설치하셔야 합니다.


게임보다는 에디터 따위의 툴에서 더 유용한 기법입니다. 예전에 개인 프로젝트에서 장난삼아 만들어 봤던 놈인데 그뒤로도 몇번이나 동일한 기법을 여러 툴에서 구현하다보니 올리면 유용하겠다 싶어서..... 이미 알고계시는 분들도 많겠지만 혹시나 모르시는 분들을 위해 여기 올리면 좋겠다고 생각해서 올립니다.


이 기법이 해결하려고 하는 건 간단합니다. 맵 에디터 같은 프로그램에서 화면에 있는 물체를 마우스로 클릭해서 선택하는걸 졸라~ 빠르게 구현하는 겁니다.


말로는 쉽죠?... 그런데 보통 구현들 어떻게 하셨나요?


흔히 쓰던 광선 vs AABB 충돌검출 방법

제가 흔히 봤던 방법중 하나는 마우스 클릭한 위치부터 화면 안쪽으로 광선(ray)를 쏴주면서 그 광선과 각 물체의 AABB의 충돌검사를 한뒤 가장 가까이에 있는 물체를 선택하는 거였습니다.


예를 들어 아래 이미지에서 오른쪽 가장자리가 화면이라고 가정하면 이런식으로 ray를 쏴서 aabb를 찾는거죠.



그런데 이 방법에 문제들이 좀 있습니다

  • 월드에 물체들이 많으면 충돌검사 시간 꽤 걸립니다

  • AABB와 충돌검사를 하므로 픽셀단위로 정확한 충돌검사가 불가능합니다.






제가 쓰는 렌더타겟과 물체 ID를 이용한 방법

저는 GPU를 이용해서 위 문제점들을 해결했습니다. 알고리듬은 매우 간단합니다. 자세한 코드는 위에 첨부해 놓은 예제코드를 봐주세요.

  1. 각 물체마다 고유 해쉬 아이디(32비트 정수)를 부여한다.

  2. 화면크기와 동일한 A8R8G8B8 렌더타겟을 하나 만든다. (이후 ID맵이라 부름)

  3. ID Map맵 렌더타겟을 설정한다.

  4. 모든 물체를 그려주면서 물체 해쉬(32비트)값을 8비트씩 짤라 R,G,B,A채널에 써준다

  5. 마우스가 클릭된 위치의 픽셀을 읽어온다

  6. 그 해쉬값과 동일한 물체를 선택한다.

  7. 선택된 물체로 하고 싶은 짓을 한다 -_-

  8. 끝 -_-


해쉬아이디

해쉬 아이디는 아무렇게나 생성이 가능합니다. 각 물체마다 고유하기만 하면 되죠. 제 예제에서는 그냥 물체 이름인 string으로부터 해쉬 아이디를 생성했습니다.


해쉬아이디를 색상으로 바꾸는 법

해쉬 아이디를 RGBA로 바꾸는 코드는 다음과 같습니다.


private static Color HashIDToColour(int hash)

{

    int a = (hash >> 24) & 0xff;

    int b = (hash >> 16) & 0xff;

    int g = (hash >> 8) & 0xff;

    int r = hash & 0xff;


    return new Color(r, g, b, a);

}


이 후 이걸 셰이더 함수로 대입해준 뒤


ColourFX.Parameters["Colour"].SetValue(HashIDToColour(go.Hash).ToVector4());


셰이더 안에서 다음과 같이 그려만 주면 됩니다.

float4 ps(VtxOut In) : COLOR

{

 return Colour;

}


해쉬아이디 읽어오기

매우 간단합니다. 그냥 그 픽셀값을 32비트로 읽어오면 끝입니다. (이미 해쉬 ID에서 색상으로 변환할때 byte순서및 엔디안 문제를 고려했거든요


public int PickObject(int x, int y)

{

    int hash = Hash.INVALID;


    int [] pickedPixel = new int[1];


    IDMap.GetData<int>(0, new Rectangle(x, y, 1, 1), pickedPixel, 0, 1);


    hash = pickedPixel[0];


    return hash;

}


예제 결과

일단 제 샘플 코드를 실행해보면 다음과 같은 그림이 보일겁니다.


메인 화면에 3개의 공이 있고.. 오른쪽 아래는 ID맵입니다.


여기서 파란색 공위에 마우스를 클릭하면 다음과 같이 됩니다.


현재 선택된 물체를 노란색으로 표현했습니다. 그리고 현재 선택된 물체를 ID 맵에 안그려서 다시 한번 더 클릭을 하면 그뒤에 있는 물체가 대신 선택되게 만들었습니다.



이정도면 대충 보여드린듯 하죠? 자세한건 직접 받아서 실행해보세요.. -_-;


기타 응용

최근에 이 기법을 응용해서 물체 ID 대신에 물체의 깊이를 저장도 해봤답니다. 마우스 클릭 위치 근처에 있는 복셀(voxel)들을 전부다 고칠일이 있어서... 그냥 마우스 클릭 깊이만 찾아다 그로부터 월드위치 구한 뒤, octree를 뒤져서 근처에 있는 복셀들을 찾아냈죠.


기타 등등의 응용법이 있을 겁니다.




오랜만에 글써본 포프였습니다.



저작자 표시 비영리 변경 금지
  1. Favicon of http://kindtis.tistory.com 친절한티스 2012/12/03 13:27      

    오왕~ 이렇게 하면 픽셀 단위로 픽킹이 가능하겠네요.

    근데 동일한 화면 크기를 사용하면 고해상도시 메모리 사용량도 높을거 같은데...

    픽킹용 렌더 타겟은 저해상도로 해서 찾아내도 되지 않으까요?

    정확한 픽셀 단위까지 체크할거 아니면 상관 없을거 같은데...

    • 김포프 2012/12/04 12:58    

      적당히 저해상도로 해도 되죠.. 실제로 고해상도로 해도 MSAA쓰면 경계 부분은 아마 정확한 해쉬값이 안나올거에요....

  2. 조금신 2012/12/03 17:37      

    DX9 이하에서는 픽셀값을 읽어올 때, GetRenderTargetData를 사용해야 하는 것으로 알고 있는데, 이 함수 자체가 하드웨어특성을 많이 타는 문제있는 함수라, 경우에 따라서는 picking ray를 이용한 검출 보다 느린 것으로 알고 있습니다. 혹시 다른 방법으로 픽셀을 읽는 방법이 있는지요?

    • 김포프 2012/12/04 12:58    

      어차피 개발자용 컴퓨터에서 사용할 함수니까(맵 에디터를 공개 안한단 조건하에..) 별 상관없지 않나요?

      한마디로 다른 방법은 모릅니다. ^_^ surface를 통채로 systemmem에 있는 렌더타겟에 복사한 뒤 거기서 찾아보면 어떨까요.. -_-;

    • Hybrid 2012/12/11 17:26    

      기억이 확실하지 않은데 제가 기억하는게 맞다면, 아마 이 방법이 고전적인 OpenGL 에서 기본 제공하는 피킹의 내부 메카니즘일겁니다.
      http://content.gpwiki.org/index.php/OpenGL:Tutorials:Picking
      이쪽에서는 자체 API를 이용하는거니 물론 화면 데이터를 다 가져올 필요가 없지요.

      일단 화면 메모리 락걸고 메모리 카피하느라 생기는 성능저하를 생각하면, 아무래도 직접 OpenGL API를 (다룰 수 있다면) 다루는게 훨씬 빠를르겠네요. (OpenGL 코드는 매우 간단하죠.)
      DX 도 비슷한게 있을꺼 같은데..... DX는 잘 모르겠고.... @.@

    • 김포프 2012/12/30 05:34    

      DX자체에서 지원하는 방법은 없는것 같구요... 뭐 전 여러번 써본 방법인데 툴에서 쓰기에 속도저하는 크게 걱정할 부분이 아니었습니다.. 정 속도저하가 되면 그냥 더블 버퍼링 걸면 되겠죠.. -_-; (1프레임 딜레이 쯤이야!....)

  3. 대마왕J 2012/12/11 22:40      

    쉬운데.....? -_-a (오호?) 첨에 공 그림들이 뭔소리인지 이해가 안가서 글만 정독하니까 그때야 그림이 이해가 가네요. 그림에 민감한것도 참 이럴땐 단점 ... 
    저도 나중에 툴 만들고 막 이렇게 되면 써야겠어요. 툴에서야 뭐 퍼포먼스따위... 하드웨어빨로 밀어붙이면 되니까.. 

    • 김포프 2012/12/30 05:34    

      제가 아트에 약합니다.. 흑흑 ..ㅜ_ㅜ

반응형
반응형

http://cafe.naver.com/jzsdn/3286




게임 이펙트를 구현하시려고 하는분을 위해 간략히 써봅니다.

제가 하는 이야기가 무슨말인지 경험자분들은 대개 알고 계실거라 생각됩니다.

 

아시는 분은 아시겠지만... 일반적으로 게임 오브젝트를 렌더링 할경우

비알파 오브젝트를 먼저 렌더링하고 알파적용 오브젝트를 렌더링하게 됩니다.

 

 

그래야 알파적용 오브젝트가 비알파 오브젝트를 뒷배경으로 알파블렌딩 효과를

나타내기 때문이죠...

 

 

대개의 이펙트 효과는 반투명(알파 블렌딩) 의 효과를 가진게 많이 존재합니다.

 

일반적으로 여러개의 알파적용 오브젝트를 렌더링 할 경우에는 카메라와 거리를 재서

먼것부터 그려나가기 시작하죠

 

그래야 블렌딩 효과가 적용되기 때문입니다. 가까운것을 먼저그리게 되면

멀리 있는 오브젝트를 가까이 있는 오브젝트가 블렌딩하지 못하게됩니다.

게다가 뒷쪽에 오브젝트는 Z버퍼에 위해 걸러지게 되어 전체적으로

이상한 형상을 뛰게됩니다. 

 

 

여기까지는 아마 대개 렌더링 정책에 관한 이야기로 이미 알고 계신분들도 많으실겁니다 ^^;

 

 

이펙트를 구현하다보면 현실적으로 수많은 이펙트 메쉬들을 전부다 카메라와 거리를 통해

그려나간다는것은 불가능하다고 봐야겠죠... ^^

 

게다가 원통형의 마법형태를 구현하려고 하면 반정도가 이상한 모습을 뛴 모양이 나오게

될겁니다.

 

이런것들을 한방에 해결하게 해주는 요소가 바로 렌더링설정에서 D3DRS_ZWRITEENABLE

FALSE로 설정하는 것입니다.

 

비알파 오브젝트를 먼저 렌더링하게 되면  Z버퍼에 상에 비알파 오브젝트에 대한 사항이

먼저 적용됩니다. (여기서도 비알파 오브젝트는 먼저 그려져야 합니다. ^^)

여기서는 D3DRS_ZWRITEENABLE가 물론 TRUE겠죠.

 

D3DRS_ZWRITEENABLE을 FASLE로 설정하고 이펙트를 렌더링하게 되면

Z버퍼를 갱신하지않고 렌더링이 적용되게 되죠. 그래서 가까이있는게

먼저 그려진다고 하더라도 이 가까운 메쉬에 위해 Z버퍼가 갱신되지 않게됩니다.

 

 

순차적으로 접근해보면....(다시 수정)

1. 가까운 메쉬가 그려진다. (Z버퍼가 갱신되지 않고 가장 먼상태로 그대로 유지된다.)

2. 먼 메쉬가 그려진다. ( Z버퍼가 갱신되지 않고 먼상태이기에 먼 메쉬도 그려진다.)

 

 

이상황에서 블렌딩을 적용하게 되면 자연스럽게 두색상이 적당히 혼합되 뒤쪽에 있는 메쉬를

가까이 있는 메쉬가 비추는듯한 효과가 생기게 되는거지요.

 

만약 이펙트가 비알파 오브젝트 뒤쪽에 존재한다면.. 이미 비알파오브젝트를 렌더링하고

Z버퍼는 비알파 오브젝트에 위해 갱신된값을 가지기 때문에

그려지지 않게됩니다. (이게 바로 Z버퍼를 끄지않고 D3DRS_ZWRITEENABLE를 사용하는 이유입니다.)

 

해당 아티클을 적용할시에 대개 블렌딩 모드를

 

lDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);   
lDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

 

lDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);   
lDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

 

lDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);   
lDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);

 

lDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);   
lDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);

 

이 넷중에 하나로 설정할때 사용합니다. 

반응형
반응형
http://www.gpgstudy.com/m/forum/topic/22596

정점 셰이더 초기화에 대한 궁금증입니다

예를 들어 구조체가 
D3DXVECTOR3 p; 
D3DXVECTOR3 n; 
DWORD Diffuse; 
float u, v; 

라고 했을때 

이런식으로 했는데 잘 안되네요.. 
D3DVERTEXELEMENT9 declaration[] = 

{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, 
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, 
{ 0, 24, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, 
{ 0, 28, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, 
D3DDECL_END() 
}; 

후미 4시간째 해메고 있습니다

color쪽이 틀린것 같네요.

코드:
{ 0, 24, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, 


대신에 

코드:
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, 


쓰셔야 할것 같아요.

Re:

감사합니다 ㅠㅠ

반응형
반응형

BLOG main image



GetSurfaceLevel()

GetRenderTarget(),
GetDepthStencilSurface()


을 사용할때 레퍼런스 카운트 1씩이 증가해 Release() 로 참조카운트 수를 감소시켜 해제하도록 해야함







http://cretom.egloos.com/583755

셰이더 책에 보면

보관했던 렌더링 표면을 복구시키는 부분에 이런 코드가 있다



//-----------------------------------------------------
// 기존 렌더링타겟 복구
//-----------------------------------------------------

m_pd3dDevice->SetRenderTarget(0, pOldBackBuffer);
m_pd3dDevice->SetDepthStencilSurface(pOldZBuffer);
m_pd3dDevice->SetViewport(&oldViewport);

pOldBackBuffer->Release();
pOldZBuffer->Release();


// 버퍼 클리어
m_pd3dDevice->Clear( 0L, NULL , D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER
      , 0x00404080, 1.0f, 0L );

// pOldBackBuffer에 렌더링하는 코드
.......
....
..




빨간색 부분이 주목해야 할 부분!

그 코드 뒤 복구한 렌더링타겟 'pOldBackBuffer' 에 Clear하고 렌더링하는 코드가 있는데

그러기 전 'pOldBackBuffer'를 Release 시켜버리고 있다.

왜 이러나.. 이해가 되질 않았는데

pDevice->GetRenderTarget(),
pDevice->GetDepthStencilSurface() 메소드의 설명을 찾아보니 의문이 풀렸다.




이 메서드를 호출하면,IDirect3DSurface9 인터페이스에 대한
내부 참조 카운트가 증가한다.
 IDirect3DSurface9 인터페이스를 사용해 끝냈을 때에
IUnknown::Release 를 호출하지 않으면 메모리 누수가 발생한다.


그러니까 스마트 포인터처럼 Get 메소드를 사용하면 내부 참조카운트가 증가하고,

내부 참조 카운트가 0일때 Release하면 최종적으로 메모리에서 내려가는 구조라서

메모리에서 해제시키려고 Release를 호출한 게 아니라,

GetRenderTarget() 호출로 +1 됐던 참조 카운트를

-1 시키려고 Release()를 호출했던거였다.








반응형
반응형



http://blog.naver.com/sorkelf/40156769867

멀티 패스 렌더링 이란 여러개의 경로를 가지는 렌더링 방법을 말한다. 보통 백 버퍼만으로 렌더링하는것을 싱글 패스 렌더링이라고 하며

멀티 패스 렌더링은 1개의 화면을 만들기 위해 여러개의 서피스에 렌더링하는 기술을 말한다


여기서는 멀티 패스 렌더링을 더욱 좁은뜻으로 다룰 것이다. 

멀티 패스 렌더링에는 [ 한번에 여러개의 서피스에 렌더링 하는 기술] 이라는 의미도 있다. 

예를들면 Tex1과 Tex2라는 서피스를 사용하여 백 버퍼에 렌더링 하는 경우 

Tex1 생성, Tex2 생성, 백 버퍼로의 렌더링이라는 3번(3패스)의 렌더링이 필요하게 된다.


멀티 패스 렌더링을 사용하면 Tex1의 생성과 Tex2의 생성을 1패스에서 한번에 수행할수 있다.

렌더링 회수가 2번이 되기 때문에 퍼포먼스를 큰 폭으로 향상시킬 수 있다. 



① 일단 렌더 타겟이 무엇인가..


   렌더링에 대해서 조금 복습해보자. 우리들이 평소에 아무렇지도 않게 렌더링하고잇는 백버퍼...

왠지 [ 렌더링 = 백버퍼 ]라고 생각하기 쉽지만, 실은 여기에도 조금 생략되어있는 부분이 있다. 


렌더링 디바이스는 디폴트 값으로 [ 렌더 타겟 0번]에 렌더링하도록 설정되어있으며,

백버퍼는 디폴트 값으로 렌더타겟 0번에 설정 되어있다. 


즉 렌더링 디바이스와 백버퍼 사이에는 [ 렌더 타겟 ] 이라는 서피스 저장소가 있는 것이다.

이것을 확실히 알면 멀티 패스 렌더링도 쉽다






② IDirect3DDevice9::SetRenderTarget 함수

    위의 그림처럼 백버퍼는 디폴트로 RT0에 설정되어 있긴 하지만 여기가 백버퍼의 고정석은 아니다.


IDirect3DDevice9::SetRenderTarget 함수를 사용하면 미리 만든 서피스를 RT0이나 RT1등으로 설정할 수 있다.:


 IDirect3Device9::SetRenderTarget 함수

HRESULT SetRenderTarget(
   DWORD RenderTargetIndex,
   IDirect3DSurface9 *pRenderTarget
);


RenderTargetIndex 에는 렌더 타겟의 번호를 설정한다

pRenderTarget에는 서피스를 넘긴다


주의 할 것은 SetRenderTarget 함수를 사용하면 이전에 설정되어있던 서피스의 포인터를 잃게 된다.

예를들어 RT0에 다른 서피스를 설정하면 백버퍼로 되돌아 올 수 없다

따라서 보통은 미리 설정된 서피스는 IDirect3DDevice9::GetRenderTarget으로 미리 저장해두고 그것을 바꾸는 형태로 사용한다



③ 지정한 렌더타겟에 렌더링 하기


   RT0 이외의 서피스에서의 렌더링은 고정 기능 파이프라인에서는 불가능하며(아마도..)프로그래머블 셰이더에서 가능하다


셰이더(HLSL)을 사용하면 픽셀 셰이더에서 아래와같은 형태로 사용한다


float4 Test_PS( float2 texCoord : TEXCOORD0 ) : COLOR0   //<- 여기!!!

{
   float outColor
   // 무언가 처리
   return outColor;
}


COLOR0라고 표시되어 있는 부분에 주목 한다.

이 부분이 실은 렌더타겟 0번에 렌더링 하세요~라는 의미의 시멘틱스이다.

COLOR의 뒷부분의 숫자가 실은 쓰여질 렌더타겟의번호 라는 것이다. 즉 이 말은..


 float4 Test_PS( float2 texCoord : TEXCOORD0 ) : COLOR1 //<- 여기!!!

{
   float outColor
   // 무언가 처리
   return outColor;
}


이렇게 하면 렌더타겟 1번에 쓰여진다는 것이 된다.

[ 이것은 싱글 패스 렌더링이잖아!!. 그럼 0번과 1번에 동시에 쓰려면 어떻게 해야하지?]

라고 생각할지도 모르지만 이 부분은 반환값을 구조체로 만들어 버리면 된다


 struct OUTPUT_PS 

{

   float4 color0 : COLOR0;
   float4 color1 : COLOR1;
};

OUTPUT_PS  Test_PS( float2 texCoord : TEXCOORD0 )
{
    OUTPUT_PS  outColor
    // 무언가 처리
   return outColor;
}



④ MRT를 서포트 하는가에 주의


   멀티 렌더 타겟은 비교적 최근엔 많이 쓰이지만 조금 옛날 비디오 카드면 서포트 하지 않는 경우도 있다

멀티 렌더 타겟으로써 가질 수 있는 서피스의 최대 수는 IDirect3DDevice9::GetDeviceCaps함수로 얻을수 있는 D3DCAPS9 구조체에서NumSimultaneousRTs의 체크한다


D3DCAPS9 Caps;

pDev->GetDeviceCaps( &Caps );
DWORD MaxRT = Caps.NumSimultaneousRTs;

멀티 렌더 타겟의 최대 수


이것이 1일 경우, 멀티 패스 렌더링은 할 수 없다. ELSA GLADIAC FX746Ultra DDR3(Geforce FX 5700 Ultra)에서는 1, 노트북 그래픽 카드인 (FMV-BIBLO MG70H 2004년 봄 모델 Intel(R) 82852/82855 GM/GME Graphics Controller)에서도 1이었다.

NVIDIA GeForce6600에서는 4였다.


대충 2005년 이후 나온 모델은 사용가능 할 것이라 판단된다


프로그램상에서 이것을 확인하는 것이 귀찮은 사람은 DirectX의 유틸리티 중DirectX Caps Viewer(DXCapsViewer.exe)」를 사용하길 바란다. 이것은 비디오 카드의 능력을 열거해 주는 어플리케이션이다.

자신의 비디오카드 폴더 내에서 [D3D Device Types]→[HAL]→[Caps]안에 위 플래그가 있을 것이다



⑤ 멀티 패스 렌더링으로 무엇을 할 것인가?


  멀티 패스 렌더링을 함으로 뭐가 가능한가? 이것은 딱 이거다 라고 할순 없지만 근래의 복잡하며 여러 장의 텍스처를 겹쳐서 사용하는 렌더링 표현에서는 필수 항목인 기술인 것은 확실하다.

특히 [ 동적으로 텍스처를 만드는 ] 이펙트에서 효과적이다

동적으로 만든다고 하면 포스트 이펙트 (렌더링한 그림에 뭉개기 효과나 세피아톤등으로 가공하는 후처리), 큐브 맵 생성, 거울 효과등등 여러가지 있을 것이다.


멀티 패스 렌더링에서의 또다른 장점은 버텍스 셰이더와의 균형이다.

버텍스 셰이더에서는 매우 복잡한 본 조작, 픽셀 셰이더에서의 라이트 처리를 위한 법선 설정, 

버텍스 변환등 귀찮은 것을 여러가지 수행한다.


싱글 패스 렌더링의 경우 매번 이 작업을 반복해야 하는 반면 멀티 패스 렌더링에서는 대부분의 버텍스 셰이더 작업을 1번으로 끝낼 수 있다. 이것은 퍼포먼스 향상으로 연결 된다.


멀티 패스 렌더링에서 뭐가 가능한가는 셰이더 프로그램을 배워가면 자연히 알게 되겠지만 연습을 위해 RGB 칼라와 알파 정보를 2개의 서피스( 하나는 백 버퍼)에 동시에 렌더링해보자



⑥ 멀티 패스 렌더링 예 -1:색과 알파 값을 동시에 렌더링


   이것은 DirectX 부록으로 있는 비행기 모델을 렌더링 한다.

이때 RGB 칼라와 알파 값을 분해 해어 별도의 텍스처로 한번 렌더링 한다.

그리고 이 결과를 교대로 화면에 렌더링 한다.

이것이 어디에 쓰이는가 보다는 멀티 패스 렌더링의 본질을 이해 하는데 집중해주길 바란다.)


○ 셰이더 프로그램

   우선은 셰이더 프로그램을 만든다. 목표는 픽셀 셰이더에서 렌더링 정보를 RGB와 알파값으로 분해하는 것이다


float4x4 WVP;   // WorldViewProjection Matrix

texture Tex;    // Texture
sampler2D TexSampler = sampler_state {  Texture = (Tex); };

struct OUTPUT_VS
{
    float4 pos      : POSITION;
    float2 texCoord : TEXCOORD0;
};

struct OUTPUT_PS
{
    float4 color : COLOR0;
    float4 alpha : COLOR1;
};

OUTPUT_VS SimpleVS( float4 inPos : POSITION, float2 inTexCoord : TEXCOORD0 )
{
    OUTPUT_VS outVS = (OUTPUT_VS)0;
    outVS.pos = mul( inPos, WVP );
    outVS.texCoord = inTexCoord;
    return outVS;
}

OUTPUT_PS RGBAndAlphaMPR_PS( float2 texCoord : TEXCOORD0 )
{
    OUTPUT_PS PSout = (OUTPUT_PS)0;
    PSout.color = tex2D( TexSampler, texCoord );
    PSout.alpha = PSout.color.a;
    PSout.alpha.a = 1.0f;
    return PSout;
}

technique RGBAndAlphaMPR
{
    pass p0
    {
        // 렌더 스테이트 설정
        AlphaBlendEnable = TRUE;
        SrcBlend = SRCALPHA;
        DestBlend = INVSRCALPHA;
        ColorOp[0] = SELECTARG1;
        ColorArg1[0] = TEXTURE;
        ColorArg2[0] = DIFFUSE;
        AlphaOp[0] = SELECTARG1;
        AlphaArg1[0] = TEXTURE;
        AlphaArg2[0] = DIFFUSE;
        ColorOp[1] = DISABLE;
        AlphaOp[1] = DISABLE;

        // 셰이더
        VertexShader = compile vs_2_0 SimpleVS();
        PixelShader = compile ps_2_0 RGBAndAlphaMPR_PS();
    }
}

셰이더 프로그램 (RGBAndAlphaMPR.fx)


월드-뷰-프로젝션 행렬로써 WVP를 선언한다. 

다음으로 Tex는 모델의 입히는 텍스처이다

이것은 픽셀 셰이더에서 사용한다

sampler는 텍스처로부터 색을 취하는 형태이지만 이번엔 Tex로부터 얻을 수 있도록 설정하였다.

원래는 샘플링 방법등을 정의하지만 여기서는 간단하게 하기 위해 생략한다.


다음 OUTPUT_VS는 버텍스 셰이더의 반환값에 대한 구조체이다.

이번엔 변환후의 버텍스 단위와 텍스처 좌표(UV 좌표)가 필요하므로 위와 같이 설정한다.

그 다음에 있는 OUTPUT_PS가 여기에서의 핵심이다. 여기에는 2개의 COLOR가 설정되어있다.

OUTPUT_PS::alpha에 알파 정보가 저장되며, 이것이 렌더타겟 1번에 출력될 값이다.


SimpleVS 버텍스 셰이더는 딱히 무언가 하는 것은 아니다 입력된 로컬 버텍스를 WVP행렬을 사용해 스크린 좌표로 변환한다

UV좌표도 구조체에 복사해서 반환값을 전달 하고 있다


픽셀 셰이더에서는 넘어온 UV 좌표에 해당하는 텍셀(텍스처 좌표상의 픽셀)을 tex2D함수로 얻어온다.

이것은 픽셀 셰이더의 기본이다.


얻어온 색으로부터 알파값을 PSout.alpha에 대입하고 있다.

마지막으로 return에서 구조체를 반환한다.

이것으로 한번에 2개의 렌더 타겟에서 렌더링된다


○ 테크닉



technique RGBAndAlphaMPR

{
    pass p0
    {
        // 렌더 스테이트 설정
        AlphaBlendEnable = TRUE;
        SrcBlend = SRCALPHA;
        DestBlend = INVSRCALPHA;
        ColorOp[0] = SELECTARG1;
        ColorArg1[0] = TEXTURE;
        ColorArg2[0] = DIFFUSE;
        AlphaOp[0] = SELECTARG1;
        AlphaArg1[0] = TEXTURE;
        AlphaArg2[0] = DIFFUSE;
        ColorOp[1] = DISABLE;
        AlphaOp[1] = DISABLE;

        // 셰이더
        VertexShader = compile vs_2_0 SimpleVS();
        PixelShader = compile ps_2_0 RGBAndAlphaMPR_PS();
    }
}

테크닉 (RGBAndAlphaMPR.fx)


알파 블렌드를 유효하게 해야 하므로 AlphaBlendEnable을 TRUE로 이하 알파 블렌드를 구현하는 스탠다드한 설정을한다


○ 프로그램


 // 멀티 렌더 타겟 테스트


#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

#include <windows.h>
#include <tchar.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <math.h>

TCHAR gName[100] = _T("멀티 렌더 타겟");

#define SAFERELEASE(x) if(x){x->Release();}
#define FULLRELEASE \
       SAFERELEASE(pAlphaSurf);   \
       SAFERELEASE(pBackBuffer);  \
       SAFERELEASE(pEffect);      \
       SAFERELEASE(pErrorBuffer); \
       SAFERELEASE(pAirPlaneTex); \
       SAFERELEASE(pAirPlane);    \
       SAFERELEASE(pAlphaTex);    \
       SAFERELEASE(g_pD3DDev);    \
       SAFERELEASE(g_pD3D);

#define FAILEDCHECK(x) \
if(FAILED(x)) {        \
        FULLRELEASE;   \
       return 0;       \
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam){
   if(mes == WM_DESTROY || mes == WM_CLOSE ) {PostQuitMessage(0); return 0;}
   return DefWindowProc(hWnd, mes, wParam, lParam);
}


int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
   // 어플리케이션 초기화
   MSG msg; HWND hWnd;
   WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL, NULL,
                                    (HBRUSH)(COLOR_WINDOW+1), NULL, (TCHAR*)gName, NULL};
   if(!RegisterClassEx(&wcex))
      return 0;

   if(!(hWnd = CreateWindow(gName, gName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 640, 480,
                                    NULL, NULL, hInstance, NULL)))
      return 0;

   // Direct3D 초기화
   LPDIRECT3D9 g_pD3D;
   LPDIRECT3DDEVICE9 g_pD3DDev;
   if( !(g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )) ) return 0;

   D3DPRESENT_PARAMETERS d3dpp = {640,480,D3DFMT_UNKNOWN,0,D3DMULTISAMPLE_NONE,0,
                                                      D3DSWAPEFFECT_DISCARD,NULL,TRUE,TRUE,D3DFMT_D24S8,0,D3DPRESENT_RATE_DEFAULT,D3DPRESENT_INTERVAL_DEFAULT};

   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   {
      g_pD3D->Release();
      return 0;
   }

   D3DCAPS9 Caps;
   g_pD3DDev->GetDeviceCaps( &Caps );
   DWORD RT = Caps.NumSimultaneousRTs;
   if ( RT <= 1 ) {
       MessageBox( hWnd, _T("멀티 렌더 타겟을 지원하지 않습니다 종료합니다"), _T("그 외 에러"),0);
       g_pD3DDev->Release();
       g_pD3D->Release();
       return 0;
   }

   // 변수 정의
   ID3DXMesh *pAirPlane = 0;
   IDirect3DTexture9 *pAirPlaneTex = 0;
   IDirect3DTexture9 *pAlphaTex = 0;
   ID3DXEffect *pEffect = 0;
   ID3DXBuffer *pErrorBuffer = 0;
   IDirect3DSurface9 *pAlphaSurf = 0;
   IDirect3DSurface9 *pBackBuffer = 0;

   // 비행기 오브젝트 생성
   DWORD NumMaterials;
   FAILEDCHECK( D3DXLoadMeshFromX( _T("airplane 2.x"), D3DXMESH_MANAGED, g_pD3DDev, NULL, NULL, NULL, &NumMaterials, &pAirPlane) );
   FAILEDCHECK( D3DXCreateTextureFromFile( g_pD3DDev, _T("AirPlaneTex.png"), &pAirPlaneTex ) );

   // 이펙트 생성
   FAILEDCHECK( D3DXCreateEffectFromFile( g_pD3DDev, _T("RGBAndAlphaMPR.fx"), 0, 0, 0, 0, &pEffect, &pErrorBuffer) );

   // 알파용 텍스처 생성
   FAILEDCHECK( g_pD3DDev->CreateTexture( 640, 480, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pAlphaTex, 0 ) );

   // 렌더 타겟 세팅
   pAlphaTex->GetSurfaceLevel( 0, &pAlphaSurf );
   g_pD3DDev->SetRenderTarget( 1, pAlphaSurf );
   g_pD3DDev->GetRenderTarget( 0, &pBackBuffer );

   // 각 행렬 생성
   D3DXMATRIX WorldMat, ViewMat, ProjMat, WVP;
   D3DXMatrixIdentity( &WorldMat );
   D3DXMatrixPerspectiveFovLH( &ProjMat, D3DXToRadian(45), 640.0f/480.0f, 0.1f, 100.0f);

   ShowWindow(hWnd, nCmdShow);

   // 메시지 루프
   int count = 0;
   double angle = 0.0;
   do{
      Sleep(1);
      if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ){ DispatchMessage(&msg);}

         g_pD3DDev->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(40,40,80), 1.0f, 0 );
         g_pD3DDev->BeginScene();

         // 뷰 회전
         angle += 0.01f;
         D3DXMatrixLookAtLH(
             &ViewMat,
             &D3DXVECTOR3((float)(10.0f*cos(angle)),5,(float)(10.0f*sin(angle))),
             &D3DXVECTOR3(0,0,0),
             &D3DXVECTOR3(0,1,0)
             );
         WVP = WorldMat * ViewMat * ProjMat;

         // 렌더 타겟 교환
        if ( count++ % 60 == 0 ) {
            IDirect3DSurface9 *pTmp = pAlphaSurf;
            pAlphaSurf = pBackBuffer;
            pBackBuffer = pTmp;
            g_pD3DDev->SetRenderTarget( 1, NULL );      // 이부분
            g_pD3DDev->SetRenderTarget( 0, pBackBuffer );
            g_pD3DDev->SetRenderTarget( 1, pAlphaSurf );
        }

         // 렌더 디바이스에 이펙트 세팅
         pEffect->SetMatrix("WVP", &WVP );
         pEffect->SetTexture("Tex", pAirPlaneTex );
         pEffect->SetTechnique( "RGBAndAlphaMPR" );
         unsigned int numPass;
         pEffect->Begin( &numPass, 0 );
         pEffect->BeginPass( 0 );
        unsigned int i;
        for( i = 0; i < NumMaterials; i++ )
             pAirPlane->DrawSubset( i );
        pEffect->EndPass();


         g_pD3DDev->EndScene();
         g_pD3DDev->Present( NULL, NULL, NULL, NULL );
   }while(msg.message != WM_QUIT);

   FULLRELEASE;

   return 0;
}

메인 프로그램(main.cpp)




반응형
반응형

BLOG main image




오브젝트들이 파이프라인을 통과하면서 최종 그려질 화면을 만들게 된다, D3D에서는 화면에 출력할때


중간의 끊김없이 화면을 보여주기 위해서 back buffer 와 front buffer 를 사용해 끊김을 해결하고있다


front buffer 에서는 화면에 보여주는 역할을 하게 되고 back buffer 에서는 그릴 화면을 저장하는 메모리용도로 사용한다



이때 back buffer 에서 front buffer 로 스위치되면서 화면에 출력되는 시간단위를 '프레임' 이라고 한다


현재 게임에선 프레임이 1초에 몇번 스위치 됐는지를 계산해 FPS로 계산한다




또한 D3D에서는 보여질 버퍼를 텍스처에 쓸 수 있게도 지원한다, 즉 메모리에 화면을 출력할 수 있도록 허용하며


그 출력 대상은 텍스처가 될 수도 있다, 이때 그려지는 대상이 되는 텍스처의 명칭을 렌더타겟이라고 한다




이로써 Shader 에서 멀티패스로 다양한 효과처리가 가능해지게 된다



반응형
반응형

http://www.kwxport.org/


kW X-port 3ds Max X file exporter

For some reason, users are getting "cannot display page" and "content decoding" errors on this kw X-port plugin site. It 
works in FireFox, but not in Chrome or IE9. I have no idea why -- perhaps Drupal, or one of the plug-ins I'm using, is 
generating bad UTF-8? Or maybe Dreamhost changed proxies and suddenly something is broken. I simply don't have 
the time to run this site any longer -- it's bad enough that I still haven't updated the exporter to 3ds Max version 
2012.

Any year now -- Real Soon Now -- Promise!)

So, my drastic fix is this: You can read this text. You can download the installers. However, all the log-in and forums 
and contact-me functionality is gone. This is pretty much a static web page now! If you need to talk to me, try 
tweeting @jwatte or contacting me as hplus0603 on gamedev.net.


Source code access should still work. Try the following:

svn co http://svn.kwxport.org/kwxport kwxport

Also, the ads weren't really making me any money, so they're gone, too. If it had been wildly successful, I imagine 

I'd have had more time to run the site itself :-)


반응형
반응형




DXSDK_DIR ( 환경변수 ) 설정법|… * Direct X
2011.10.25 15:26

 

내컴퓨터 -> 오른쪽 마우스 클릭후 "속성" -> 고급시스템 설정 -> 환경변수







http://cafe.naver.com/leafs/94884





그럼 위와 같은 창에서 VC++ 디렉토리를 클릭후, 우측에 포함 디렉토리에는 $(DXSDK_DIR)Include를 추가하고, 라이브러리 디렉토리에는 $(DXSDK_DIR)Lib\x86를 추가해 주세요.





반응형
반응형

http://d.hatena.ne.jp/runicalp/20081114/1226680735


  • error C2051 : case 식은 정수 상수이어야합니다. c : \ development \ sdk \ temp \ sdk ( c + + ) \ samples \ c + + \ common \ src\ d3dapp.cpp 1582

필자 환경에서는 HRESULT_FROM_WIN32가 인라인 함수 로 정의되어 있기 때문에 이것을 매크로 로 바꿉니다.

SDK ( C + + ) \ Samples \ C + + \ Common \ Src \ d3dapp.cpp 1582 행

case HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) :

case __HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) :

반응형
반응형

http://magic-finger.tistory.com/28

[HLSL] DX9 Effect에서 pass함수 변경사항.

최근에 DX9가 업데이트되면서 HLSL Effect의 패스호출 함수인 ID3DXEffec::Pass(UINT* UPass)가
ID3DXEffect::BeginPass(UINT* UPass) ID3DXEffect::EndPass();로 변경되었습니다.
대부분 D3D9책에서는 
ID3DXEffec::Pass(UINT* UPass)로 나왔을거에요.(현재 사용하고 있는 2010버전엔 없더라구요.) 
위 두 함수사이에 렌더함수를 호출하면되는데 문제는 우리가 원하는 결과가 아니라는겁니다.
문제의 원인이 되는 부분은 바로 BeginPass와 EndPass함수로서 BeginPass함수의 특성상 EndPass가 실행되기 전까지 다음 스테이트로 넘어가지않고 계속 호출하게되어 나중엔 제일 마지막에 설정한 부분에 모두 출력하게된다는 것이죠.
그렇담 여기서 몇가지 해결방법을 생각해볼 수 있겠군요.

첫번쩨로 렌더링함수를 호출할 때마다 BeginPass와 EndPass를 호출하는방법입니다. 이렇게하면 네군데에 물체가 잘나옵니다만 물체가 출력되는 결과물을 보니 원하는 순서가 아니네요? 맨 마지막에 출력되야할 물체가 맨 첫번째로 가있고, 맨처음 출력해야할 물체가 맨마지막으로 가있다는 사실을 발견할 수가 있어요. 이 방법이 해결된다고해도 반복되는 코드가 많아서 코드가 쓸때없이 길어지고 수십번이상 반복되는 코드라면 골치가 아파집니다. ㅋㅋ 어휴 

[첫번째 방법 소스코드]
ToonEffect->BeginPass(j);

                ToonEffect->SetMatrix(hWorldMatrix, &World[0]);
                ToonEffect->SetMatrix(hViewMatrix, &View);
                ToonEffect->SetVector(hColor, &color[0]);
                Mesh[0]->DrawSubset(0);  
  
ToonEffect->EndPass();

ToonEffect->BeginPass(j);

                ToonEffect->SetMatrix(hWorldMatrix, &World[1]);
                ToonEffect->SetMatrix(hViewMatrix, &View);
                ToonEffect->SetVector(hColor, &color[1]);
                Mesh[1]->DrawSubset(0);  
  
ToonEffect->EndPass();

ToonEffect->BeginPass(j);

                ToonEffect->SetMatrix(hWorldMatrix, &World[2]);
                ToonEffect->SetMatrix(hViewMatrix, &View);
                ToonEffect->SetVector(hColor, &color[2]);
                Mesh[2]->DrawSubset(0);  
  
ToonEffect->EndPass();

ToonEffect->BeginPass(j);

                ToonEffect->SetMatrix(hWorldMatrix, &World[3]);
                ToonEffect->SetMatrix(hViewMatrix, &View);
                ToonEffect->SetVector(hColor, &color[3]);
                Mesh[3]->DrawSubset(0);  
  
ToonEffect->EndPass();



두번째 방법으로 반복되는 코드를 예전과 같이 루프로 묶고 루프 안에 Begin/End Pass를 넣는 방법으로 생각해봅니다.

[두번째 방법 소스코드]
Device->Begin();

UINT Pass;
        ToonEffect->Begin(&Pass, 0);
        for(int j = 0 ; j < Pass ; j++)
        {
            
            for(int i = 0 ; i < 4 ; i++)
            {        
                ToonEffect->BeginPass(j);

                ToonEffect->SetMatrix(hWorldMatrix, &World[i]);
                ToonEffect->SetMatrix(hViewMatrix, &View);
                ToonEffect->SetVector(hColor, &color[i]);
                Mesh[i]->DrawSubset(0); 

                ToonEffect->EndPass();   
            }
            
        }
        ToonEffect->End();

Device->End();


이렇게하면 매 루프때마다 Begin/End Pass를 호출해서 매 스테이트마다 넘어가겠지만 결과는 첫번째 방법과 동일하다는 것을 알 수가 있습니다.  

이것도 안된다 저것도 안된다...
정녕 해결방법은 없는 것일까요?

아직 포기하기엔 이릅니다! 
DirectX를 만든 MS에서 위 두 함수를 새로 만들었으면 두 함수를 책임을 져야하는 함수를 따로 안만들었을리는 없겠지요.
그것이 바로 ID3DXEffect::CommitChanges()함수입니다. 이를 이용하는 겁니다. 이 문제점의 해결방법이기도하구요.
위 함수를 렌더링함수를 불러오기 전에 호출해봅니다. (꼭 렌더링함수 호출 전에 호출해야합니다. 안그러면 첫번째나 두번째처럼 순서가 뒤바뀝니다.)

[해결방법 소스코드]
//호출순서 : 디바이스의 Begin > 이펙트의 Begin(이펙트 내의 패스 수 리턴) > 이팩트의 BeginPass(패스 수만큼 루프를 돈다)
Device->Begin();

UINT Pass;
        ToonEffect->Begin(&Pass, 0);
        for(int j = 0 ; j < Pass ; j++)
        {
            ToonEffect->BeginPass(j);
            for(int i = 0 ; i < 4 ; i++)
            {        
                ToonEffect->SetMatrix(hWorldMatrix, &World[i]);
                ToonEffect->SetMatrix(hViewMatrix, &View);
                ToonEffect->SetVector(hColor, &color[i]);
                ToonEffect->CommitChanges(); //BeginPass호출 시 그리기 전에 반드시 이 함수 호출
                Mesh[i]->DrawSubset(0);    
            }
            ToonEffect->EndPass();
        }
        ToonEffect->End();

Device->End();


결과가 어떤가요? 원하는 결과가 잘 출력되었나요?
BeginPass와 EndPass를 사용하게되면(특히 반복해서 렌더링하는 함수가 존재할 경우) CommitChanges함수도 같이 사용해야한다는 사실 잊지마세요.

ID3DXEffect::CommitChanges()호출 전

ID3DXEffect::CommitChanges()호출 후

샘플은 카툰렌더링기법입니다.

반응형
반응형

  
2007.07.10 17:53

error C2061: 구문 오류 : 식별자 'LPDIRECTXFILEDATA'

 

 

DirectX 9.0 에서 9.0C로 넘어가면서 바뀐었다

해결

 

#include <dxfile.h>






http://d.hatena.ne.jp/runicalp/20081114/1226680735


  • error C2051 : case 식은 정수 상수이어야합니다. c : \ development \ sdk \ temp \ sdk ( c + + ) \ samples \ c + + \ common \ src\ d3dapp.cpp 1582

필자 환경에서는 HRESULT_FROM_WIN32가 인라인 함수 로 정의되어 있기 때문에 이것을 매크로 로 바꿉니다.

SDK ( C + + ) \ Samples \ C + + \ Common \ Src \ d3dapp.cpp 1582 행

case HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) :

case __HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) :


반응형
반응형




이펙트로 렌더링 할 때 렌더링할때 ID3DXEffect::Begin 과 ID3DXEffect::End  블록을 사용하는데 


이때  Begin 함수에서  pEffect->Begin( NULL, var );  처럼 var 자리에 아래 값들을 지정해 각각 이펙트를 켜고 끄는 기능을 할 수 있다






http://goo.gl/0eRVP


zero ( 0 )                                         :   현재의 장치 상태와 셰이더 상태를 보관했다가 이펙트가 종료될때(ID3DXEffect::End 가 호출될때)

 상태를 복구할 것을 지시한다, 이펙트는 상태를 변겨할 수 있으며 이 플래그를 통해 이펙트가 시

 작 할 때의 상태로 되돌아 갈 수 있다


D3DXFX_DONOTSAVESTATE         : 장치의 상태를 보관했다가 복구할 것을 지시한다(셰이더 상태는 제외한다).


D3DXFX_DONOTSAVESHADERSTATE   :   셰이더 상태를 보관하고 복구하지 않을 것을 지정한다.

반응형
반응형


http://blog.naver.com/nowcom77/20171445466


3D에서 글자를 출력하는 부분과 FPS를 출력하는 내용입니다. 

 

 

 

 

12문자 출력

   

Direct3D에서는 문자를 출력하기 위해서 LPD3DXFONT 객체를 사용한다.

   

12.1 LPD3DXFONT 객체 생성과 초기화

   

LPD3DXFONT 객체를 생성하고 초기화하는 함수로 D3DXCreateFont()가 있다.

 

HRESULT D3DXCreateFont(

__in LPDIRECT3DDEVICE9 pDevice,

__in INT Height,

__in UINT Width,

__in UINT Weight,

__in UINT MipLevels,

__in BOOL Italic,

__in DWORD CharSet,

__in DWORD OutputPrecision,

__in DWORD Quality,

__in DWORD PitchAndFamily,

__in LPCTSTR pFacename,

__out LPD3DXFONT *ppFont

);

[표 12-1] Font 생성 함수

   

Height와 Width는 글자의 가로세로 길이이며 Weight는 글자의 굵기를 결정하는 매개변수이다. Weight에 설정하는 값은WinGDI.h 헤더에 있으며 그 기본 값은 FW_NORMAL이다.

 

#define FW_THIN 100

#define FW_EXTRALIGHT 200

#define FW_LIGHT 300

#define FW_NORMAL 400

#define FW_MEDIUM 500

#define FW_SEMIBOLD 600

#define FW_BOLD 700

#define FW_EXTRABOLD 800

#define FW_HEAVY 900

   

#define FW_ULTRALIGHT FW_EXTRALIGHT

#define FW_REGULAR FW_NORMAL

#define FW_DEMIBOLD FW_SEMIBOLD

#define FW_ULTRABOLD FW_EXTRABOLD

#define FW_BLACK FW_HEAVY

[표 12-2] WinGDI.h 헤더

   

MipLevels에는 기본 값인 1을 설정하며 Italic에는 이텔릭체를 사용할 것인지의 여부를 설정하며 여기에는 일반적으로 FALSE를 설정한다.

그 외에는 기본값을 설정하면 되며 CharSet에는 DEFAULT_CHARSET을 설정하며 OutputPrecision에는OUT_DEFAULT_PRECIS으로 설정한다.

그리고 Quality에는 DEFAULT_QUALITY를 PitchAndFamily에는 DEFAULT_PITCH | FF_DONTCARE를 설정한다.

pFacename에는 글자체를 설정하는데 "Arial" 또는 “System“등을 설정한다.

여기까지 설명한 폰트의 설정값을 셋팅하여 D3DXCreateFont() 함수를 호출하면 다음과 같다.

   

LPD3DXFONT Font;

................. 생략 ................

D3DXCreateFont( m_pd3dDevice, 20, 0, FW_NORMAL, 1, FALSE, DEFAULT_CHARSET,

OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,

"Arial", &Font );

[표 12-3]

   

12.2 출력

   

글자를 출력해 주는 LPD3DXFONT 객체의 멤버 함수에는 DrawText()가 있으며 그 원형은 다음과 같다.

   

INT DrawText(

[in] LPD3DXSPRITE pSprite,

[in] LPCTSTR pString,

[in] INT Count,

[in] LPRECT pRect,

[in] DWORD Format,

[in] D3DCOLOR Color

);

[표 12-4] 출력 함수

 

pSprite에는 NULL을 설정하고 pString에는 출력하려는 문자열을 설정한다. Count에는 1을 설정하며 널문자까지를 출력하게 된다.

pRect에는 출력하려는 위치를 설정하는데 left와 top 값을 설정하면 되며 나머지는 0으로 설정한다. Format에는 문자의 정렬에 관련된 값을 설정하는데 DT_NOCLIP을 설정한다.

Color에는 출력할 색상값을 설정하며 색상값은 D3DXCOLOR()를 이용하여 설정한다.

색상값의 범위는 0.0 ~ 1.0f 까지면 그 원형은 다음과 같다.

   

D3DXCOLOR( FLOAT r, FLOAT g, FLOAT b, FLOAT a );

출력함수를 설정하면 다음과 같다.

   

RECT rt;

SetRect( &rt, 100, 430, 0, 0 );

   

Font->DrawText( NULL, "Test", -1, &rt, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );

   

12.3 FPS 출력

   

FPS(Frame Per Second)는 1초에 화면 전환이 몇 번 일어났는가를 측정한 값을 말한다.

그래서 FPS로 게임 엔진의 렌더링 성능을 평가하는 경향이 있으며 게임 엔진의 개발 초기에 는 항상 FPS를 출력하면서 프로그래밍을 한다.

컴퓨터에서는 초 단위가 아닌 밀리세컨드 단위로 시간 값을 가져오므로 1초는 1000 밀리세컨드가 되며 경과된 시간이 1초인지를 알 수 있는 방법은 현재 시각과 이전 시각의 차를 이용하거나 매 프레임마다 경과된 시간을 누적하여 판단하는 방법등이 있다.

아래의 소스는 매 프레임마다 경과된 시간을 누적하여 판단하는 소스이다.

   

void CGameEdu01::OnInit()

{

int i;

   

RECT rect;

D3DVIEWPORT9 vp;

GetClientRect( m_hWnd, &rect );

   

vp.X = 0;

vp.Y = 0;

vp.Width = rect.right - rect.left;

vp.Height = rect.bottom - rect.top;

vp.MinZ = 0.0f;

vp.MaxZ = 1.0f;

   

m_Eye.x = 0.0f;

m_Eye.y = 10.0f;

m_Eye.z =-32.0f;

   

m_At.x = 0.0f;

m_At.y = 0.0f;

m_At.z = 0.0f;

   

m_Up.x = 0.0f;

m_Up.y = 1.0f;

m_Up.z = 0.0f;

   

D3DXMatrixLookAtLH( &m_matView, &m_Eye, &m_At, &m_Up );

m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_matView );

D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );

m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProj );

m_pd3dDevice->SetViewport( &vp );

   

D3DXCreateFont( m_pd3dDevice, 20, 0, FW_NORMAL, 1, FALSE, DEFAULT_CHARSET,

OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,

"System", &m_pFont );

}

   

void CGameEdu01::OnRender()

{

char string[100];

RECT rt = { 10, 10, 0, 0 };

   

sprintf( string, "FPS: %d", m_nFPS );

m_pFont->DrawText( NULL, string, -1, &rt, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f,

0.0f, 1.0f ) );

m_nFPSCount++;

}

   

void CGameEdu01::OnUpdate()

{

DWORD dwCurTime = GetTickCount();

static DWORD dwOldTime = GetTickCount();

static DWORD dwAccumulateTime = 0; // 누적 경과 시간

   

m_dwElapsedTime = dwCurTime – dwOldTime; // 프레임 경과 시간

dwOldTime = dwCurTime;

   

dwAccumulateTime += m_dwElapsedTime; // 누적

if( dwAccumulateTime >= 1000 ) // 1초 경과 체크

{

dwAccumulateTime = 0;

m_nFPS = m_nFPSCount;

m_nFPSCount = 0;

}

}

   

void CGameEdu01::OnRelease()

{

      m_pFont->Release();

}

   

  

[출처] 12강. 글자 출력|작성자 nowcom77

반응형
반응형


http://dark0946.tistory.com/63


조명

환경광(Ambient Light)  : 

난반사광(Diffuse Light) :

정반사광(Specular Light) :




재질( = 머트리얼) 지정
D3DMATERIAL9
{
Diffuse  - 표면이 반사하는 난반사광
Ambient - 표면이 반사하는 환경광
Specular - 표면이 반사하는 정반사광
Emissive - 자체 발광
Power - 발광 정도
}




광원
 - 점 광원(Point Light)
멀리 갈수록 어두워지며, 멀리갈수록 그림자가 커진다.

- 방향성 광원(Directional Light)
 = 태양광과 비슷. 빛의 밝기는 똑같음. 각도의 영향

- 스포트 광원(Spot Light)
특정 영역에만 비춤.(스포트라이트, 손전등과 유사)
가운데 지점은 밝고 주변으로 갈수록 어두워짐.


D3DLIGHT9
{
D3DLIGHTTYPE  Type - 광원 종류
D3DCOLORVALUE Diffuse - 표면이 반사하는 난반사광 색상
D3DCOLORVALUE Ambient - 표면이 반사하는 환경광 색상
D3DCOLORVALUE Specular - 표면이 반사하는 정반사광 색상
D3DVECTOR Position  -   광원의 위치 지정 벡터 (방향성광원은 상관없음 - 거리에따라 빛의 세기가 변하지 않음.)
D3DVECTOR Direction  - 빛이 향하는 방향 지정. (점광원은 필요없음 - 주변으로 다 비치니까)
float Range;  - 빛이 소멸되는거리. (Ex. 남산 언덕에 있는 가로등 하나가 내 얼굴까지와서 비추진 않는다.)
float Falloff; - (스포트에서만 사용) 밝은 원과 주변 어두운 원의 밝기 차이
float Attenuation0; - 상수감소
float Attenuation1; - 선형감소
float Attenuation2; - 이차감소
float Theta;     -스포트 광원에서 가장 밝은부분 비추는 각도
float Phi; - 스포트 광원에서 전체를 비추는 각도
}





http://dark0946.tistory.com/65



 D3DLIGHT9 dir;
 ::ZeroMemory(&dir, sizeof(dir));
 dir.Type      = D3DLIGHT_DIRECTIONAL;   // 조명 종류
 dir.Diffuse   = d3d::WHITE;  // 난반사광 색상
 dir.Specular  = d3d::WHITE * 0.3f;  // 정반사광 색상
 dir.Ambient   = d3d::WHITE * 0.6f;  // 환경광 색상
 dir.Direction = D3DXVECTOR3(0.0f, 0.0f, -5.0f); // x축 방향에서 빛이 비춰짐.


  D3DXVECTOR3 pos(0.0f, 0.0f, -10.0f);   // 원점 to  벡터좌표 X  -> 벡터좌표 -> 원점  :: 화살표 방향을 기준
  D3DXCOLOR c1 = d3d::WHITE;
  D3DLIGHT9 p1  = d3d::InitDirectionalLight(&pos,&c1);


반응형
반응형



Device 초기화  Direct 2D 

2012/05/08 05:40

복사http://blog.naver.com/dyunarion/80159553505

디바이스 초기화

 

장치의 정보를 가져오는데 성공했으면 이제 장치를 원하는 방향으로 세팅해야 합니다.

이 단계는 D3DPRESENT_PARAMETERS 구조체 인스턴스를 채우는 일로 이 구조체는 IDirect3DDevice9 객체의 성격을 결정하는데

이용 됩니다.

 

우선 세팅할 구조체를 선언하겠습니다.

D3DPRESENT_PARAMETERS d3dpp;   //이 구조체는 앞으로 그래픽 장치의 설정을 담을 용도입니다.

ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));  //값을 넣어주기 전에 우선 전부 0으로 만들겠습니다.

 

D3DPRESENT_PARAMETERS 구조체의 멤버는 개수가 좀 많습니다.

 

BackBufferWidth 와 BackBufferHeight는 후면 버퍼의 너비와 높이이며 UINT형 입니다.

백버퍼의 가로길이, 세로길이를 넣어주시면 됩니다.

d3dpp.BackBufferWidth = WINSIZEX;  //저는 미리 const 해둔 클라이언트 가로와 세로로 하겠습니다.

d3dpp.BackBufferHeight = WINSIZEY;

 

BackBufferFormat 은 백퍼버의 픽셀 포멧으로 저는 32비트로 하겠습니다.

d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;

 

BackBufferCount 는 사용할 백버퍼의 수를 의미하는데 보통 1을 지정해서 한개의 백버퍼를 사용합니다.

d3dpp.BackBufferCount = 1;

 

MultiSampleType과 MultiSampleQuality는 멀티샘플링의 사용여부와 그 수위로 이미지를 보다 더 부드럽게 표현이 가능한 옵션입니다.

d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;  //저는 사용하지 않겠습니다.

d3dpp.MultiSampleQuality = 0; //사용하지 않으므로 0으로 두겠습니다.

 

SwapEffect 는 플리핑 체인의 버퍼가 교환되는 방법입니다. D3DSWAPEFFECT_DISCARD가 가장 효과적입니다.

d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

 

hDeviceWindow는 사용할 윈도우의 핸들로 드로인의 대상이 될 윈도우를 지정해 줍니다.

d3dpp.hDeviceWindow = g_hWnd;  //미리 잡아둔 hWnd를 사용하겠습니다.

 

Windowed는 윈도우 모드를 지정합니다. true로 할 경우 윈도우 화면을 false로 할 경우 전체 화면이 지정됩니다.

d3dpp.Windowed = true; //창 모드로 하겠습니다.

 

EnableAutoDepthStencil은 Direct가 자동으로 깊이/스텐실 버퍼를 만들고 관리하게 하려면 true로 지정합니다.

d3dpp.EnableAutoDepthStencil = true;

 

AutoDepthStencilFormat은 깊이, 스텐실 버퍼의 포맷입니다.

d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; //깊이에 24bit 스텐실에 8bit 사용

 

Flags는 몇 가지 부가적인 기능으로 0으로 하거나 D3DPRESENTFLAG 집합의 멤머중에 하나를 지정할 수 도 있습니다.

d3dpp.Flags = 0; //저는 사용하지 않겠습니다.

 

FullScreen_RefreshRateInHz은 재생율을 지정합니다.

d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //디폴트 재생율을 이용합니다. (모니터의 화면 주사율)

 

PresentationInterval은 시연 간격으로 일반적으로 IMMEDIATE(즉시시연)하거나 DEFAULT(재생율)로 합니다.

PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

//DEFAULT로 할 경우 모니터의 주사율에 따라 알아서 정해집니다.

 

D3DPRESENT_PARAMETERS의 값을 채운 뒤에는 새로운 메서드를 이용해 IDirect3DDevice9 객체를 만들 수 있습니다.

m_p3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, Vp, &d3dpp, &m_p3Device); 

//m_p3D 는 LPDIRECT3D9 (IDirect3D9 컴객체) 을 인스턴스한 것입니다. 

첫번째 원소는 Adapter로 디스플레이어 어댑터를 지정합니다. DEFAULT는 기본 장치

두번째 원소는 DeviceType으로 이용할 장치 타입을 지정합니다. REF도 있지만 여기서는 HAL을 지정하겠습니다.

세번째 원소는 hFocusWindow입니다. 장치가 드로잉할 윈도우의 핸들을 넘겨주면 됩니다.

네번째 원소는 BehaviorFlags로 버텍스 프로세싱 타입을 지정하시면 됩니다. 미리 만들어둔 Vp를 여기서 사용합니다.

다섯번째 원소는 pPresentationParameters 는 미리 초기화해둔 D3DPRESENT_PARAMETERS 인스턴스를 지정합니다.

마지막 원소로  ppReturnedDeviceInterface가 있습니다. 생성된 장치를 리턴함으로

미리 LPDIRECT3DDEVICE9을 인스턴스한 m_p3Devie를 지정합니다.

CreateDevice 는 HRESULT를 리턴함으로 FAILED 매크로를 이용하여 성공 실패를 알릴수도 있습니다.

 

if(FAILED(m_p3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, Vp, &d3dpp, &m_p3Device)))

{

MessageBox(g_hWnd, L"디바이스 장치 생성 실패", L"SYSTEM ERROR", MB_OK);

}




[출처] Device 초기화 |작성자 서버

반응형

'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글

글자 출력  (0) 2013.01.04
D3DLIGHT9 광원  (0) 2013.01.02
D3D 에서의 HRESULT 값의 의미  (0) 2012.12.30
FPS 와 프레임 즉시 렌더링  (0) 2012.12.27
renderState를 쉽게 조작하기 IDirect3DStateBlock9  (0) 2012.12.22
반응형

http://blog.naver.com/maelblood/20161497755



Direct에서 Com 객체를 사용하다 보니 HRESULT를 사용하게 되었다.


HRESULT : 32bit signed 정수형이다.


HRESULT는 반환형 중 하나이다.


COM규정에 의한 것은 아니지만 COM Interface에 소속된 대부분의 함수들은   HRESULT의 반환값을 가진다.

이렇게 대부분  COM Interface에 소속된 함수들이 반환형으로 HRESULT를 사용함으로 클라이언트에게 일관성 있는

함수의 정보를 전달할 수 있게 된다.


HRESULT의 원래 목적은 공식적으로 OS/ 2 운영 체제의 여러 하위 시스템에 오류 코드간의 충돌을 방지하기 위해 

내부공개와 MS 모두 사용하기 위해 오류 코드의 범위를 배치하는 것이었다.


HRESULT내에는 에러코드의 본형과 출저에 대한 다양한 비트정보를 가지고 있다.(보통 COM 프로그래밍)


사용방법은 bool형의 true / false 똑같이 SUCCEEDED/FAILED를 사용한다.

bool형과 차이점이 있다면 굳이 리턴 값을 받지 않아도 되는 것이 다른 점이다.


Device초기화 하려고 GetDeviceCaps 함수로 장치 가져오기를 할때


if(FAILED(P3D->GetDeviceCaps(.....)))

{

MessageBox(L"장치 가져오기 실패!!");

return E_FAIL;

}

return S_OK;

이런식으로 사용이 가능 합니다.


디바이스 장치 가져오기가 실패를 하면 메시지를 출력하게 한 것인데 디버깅이 편리합니다.

(HRESULT 함수를 사용하는 이유는 디버깅이 용이하기 때문)


주의할 점

bool형은  true/ false 가 1/0 이지만 HRESULT의 SUCCEEDED/FAILED는 0/1의 값을 가지고 있는 점이 다른 점입니다.


HRESULT  의 구조


 Bit

 0

 1

 2

 3

 4

 5

 6

 7

 8

 9

 10

 12

 13

 14

 15

   ->

 Field

 Code


 Bit

 16

 17

 18

 19

 20

 21

 22

 23

 24

 25

 26

 27

 28

 29

 30

 31

 Field

 Facility

 X

 N

 V



 Field

 설명

 S

 Severity - 함수의 성공과 실패를 알려준다.

 (return : 0 - 성공과 실패를 알려준다.) 

 R

 실별코드의 예약부분

 (return : 1 - 실패) 

 C

 Customer - 그 값이 사용자 정의 인지 아닌지 식별하는 비트

 (return : 1 - 사용자 정의)

 N

 식별코드의 예약부분, 상태값 발견을 위해 쓰인다.

 X

 식별코드의 예약부분

 Facility

 에러를 담당하는 시스템 서비스를 알려준다. 식별 코드는 아래와 같다.

  ① RPC ② Dispatch ③ Storage ④ ITF ⑤ ⑥ ⑦ Win32 ⑧ windows ⑨ SSPI ⑩ Control ⑪ CERT

 Code

  Facility의 상태 코드


HRESULT의 상태 정보 요약


 S_OK

 때때로 Boolean TRUE 값(0x00)으로 S_FALSE와 함께 사용되며 함수가 성공하였음을 의미 한다.

 NOERROR

 S_OK와 동일한 의미 이다.

 S_FALSE

 S_OK와 반대로 Boolean FALSE 값(0x01)으로 함수가 실패 했음을 의미 한다.

 E_OUTOFMEMORY

 필요한 메모리를 할당할 수 없음 

 E_NOTIMPL

 멤버 함수에 구현 코드가 포함되어 있지 않다.

 E_UNEXPRCTED

 치명적인 실패를 의미한다.

 E_INVALIDARG

 하나 혹은 그 이상의 인자가 타당하지 않음

 E_NOINTERFACE

 요청한 인터페이스를 지원하지 않음

 E_POINTER

 타당하지 않은 포인터

 E_HANDLE

 타당하지 않은 처리

 E_ABORT

 작동 중지

 E_FAIL

 특정하지 않은 실패

 E_ACCESSDENIED

 일반적인 접근이 금지된 에러




LRESULT : long타입, Win32 환경에서 메시지 처리를 마친 후 OS에게 신호를 주기 위한 값


LRESULT는 long 변수의 다른 이름일 뿐이다. long 이라는 리턴값을 쓰지 않고 LRESULT라고 

재 선언한 것은 이 값이 리턴 값임을 좀 더 명확히 나타내기 위한 것이다.

Win32 API에서 CALLBACK함수 앞에는 LRESULT가 반환된다.


LRESULT CALLBACK WndProc(HWND hwnd, UINT iMessage, WPARAM wParam,.....)

{

....

}


LRESULT의 반환값은 무엇일까?


LRESULT는 long 타입형으로 Win32 환경에서 메시지 처리를 마친후 O/S 에게 어떤 신호를 주기위해 사용되는 값이다.

각각의 메시지 case에 대한 처리 값이 때로는 단순히 -1, 0, 1 등으로 어떤 때는 비트 플래그로 O/S 가 알수 있게 설정한다.

또는 포인터를 캐스팅해서 반환하기도 한다. 이는 포인터가 4Byte이기 가능하다. 윈도우 프로그램에서는 LRESULT값으로

객체의 포인터를 반환하는 것을 볼 수있다.


0을 리턴하면 OS는 더이상 메시지에 대한 처리를 하지 않고 프로그래머가 직접 처리한다는 의미를 갖는다.


-1을 반환할때도 있는대 이 경우 O/S가 진행하던 작업을 취소시키는 의미를 갖는다.

[출처] HRESULT / LRESULT |작성자 살발해

반응형
반응형


http://creaty.net/game/?menu=OpenFM&bid=3&mod=view&post=9



내용 :

 안녕하세요~ 

제가 간단한 게임을 만들고 있는데요 제가 만든 컴퓨터에서는 속도가 적당한데 

다른 컴퓨터에서 하면 엄청 빠르거든요. 그래서 이것저것 뒤져보다가 

프레임 동기화라는 것을 보았습니다. 그래서 검색도 해봤는데 원하는 답이 없어서요 

어떻게 적용시켜야되는건지 감이 잡히지가 않아서요. 

FPS 값을 구해서 이것으로 어떻게하는건가요? 

조언좀 부탁드립니다 ㅠㅠ

이 글은 GPG스터디와 연결된 글입니다. - [Gpg Study 원문보기]


D3DPRESENT_PARAMETERS 구조체를 설정하셔야 합니다.
내용 :

D3DPRESENT_PARAMETERS 구조체의 PresentationInterval 를 어떻게 설정하느냐에 따라 프레임이 천차만별로 달라질 수 있습니다.

보통 사용하는 플래그는 3종류가 있는데, 그것들은 다음과 같습니다.

 

D3DPRESENT_INTERVAL_DEFAULT : DirectX가 적절한 값을 선택하여 렌더링간격을 조절한다.

D3DPRESENT_INTERVAL_IMMEDIATE  : 기다리지 않고, 항상 렌더링한다. (프레임 무제한)

D3DPRESENT_INTERVAL_ONE  : 모니터 갱신이 1번 이루어지는 시간에 렌더링 간격을 맞춘다.


 

만약 프레임이 아니라, 이동에 관한 내용이셨다면 각 프레임간의 시간차이를 이용해 이동거리를 보간해주셔야 합니다.

 

// 시간지정

static time_t before_time = timeGetTime(); // 시간값 초기화

time_t now_time = timeGetTime(); // 현재시간

// 시간차이를 구한다.

time_t tick = timeGetTime() - before_time;

 

// 이동거리 계산 : 가장 간단하게 보간하는 방법은 시간값을 곱하는 것입니다.

position = position + move * tick / 1000.0f;

// 일반적으로 1초에 move 만큼 움직이기위해 1000을 나눠줍니다. 이것은 timeGetTime 함수의 해상도 때문

 

// 마지막으로 현재 프래임의 시간을 저장하고, 다음 프레임에 이용한다.

before_time = now_time;


반응형
반응형
http://blog.naver.com/dlqudgml81/50119354700


IDirect3DStateBlock9
기능 - 렌더링 스테이트를 캡슐화
다른 기능을 제외하더도 렌더링 스테이트를 제대로 관리 안하고 있을시에 초기로 돌리기에 아주 편했다.
사용법은 SDK를 참조하자!
 
ex ) 간단히 현재 렌더링 스테이트를 저장하고 초기화 하는 방법
1. CreateStateBlock ( ); // 생성한다.
2. IDirect3DStateBlock9 ->Capture();를해주면 이후에 모든 렌더링 스테이트를 저장한다.
3. IDirect3DStateBlock9 ->Apply(); 초기로 돌려준다.





http://diefish.egloos.com/10099055

DirectX에서 재공해주는 IDirect3DStateBlock9 를 이용하면
D3D렌더링 옵션정보를 잠시 기억했다가 다시 원복시켜주고 싶은 시점에서 전상태로 돌려주도록 할수 있다.


// 첫번째 파라미터 관련
typedef enum _D3DSTATEBLOCKTYPE
{
    D3DSBT_ALL                    = 1,          // capture all state
    D3DSBT_PIXELSTATE       = 2,         // capture pixel state
    D3DSBT_VERTEXSTATE   = 3,          // capture vertex state
    D3DSBT_FORCE_DWORD   = 0x7fffffff,
} D3DSTATEBLOCKTYPE;




[사용예]

// IDirect3DStateBlock9의 초기화 관련
IDirect3DStateBlock9* pStateBlock = NULL;
pd3dDevice->CreateStateBlock( D3DSBT_ALL, &pStateBlock );



g_pStateBlock->Capture();    // 현재 설정을 기억
    // <-- 이부분에서 다른 설정으로 랜더링

g_pStateBlock->Apply();       // Capture()를 호출했던 시점의 상태로 원복



http://gigaboy.egloos.com/10734021


IDirect3DStateBlock9를 사용한 렌더상태 조작 D3D
by gigaboy 2011/06/28 14:32 gigaboy.egloos.com/10734021 



IDirect3DStateBlock9* pStateBlock = NULL;
gd3dDevice->CreateStateBlock( D3DSBT_ALL, &pStateBlock );  // 프로그램 생성할 때 초기화



// 변경되는 렌더 스테이트 BeginStateBlock, EndStateBlock 사이에 입력.
gd3dDevice->BeginStateBlock(); 

gd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );  // 와이어 프레임.

gd3dDevice->EndStateBlock( &pStateBlock ); // pStateBlock에 상태들이 기록되어 있다.


gd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );  // 솔리드로 그리고 싶다.

drawObjectA(); // 솔리드로 그려진다.


pStateBlock->Apply(); // 이전에 기억해 두었던 렌더 상태로 되돌린다.

drawObjectB(); // 와이어 프레임으로 그려진다.
drawObjectC();

pStateBlock->Release(); // 프로그램 종료시 해제




구와 기둥은 WIRE 로 그려지고 있지만 바닥은 SOLID로 그려지고 있다.



 가능하면 렌더 상태들을 FX 안에서 사용하는게 편한것 같다.







반응형
반응형
http://goo.gl/JeVjN

출처 : GPG

소프트 파티클이란?

소프트 파티클을 만들어주는 기술의 정확한 명칭은 Depth bias blend이다.

Depth bias blend는 스프라이트 텍스처에 가상적인 두께를 만들어서 그 두께 정보가 무엇인가와 교차하면 교차하는 객체나 표면의 픽셀의 색과 그 스프라이트 텍스처의 교차되는 부분의 픽셀 색의 최대 근사값을 구해 교차하는 부분의 파티클 픽셀의 색을 보간하는 연산을 통해 교차선을 부드럽게 만들어주어 칼날과 같은 날카로운 교차선이 나타나지 않게 하는 기법이다.

이것을 스프라이트 기반의 Emitter파티클에 사용할 시에 소프트 파티클이라고 불리게 되는 것이며 활용되는 부분은 파티클뿐만이 아니라 여러 부분에 사용할 수 있다.

기존의 게임들에서 화염, 폭포수, 연기와 같은 파티클이 화면상의 다른 3D 객체나 월드 표면과 교차하면 그 칼날과 같은 교차선이 강하게 드러나는 매우 부자연스러웠던 연출을 본적이 때때로 있을것이다.

불꽃이나 탄피같은 파티클은 매우 작은 폴리곤 덩어리들에 알파값을 준 텍스처를 사용해 표현하기 때문에 다른 면과 교차해도 교차선같은게 드러나는 일이 없지만 자욱한 연기나 뿜어져 나오는 화염, 또는 사방으로 튀기는 물방울이나 폭포수와 같은 Emitter 파티클은 그 파티클의 모양을 그린 텍스처를 앏은 사각형 텍스처에 붙인 포인트 스프라이트 를 여러개를 사용해 만들어내는 것이기 때문에 다른 면과 교차한다면 그 교차선이 강하게 드러나게 된다.

이 기술의 알고리즘은 오래전부터 구상되었었고 사용되어 왔지만 그 명칭이 불분명하였다. 예를 들어 Infinity Ward의 2005년작 Call of Duty 2는 이 기술을 옵션에서 Zfeather Smoke라는 이름으로 명명하였고 어떤 게임들에선 종종 소프트 엣지 (Soft Edge)라는 이름으로 불리기도 한다. 이번에 MS에서 DX10 D3D 10 기술표를 내 놓으면서 거기에 기본적으로 포함된것중 하나가 이 기법인데 거기서는 소프트 파티클이란 이름으로 정의하고 있으며 최근의 게임이나 엔진들도 소프트 파티클이란 이름을 사용하고 있어서 소프트 파티클이란 이름으로 굳어지고 있다.

아래의 스크린샷들은 Capcom사의 Lost Planet의 게임 화면으로 위의 것은 소프트 파티클 처리가 되지 않은 스크린샷이고 아래의 것은 소프트 파티클 처리가 되어 있는 스크린샷이다. 서로 대조하여 그 교차선이 드러나고 안드러나고의 차이가 극명하게 드러난다.

화염 파티클 (스프라이트 텍스처)이 몬스터나 오브젝트, 벽, 바닥, 천장 등에 교차하여 그 교차선이 강하게 드러나고 있다.

소프트 파티클 처리가 되어서 화염 파티클 (스프라이트 텍스처)이 표면과 교차되는 부분의 픽셀의 색이 교차되는 표면 부분의 텍스처 색과 중간으로 보간되어 그 교차선이 마치 없는것처럼 부드럽게 보인다.

이 Depth bias blend처리를 물가의 부드러운 교차선 처리 (이것을 잘 활용한 예로는 2006년에 출시한 Ubisoft의 Splinter Cell: Double Agent가 있으며 곧 출시 예정인 Crysis에서도 구현)에 사용하는 것도 가능하며 특히 디자이너가 응용하기에 따라서 기존에 표현하기 힘들었던 것들을 부드럽게 표현 가능하다.

기본의 Depth bias blend처리를 하지 않은 상태에선 스프라이트 텍스처를 여러장을 사용해서 서로 겹치지 않게 정렬하면 자욱한 연기따위는 만들수 있었지만 어느 방향에서 바라보아도 입체적인 연기나 구름따위를 만들려면 그 스프라이트 텍스처들이 서로 교차해야하기 때문에 교차선이 드러나서 만들어도 비정상적인 모습으로 보이게되어 제대로 된 표현이 불가능 했었다.

Depth bias blend처리를 하고 스프라이트 텍스처를 여러장을 사용하여 서로 교차시키면서 입체감이 있게 구성한다면 볼륨감이 있는 연기, 혹은 구름 등을 만들어 낼수 있게 된다. 이것은 Volumetric Particles (볼류메트릭 파티클)이라고 불리기도 하는데 볼류메트릭 파티클이란 기법은 사실은 별도로 존재하는 것이 아니며 소프트 파티클을 6방향면체 혹은 그 이상으로 둘러싼 것에 불과하다.

이것을 응용하면 볼류메트릭 파티클에다가 광원과 음영처리도 보다 자유롭게 사용이 가능 하다. 왜냐하면 교차선이 드러나지 않고 부드럽게 보간되어 자연스러운 음영처리가 가능해지기 때문이다. 이를 응용하면 광원이 반사되는 연기, 햇빛이 반사되거나 투과되는 구름, 구름 아래로 뻗어나오는 구름 등의 그림자 등이 구현 가능하다.

그리고 이 Depth bias blend기법을 사용해서 안개속이나 수중에서의 부드럽게 보간되는 빛의 변화 (이것을 잘 활용한 예로 역시 2006년에 출시한 Ubisoft의 Splinter Cell: Double Agent가 있으며 앞으로 출시될 Crysis에서도 구현)가 표현이 가능하다.

이 기법들은 DX10의 D3D 10에 예제로 포함된 것들이며 복잡한 응용 단계는 DX9급 이상은 되야 가능하지만 기본적인 보간법 (위의 스크린샷에서 소프트 파티클 처리) 구현자체는 DX7 이하급의 고정 파이프라인 상으로도 구현이 가능한 매우 단순한 기술이다.

소프트 파티클을 최초로 구현해 출시한 게임은 2005년에 출시한 Ubisoft의 Splinter Cell: Chaos Theory이며 같은 해에 출시한 Call of Duty 2가 있었고 이후 게임들에선 거의 기본적으로 채용하고 있다.

최근에 발매된 게임들은 이와 같은 소프트 파티클 처리는 기본적으로 지원하는 단계에 이르렀다.

이를 응용해 볼류메트릭 파티클이나 음영 처리 등의 더 복잡한 기법들의 사용도 언리얼 엔진 3와 같은 최신의 게임 엔진들이라면 모두 지원하고 있는 기술들이다.


반응형
반응형

HRESULT h0 =D3DERR_NOTFOUND                ;                    //-2005530522

HRESULT h1 =D3DERR_MOREDATA                ;                    //-2005530521

HRESULT h2 =D3DERR_DEVICELOST              ;                    //-2005530520

HRESULT h3 =D3DERR_DEVICENOTRESET      ;                    //-2005530519

HRESULT h4 =D3DERR_NOTAVAILABLE          ;                    //-2005530518

HRESULT h5 =D3DERR_OUTOFVIDEOMEMORY;                    //-2005532292

HRESULT h6 =D3DERR_INVALIDDEVICE          ;                    //-2005530517

HRESULT h7 =D3DERR_INVALIDCALL             ;                   //-2005530516

HRESULT h8 =D3DERR_DRIVERINVALIDCALL ;                    //-2005530515

HRESULT h9 =D3DERR_WASSTILLDRAWING  ;                   //-2005532132

HRESULT h10 =D3DOK_NOAUTOGEN                ;                 //141953135                        양수





반응형
반응형


http://www.gpgstudy.com/gpgiki/D3D%20%EB%94%94%EB%B0%94%EC%9D%B4%EC%8A%A4%20%EC%86%8C%EC%8B%A4%20%EC%B2%98%EB%A6%AC




D3D 디바이스 소실 처리


이 페이지는 http://www.gpgstudy.com/forum/viewtopic.php?topic=1451 에 올라온 '과객' 님의 글에 기초한 것입니다. 수정, 보충 가능(1 인칭 언급을 제거하는 것도 포함해서요)

외부에서 링크를 걸 때 한글 관련 문제가 있다면 http://www.gpgstudy.com/gpgiki/DxDeviceLostHandling 를 사용하세요.

참여한 분들: 과객, ...

디바이스 소실의 두가지 경우

1. 디바이스 소실되었고 복구 불가능의 경우

: 이 경우에는 대책이 없다. 전부(IDirect3DDevice를 통해 생성된 모든 리소스들과 IDirect3DDeivce객체) 해제한 후 처음부터 다시 생성한다.

2. 디바이스 소실되었고 복구 가능의 경우

: 이 경우에는 디바이스에 올라간 리소스(리소스 생성시 D3DPOOL_DEFAULT 플래그를 이용하여 생성된 객체들)들만 새로 로딩하면 된다.

특이사항

디바이스가 소실되어도 IDirect3DDevice관련 함수들이 성공을 반환 할 경우가 있다.

도움말에 보면 "디바이스가 소실되어도 동작은 보증된다"고 되어있다. 물론 이때의 동작은 헛동작이다. 아무 효과가 없는것이다. 왜 이런식인가 생각해보니, 밑의 글을 읽어보면 알겠지만,, 언제 어떻게 디바이스 손실이 발생할지 모르니 프로그래머로써는 이런 상황을 대처 할 수 없는것이다. 디바이스와 관련된 모든 함수들에 대해서, 리턴값을 체크하지 않는한 불가능하다는 얘기이다. 그리고 손실된 디바이스 자원이 언제 넘어오게 될지도 모르는 상황에서 이런 처리는 너무 고난이도일껏 같다. 차라리 처리되는것 처럼 보이고, 실제로는 처리가 안되게 하는것이 훨씬 이득일껏 같다. 어디까지 제 추측입니다. 틀렸어도 양해를..

왜 이딴게 있는걸까?

예를들면, 2개의 응용프로그램 A와 B가 돌아가는 상황에서, A란 놈과 B란 놈 둘다 비디오 램을 많이 사용하는 프로그램이었다 치자. 이 상황에서 A란 프로그램이 돌아가고 있는 상황이어서 비디오 램의 여유분이 없었다 치자, 자.. 이제 문제의 B가 실행되어 졌을 경우,, 어떻게 해야할까? Win32는 멀티 태스킹 환경이다. 고로 여러 응용프로그램들이 같은 하드웨어 자원을 공유한다. 즉, DOS처럼 하나의 응용프로그램이 하드웨어 자원을 독점하면 안된다는 것이다. 고로 윈도우즈가 택한방식이활성화 애플리케이션에게 자원을 넘겨주자는 방식이다. A가 활성화되면, A에게 자원을 주고, B가 활성화되면 B에게 자원을 준다. 그러므로 사용자는 두 응용프로그램을 동시에 사용할 수 있는것이다. 덕분에 프로그래머는 귀찮지만은... 어디까지 제 추측입니다. 틀렸어도 양해를.. 아니지 지적을..

디바이스 소실 처리

IDirect3DDevice::TestCooperativeLevel()을 호출하여, 디바이스를 복구 할 수 있는지 검사해본다. 반환값(HRESULT)이

  • D3DERR_DEVICELOST인 경우 디바이스가 소실되었고 아직 복구할 수 없는 상태이다. 복구할 수 있을때까지 대기한다.
  • D3DERR_DEVICENOTRESET인 경우 디바이스가 소실되지만 지금 복구할 수 있는 상태이다. 디바이스를 복구한다.

디바이스 복구

  1. . D3DPOOL_DEFAULT로 잡은 리소스들을 전부 릴리즈한다. %%%(안그러면 다음에 호출될 IDirect3DDevice::Reset()이 실패할것이다.)
  2. . IDirect3DDevice::Reset()을 호출한다. %%%(Reset()을 그냥 IDirect3DDevice의 복구명령어라 생각하면 이해가 편함)
  3. . 디바이스를 다시 셋팅한다.(랜더스테이트, 뷰 행렬등..)
  4. . D3DPOOL_DEFAULT로 잡은 리소스들을 다시 로드한다.

Adapter나 D3DDEVTYPE이 변경되어야 하는 경우에는 디바이스를 다시 생성해야 한다.

  1. . 모든 리소스들을 릴리즈한다.
  2. . 디바이스를 릴리즈한다.
  3. . 디바이스를 새로 생성한다.
  4. . 디바이스를 다시 셋팅한다.(랜더스테이트, 뷰 행렬등..)
  5. . 모든 리소스들을 다시 로드한다.

디바이스가 소실되는경우

풀스크린 모드일때..

  • 다른 애플리케이션이 디바이스를 점유하는 경우.
    • 애플리케이션이 작업표시줄로 최소화 되는 경우.
    • 다른 애플리케이션이 풀스크린 모드로 생성될경우.
  • 전력관리 이벤트(WM_POWERBROADCAST)가 발생했을 경우.

윈도우 모드일때..

  • 전력관리 이벤트가 발생했을 경우.
  • 다른 애플리케이션이 풀스크린 모드로 생성될경우.. (이경우 제 카드에서는 문제가 없었음)
  • 디스플레이 등록정보에서 색상모드를 변경하는 경우.

테스트 사항

카드 : Radeon 9000 128M, OS : Win 2000

A,B : D3D를 사용하는 애플리케이션

  1. . A:win, B:win ==> A:full, B:win // (A를 풀스크린으로 전환) %%%-A:ok, B:ok
  2. . A:full, B:win ===> A:win B:win // (A를 윈도우모드로 전환) %%%- A:ok, B:lost(고칠수 있음)
  3. . A:full, B:win ===> A:full(minimize), B:win // (마우스로 바탕화면을 찍거나 Alt+Tab) %%%- A:lost(고칠수 없음), B:lost(고칠수 없음)
  4. . A:full(lost), B:win ===> A:full(lost), B:full // (B를 풀스크린으로 전환) %%%- A:lost상태 유지, B:ok (A는 시작하기 전에 이미 lost상태였음)
  5. . A:full(lost), B:full ===> A:full(lost), B:full(lost) // (바탕화면 찍음) %%%- A:(lost상태유지), B:lost(고칠수 없음) (A는 시작전에 이미 lost상태였음)
  6. . A:full, B:win ===> A:종료, B:win(lost) // (A를 종료) %%%- A:종료됨, B:lost(고칠수 있음)

X. 기타 등등, 여러 상황에 따라 디바이스 로스트가 발생 된다. 이런 상황이 더 있으나 해결책을 어느정도 찾은것 같으므로 더 이상은 생략.

X. 그리고 다른 그래픽 카드의경우는 어떻게 처리될지 잘모르겠음.

결론

1. Present()함수의 리턴값은 항상 체크해야 한다. 위와 같이 언제 디바이스 손실이 발생 할지 모른다.

2. 임의로 체크해 보고 싶은 경우. TestCooperativeLevel()함수를 이용하자.

방법론

필수사항 : Present()리턴값은 항상 반드시 꼭 체크하자. 언제 어떻게 어떤 이유로 Present()가 실패할지 모른다. 이건 필수이다.

그리고 Present()가 실패하면 위와같은 방법으로 복구하면 될꺼 같다.

0. Present()함수 실패시만 복원한다.

단점으로는 에러를 알아내는 시점이 Present()가 호출될때(뷰포트를 하나 생성한 경우라면 한프레임에 한번씩)뿐 이라는 것이다. 이 단점은 랜더링 결과물에 접근하여, 그것이 애플리케이션 로직에 적용되는 경우라면 치명적일 수 있다고 예상된다. 그점을 제외하면 가장 무난할 껏 같다.

1. CD3DApplication(Direct3D Wizzard에서 제공)의 방식

이 클래스를 보면,, 꽤나 복잡한 방식(주로 윈도우 메세지를 핸들링한다.)으로 처리 하는데(즉, 디바이스 손실이 일어나기전에 미치 처리함)으로 해결하고 있다. 꼭이렇게 까지 해야 하는지는 잘모르겠지만... 요는 여러가지 상황에 미리 대처한다는 방식이다. 위의 <테스트 사항>같은 짓을 많이 시도해보고, 어느때 디바이스가 손실되는지 정확하게 알아낸 후, 미리알 수 있는경우(풀스크린에서 Alt+tab에 의해 갑자기 비활성화 시킨다든지 등등) 할수 있는데까지 까지 하는것이다. 그런 눈물겨운 노력이 CD3DApplication에 보면 잘 나온다. 이런건 보고 베끼자...^^ 이경우 100% 문제를 해결했다고 볼 수는 없다고 생각되지만 0번의 경우보단 낫다. 이런 문제를 봐선 Direct3D의 설계의 결함같기도 하다. 결국 이런 문제들을 100% 해결 할 수는 없다고 생각된다.

결과 : 실제로 1번과 같이 대부분 예측되는 치명 적인 몇몇 가지들에 대해 미리 알아내서 처리해주면,, 거의 문제는 안생긴다. 대신 코딩이 지저분해지는건 어쩔수 없다.

stub code

void RenderAll()
{
    // ...
    // 모든 그래픽들에 대한 랜더링을 한다.
    // ...

    // 백버퍼 플리핑.
    hr = m_pDevice->Present( NULL, NULL, NULL, NULL );
    if ( FAILED(hr) )
    {
        if ( D3DERR_DEVICELOST == hr )
        {
            // 디바이스를 소실했고, 복구가 불가능 상태
        }
        else ( D3DERR_DEVICENOTRESET == hr )
        {
            // 디바이스를 소실했지만, 복구가 가능한경우.
        }
    }
}

설계

한가지 방법은 랜더러 클래스(또는 이런 이벤트를 처리할 객체)에 두가지상황(디바이스 손실시 복구가능/복구불가능)이 발생했을때, 로딩할 목록을 등록해 놓은 후, 이벤트가 발생하면 각각 해당 이벤트에 맞게끔 다시 로드하는 식으로, 구성하면 될 껏 같다.

//**** 디바이스 리소스 인터페이스.. // 디바이스 의존적인 리소스들의 추상클래스. struct IDeviceRes { virtual void Invalidate() = 0; virtual bool SetValidate() = 0; }; //**** 텍스쳐 클래스 class CTextureRes : public IDeviceRes { public: virtual void Invalidate() { 텍스쳐 해제; } virtual bool SetValidate() { 텍스쳐 다시 로드; } bool Load(); void Unload(); protected: char m_szFileName[256]; LPDIRECT3DTEXTURE9 m_pTexture; }; //**** 텍스쳐를 관리할 클래스(클라이언트에서 접근하여 사용) class CDataContainer { public: LoadTexture( const char* szFileName ) { // 1. 텍스쳐 로딩 // 2. 만약 텍스쳐가 VRam에 잡혔다면..(D3DPOOL_DEFAULT) // 2.1 랜더러의 의 VRam리스트에 등록(m_pRenderer->m_VRamRes) // 3. 텍스쳐가 다른모드로 생성되었다면..(D3DPOOL_MANAGED or etc..) // 3.1 랜더러의 의 Managed리스트에 등록(m_pRenderer->m_ManagedRes) } UnloadTexture( const char* szFileName ) { // 랜더러의 디바이스 목록에서 지운다. m_pRenderer->Unregist( szFileName ); } protected: vector<CTextureRes*> m_TextureContainer; CRenderer* m_pRenderer; } //**** 문제의 랜더러 클래스 class CRenderer { public: // 디바이스가 해제 &#46124;거나 해제 하라. // - 이 함수는 외부에서 임의로 호출이 가능하다. void InvalidateDevice( HRESULT hrDeviceState ) { if ( FAILED( hrDeviceState ) { if ( D3DERR_DEVICENOTRESET == hrDeviceState ) { // 1. m_VRamRes 리소스만 해제한다. // for_each(m_VRamRes의 시작에서 끝까지) { m_VRamRes[i]->Invalidate(); } } else if ( D3DERR_DEVICELOST == hrDeviceState ) { // 1. m_VRamRes과 m_ManagedRes들에 대해서 해제한다.(전 리소스들에 대해 수행) // for_each(m_VRamRes의 시작에서 끝까지) { m_VRamRes[i]->Invalidate(); } // for_each(m_ManagedRes의 시작에서 끝가지) { m_ManagedRes[i]->Invalidate(); } // 2. 디바이스를 릴리즈한다. } } m_hrDeviceState = hrDeviceState; // 디바이스 상태값 업데이트 } // 디바이스가 활성화하라. // - 이 함수도 외부에서 임의로 호출이 가능하다. bool SetValidateDevice() { if ( FAILED(m_hrDeviceState) ) { if ( D3DERR_DEVICENOTRESET == m_hrDeviceState ) { //**** 디바이스를 복구할수 있다. // 0. D3DPOOL_DEFAULT로 생성된 자원들 모두 해제 (이 문장은 포스팅하면서 추가) // 1. IDrect3DDevice::Reset()한다. // 2. 랜더 스테이트 / 뷰행렬 셋팅 // 3. m_VRamRes 리소스들을 다시 로딩한다. // for_each(m_VRamRes의 시작에서 끝까지) { m_VRamRes[i]->SetValidate(); } } else if ( D3DERR_DEVICELOST == m_hrDeviceState ) { //**** m_VRamRes 복구할수 없다. // 0. D3DPOOL_DEFAULT / D3DPOOL_MANAGED 리소스 해제(이 문장은 포스팅하면서 추가) // 1. 디바이스를 재생성한다. // 2. 랜더 스테이트 / 뷰행렬 셋팅 // 3. m_VRamRes / m_ManagedRes 리소스를 로딩한다. // for_each(m_VRamRes의 시작에서 끝까지) { m_VRamRes[i]->SetValidate(); } // for_each(m_ManagedRes의 시작에서 끝가지) { m_ManagedRes[i]->SetValidate(); } } // 검증해본다. m_hrDeviceState = m_pDevice->TestCooperativeLevel(); return SUCCEEDED(m_hrDeviceState); } return true; } // 랜더링한다. void RenderAll() { //**** 디바이스가 유효한 상태가 아니라면 그냥 리턴. if ( FAILED(m_hrDeviceState) ) return; // ... //**** 모든 그래픽들에 대한 랜더링을 한다. // ... //**** 백버퍼 플리핑. m_hrDeviceState = m_pDevice->Present( NULL, NULL, NULL, NULL ); if ( FAILED(m_hrDeviceState) ) { // 디바이스에 뭔가 이상이 있다면,, InvalidateDevice( m_hrDeviceState ); // 외부에 알려준다. 아마 누군가에게 알려줄 필요가 있을껏이다. // CApp나 혹은 다른 누군가에게.. } } protected: //**** properties // 디바이스 의존적인 메모리 관리 vector<IDeviceResource*> m_VRamRes; // POOL_DEFAULT vector<IDeviceResource*> m_ManagedRes; // MANAGED or etc HRESULT m_hrDeviceState; // 현재의 디바이스 상태값 LPDIRECT3DDEVICE9 m_pDevice; };

추신

괜찮은 방법이나, 사용되어지는 방법이 있으면 올려주세요. 저도 구현은 안해본 사람입니다. 아마 틀린 부분도 있으리라 생각됩니다. 많은 지적을.. 써놓고 보니 장문이네요.

< 덧글 >

그리고 업데이트 내용입니다. gpgstudy.com의 손님께서 쓰신글의 요약입니다.

TestCooperativeLevel()로 D3DERR_DEVICENOTRESET임을 확인한후 Reset()을 했을때 실패할 수도 있다는군요.

나중에 TestCooperativeLevel()로 확인해 보니 D3DERR_DEVICELOST였다고 합니다. 결국 Reset()이 실패했을경우에도 다시 체크를 한후 소실상태라면 디바이스를 다시 생성해야 할껏같습니다.

반응형
반응형


복사http://blog.naver.com/cra2yboy/90139675513


첨부파일 (1)

환경맵이란 무엇인가?

 

 

환경 맵핑이란 반사성이 있는 표면에 레이 트레이싱을 하지 않고 주변이 반사되는 듯 시뮬레이션하는 방법이다.

실제와 같은 반사를 위한 광선 추적 기법은 비용이 크기 때문에 환경맵을 통해 이와 비슷한 효과를 내는 것이다.

 

다양한 형태의 큐브맵

 

 

 

이 예제에서는 CreateCubeTexture 함수를 이용해 큐브 텍스쳐를 생성한다.

 

텍스쳐 좌표를 처리하기 위한 인자들

 

D3DTSS_TCI_PASSTHRU 는 정점에 주어진 텍스쳐 좌표를 그대로 사용

D3DTSS_TCI_CAMERASPACENORMAL 는 정점의 법선 정보를 카메라의 공간좌표로 변환 한 뒤 텍스쳐 변환 행렬 적용 후 텍스쳐 좌표로 사용(환경 맵핑)

D3DTSS_TCI_CAMERASPACEPOSITION 는 정점의 위치를 카메라 공간좌표로 변환한 뒤 텍스쳐 변환행렬 적용 후 텍스쳐 좌표로 사용(그림자 맵핑)

D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 는 정점의 위치와 법선을 카메라 공간좌표로 변호나한 뒤 시선에 대한 반사벡터를 구하여 텍스쳐 변환행렬 적용 후 텍스쳐 좌표로 사용(반사 환경 맵핑)

D3DTSS_TCI_SPHEREMAP는 구면 맵핑을 위한 텍스쳐 좌표를 사용(구면 맵핑)

 

큐브 환경맵 생성하기

 

큐브 환경맵을 생성하기 위해서 이 예제에서 처리한 방법은 카메라를 기준이 되는 위치에 옮겨 놓고 6 방향을 향하도록 카메라를 각각 돌아가며 텍스쳐에 화면을 렌더링하는 방식을 사용 했다.

 

단축키 'E'를 누르면 CreateCubeMap 함수를 호출하도록 되어 있고 이곳에서 큐브맵 텍스쳐를 생성 후 렌더링 하고 파일에 저장하는 역할을 한다.

 

렌더링

 

 

g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR | 1);

 

주전자에 텍스쳐를 맵핑하여 렌더링 해야 하는데 텍스쳐의 맵핑 좌표는 카메라 위치를 기준으로 매번 재계산하여 적용시켜 준다.

반응형
반응형



http://blog.naver.com/sorkelf/40157348191



이번엔 환경맵(큐브맵, Cube Map)을 알아보자


환경맵이란 모델 표면의 배경등이 비추는 모습을 재현한 것으로,필요한 소재들이나 텍스처들을 가리킨다. 

(흔히들 말하는 잘 닦은 금속이 비추는 모습) 같은거 그런거







 

① 눈 →모델 표면 반사→배경의 어딘가


우리들의 시선으로부터 한 물건의 어떤 지점에 광선을 쏜다고 생각하자

그러면 광선은 면에 입사하여 다시 반사한다.


반사한 후의 광선은 분명 어딘가 먼곳으로 가다가 반드시 어딘가에 충돌한다.

그 부딪힌곳에 적어도 무언가의 색이 반드시 있다.


이와는 반대로 그 부딪힌 곳에서부터 물건의 반사지점까지 광선을 쏜다고하자

그러면 레이는 표면에 반사해서 분명 우리들 눈에 다시 들어 온다.

이러한 원리로 인해 우리들은 표면의 색을 알 수 있다.

반사한 색을 보고 있음

 

그럼 이 부분을 셰이더에서 생각해보자


버텍스 셰이더에는 로컬 공간의 버텍스 좌표가 인수로써 들어온다.

이것에 월드 변환행렬을 곱하면 월드 공간으로 이동한다.


지금 카메의 월드 위치가 있다고 하고 그 위치로부터 월드 공간에 있는 버텍스에 대해서 레이를 쏜다.

이 레이의 방향이 [ 시선 벡터 ] 이다.


버텍스에는 이미 또 다른 [ 법선 (Normal) ] 이라는 정보도 들어 있다.

법선은 표면을 가리키는 것이는 것이므로 

우리는 시선벡터와 법선 벡터만 알면 반사벡터는 간단히 구할 수 있다.

그 다음엔 반사한 곳에 있는 배경색으로부터 색을 얻어오면 끝이다.


물론 셰이더 내에는 월드에 있는  어떤 모델의 정보를 알 수 없다

셰이더 내에서 얻을 수 있는 것은 색정보와 버텍스 컬러 그리고 입혀진 텍스처 만이기 때문이다.


여기서 생각할 수 있는 것이 [ 3D 공간에 세계는 커다란 입방체! ]다 라는 것이다.

그렇게 하면 배경의 색정보는 6면의 텍스처로 모두 표현될 수 있다



 

셰이더내에서 입방체라고 생각하면 그 모델(배경) 에 대한 정보를 셰이더내에 전달할 필요는없다

이 후에는 시선이 닿을 것이라는 커다란 텍스처의 UV를 직접 지정하여 그 색을 출력하면

모델의 표면에 주위의 색이 반사한 것 처럼 보일 것이다


이 입방체의 내측에 붙어있는 텍스처를 [ 환경 맵 ] 이라고 한다



② IDirect3DCubeTexture + reflect함수 사용하면 끝



또한 위 텍스처는 큐브맵이라고도 하며 이러한 6면의 텍스처를 IDirect3DTexture9를 6개 사용해서 표현할 수도 있지만 

DirectX에서는 큐브맵 전용 IDirect3DCubeTexture라는 인터페이스가 준비되어 있으며 이것을 사용하면 

간단히 큐브 환경맵을 만들수 있다


큐브맵은 보통 D3DXCreateCubeTextureFromFile 함수를 사용하여 불러온다


 HRESULT D3DXCreateCubeTextureFromFile(

    LPDIRECT3DDEVICE9            pDevice,
    LPCTSTR                             pSrcFile,
    LPDIRECT3DCUBETEXTURE9 *ppCubeTexture
);

pDevice는 렌더링 디바이스
pSrcFile 에는 큐브 맵이 들어간 파일명 (단 dds 포맷)。
ppCubeTexture 에 큐브맵 오브젝트의 포인터를 전달한다。


이 함수에서 사용할 수 있는 파일은 dds 포맷 파일이며 DirectX Texture Tool로 다른 파일들로부터 만들수도 있다.



이렇게 해서 만든 큐브맵 텍스처를 셰이더에 전달한다.


 // 환경 매핑 버텍스 셰이더

const char *vertexShaderStr =
float4x4 view : register(c0);          // 보통 WVP로 한번에 보냄
float4x4 proj : register(c4);
float4x4 world : register(c8);
float3 cameraPosW : register(c12); // 카메라 월드 위치

struct VS_IN {
    float3 pos : POSITION;
    float3 normal: NORMAL;
};

struct VS_OUT {
   float4 pos : POSITION;
   float3 normalW: TEXCOORD0; // 월드 좌표상의 법선
   float3 viewVecW: TEXCOORD1; // 월드 좌표상의 시선벡터
};

VS_OUT main( VS_IN In ) {
  VS_OUT Out;
  Out.pos = mul( float4(In.pos, 1.0f), world );
  Out.viewVecW = Out.pos.xyz - cameraPosW;
  Out.pos = mul( Out.pos, view );
  Out.pos = mul( Out.pos, proj );

  Out.normalW = mul( float4(In.normal, 0.0f), world );

  return Out;
}


// 환경 매핑용 픽셀 셰이더
const char *pixelShaderStr =
textureCUBE cubeTex;
samplerCUBE cubeTexSampler =
sampler_state {
  Texture = <cubeTex>;
  MinFilter = LINEAR;
  MagFilter = LINEAR;
  MipFilter = LINEAR;
};

struct VS_OUT {
  float3 normalW: TEXCOORD0;
  float3 viewVecW: TEXCOORD1;
};

float4 main( VS_OUT In ) : COLOR {
  float3 vReflect = reflect( In.viewVecW, In.normalW );
  return texCUBE(cubeTexSampler, vReflect);
}


대부분이 변수나 샘플러등의 선언이지 실제 셰이더 코드는 얼마 없다


특히 픽셀 셰이더는 달랑 2행 뿐이다.

이게 가능한 것은 셰이더 자체가 큐브맵 텍스처로부터 샘플링을 하는것을 지원해주기 때문이다


우선 큐브맵은 textureCUBE라는 텍스처 형으로 얻어진다

그리고 이 텍스처 전용 샘플러로 samplerCUBE를 지원한다


texCUBE 함수를 통해 samplerCUBE샘플러에 대해서 반사 벡터를 전달하면 

그 벡터에 맞는 큐브맵의 색을 얻어 반사벡터와 입방체의 교점을 구하고

그것을 UV로 변환하고 뭐하고뭐 하고 하는 여러가지 계산을 전부 생략 가능하다


그러면 반사 벡터는 어떻게 구하는가?


3D게임 프로그래밍 & 컴퓨터 그래픽을 위한 수학 1판 160쪽에 있는 (2판이 없어 제길..)




R = 2(N·L)N-L 을 사용해도 되지만

셰이더에서는 reflect라는 함수를 지원하며 (내부가 저렇게 되있긴 하지만..)

입사벡터와 면의 법선벡터로부터 시선벡터에 진행방향인 반사벡터를 구해준다


시선벡터는 카메라의 위치와 카메라가 보고 있는 점을 알수 있으면 구할수 있다

(월드좌표로 변한된 버텍스 위치 - 카메라의 월드 좌표상의 위치)


이것을 TEXCOORD1로 하여 법선벡터와 함께 픽셀 셰이더에 보낸다



③ 애플리케이션 프로그램


애플리케이션에서는 IDirect3DDevice9::SetTexture 함수로 큐브맵 텍스처를 전달하고

버텍스 셰이더와 픽셀 셰이더를 각각 렌더링 디바이스에 설정하고 렌더링 하면 된다


 // 카메라 갱신

D3DXVECTOR3 cameraPos(350.0f * cos(a*0.5f), 450.0f * sin(0.2f*a), 350.0f * sin(a*0.5f));

g_pD3DDev->SetTexture(0, cubeTex); // 큐브맵 세팅

g_pD3DDev->SetVertexShader(vertexShader);
g_pD3DDev->SetPixelShader(pixelShader);

g_pD3DDev->SetVertexShaderConstantF(0, (float*)&view, 4);   //보통 SetMatrix로 한번에 보냄
g_pD3DDev->SetVertexShaderConstantF(4, (float*)&proj, 4);
g_pD3DDev->SetVertexShaderConstantF(8, (float*)&world, 4);
g_pD3DDev->SetVertexShaderConstantF(12, (float*)&cameraPos, 4);

cube->DrawSubset(0);


어려울지도 모르지만 봐왔듯이 환경 매핑은 큐브맵만 있으면 의외로 간단하다

반응형
반응형

//Slices는 나누어질 삼각형의 갯수 이며 Stack은 사진에서 Y축으로 나누어질 갯수
 if( FAILED(D3DXCreateSphere(_pD3dDevice,5,8,4,&_sphere, NULL)) ){
   AfxMessageBox(L"스피어 생성 실패");
}

반응형

'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글

Direct3D9에서 큐브 환경맵 만들어 보기  (0) 2012.11.08
환경 맵(큐브 맵, Cube Map)  (0) 2012.11.08
투명처리와 알파 합성  (0) 2012.11.02
점 그리기 -크기 변환  (0) 2012.11.02
점그리기  (0) 2012.11.02
반응형

칼라키로 뺀다
  * 텍스쳐 생성시 칼러키를 지정하여 빼기

D3DCOLOR ColorKey = D3DCOLOR_XRGB(255,0,255);
D3DXCreateTextureFromFileEx( DXD9, 이름,  크기, 크기, 1, NULL,텍스쳐포맷, 메모리풀, 필터, 필터, ColorKey, NULL, NULL, 텍스쳐포인터);


픽셀에 투명값이 있다
  * 포토샵에서 저장시 알파채널을 포함해서 저장
  * TGA, PNG, DDS등의 포맷을 사용
  * SetRenderState에 알파를 사용한다는 옵션을 선택

m_pD3dD9->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3dD9->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_pD3dD9->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);



SetTextureStage에서 FACTOR로 투명도를 조절한다
  * 이미지가 가지고 있는 알파값에 다시 알파값을 조정할수 있다.
  * 픽셀칼러(RGB) * 픽셀알파값(100%로계산) * 원하는 알파값(100%로계산)

m_pD3dD9->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
m_pD3dD9->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pD3dD9->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
m_pD3dD9->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_ARGB( 원하는 알파값, 255, 255, 255 ) );



정점의 알파값을 사용한다
  * 정점의 칼라가 ARGB를 사용할경우 0xffffffff인데
  * 맨앞의 ff값을 수정해주면, 채워지는 face의알파도 영향을 받는다.
  * 픽셀칼러(RGB) * 픽셀알파값(100%로계산) * 정점알파값(100%로계산)

m_pD3dD9->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
m_pD3dD9->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

m_pD3dD9->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

 

 

 

 

 

 


http://www.silverwolf.co.kr/4886

 

 

[알파합성]

 

2번 렌더링을 실시하는 , 이른바 투패스 라고 부르는 방법으로 알파 합성(알파 블렌딩) 을 의미 알파 합성이란 폴리곤을 렌더링할때, 폴리곤 색을 그냥 출력하는 것이 아니라 이미 렌더링 된 화면에 여러가지 합성을 해서 출력하는 방법이다. 

알파합성은 현재 그려져 있는 색과 렌더링하는 폴리곤의 색을 합성한다. 따라서 , 반투명 폴리곤을 렌더링하기 전에 불투명 오브젝트를 렌더링 하여야 한다.   

깊이 테스트를 하면서 렌더링 할 경우 , 렌더링 순서를 잘못하면 반 투명 폴리곤의 한쪽 부분은 오브젝트가 렌더링 되지 않고, 마술처럼 오브젝트의 일부분이 사라진 화면이 출력되게 됨. 

------------------------------------------------------------------------------------- 

반투명 on : 디바이스->SetRenderState(D3DRS_ALPHABLENDABLE , TRUE); 
반투명 OFF : 디바이스->SetRenderState(D3DRS_ALPHABLENDABLE , FLASE); 

------------------------------------------------------------------------------------- 
합성 설정 방법 : 디바이스->SetRenderState(D3DRS_BLENDOP , 값) 

D3DBLENDOP_ADD 
                          최종색 = A * 렌더링할 폴리곤 색 + B * 이미 렌더링 된 색 

D3DBLENDOP_SUBTRACT 
                          최종색 = A * 렌더링할 폴리곤 색 - B * 이미 렌더링 된 색 

D3DBLENDOP_REVSUBTRACT 
                          최종색 = -A * 렌더링할 폴리곤 색 + B * 이미 렌더링 된 색 

D3DBELNDOP_MIN 
                         최종색 = 작은값(A * 렌더링할 폴리곤 색 , B * 이미 렌더링 된 색) 

D3DBELNDOP_MAX 
                         최종색 = 큰값(A * 렌더링할 폴리곤 색 , B * 이미 렌더링 된 색) 

-------------------------------------------------------------------------------------- 
아무 것도 설정되지 않았을때는 D3DBLENDOP_ADD 가 사용되며 , D3DBLENDOP_ADD 는 색을 서로 더한다. 

합성 강도 또한 SetRenderState 로 설정한다. 
이제부터 렌더링 하려는 폴리곤의 합성 강도 
디바이스->SetRenderState(D3DRS_SRCDBLEND , 값A) 

이미 렌더링 된 렌더일 타겟 색의 합성 강도 
디바이스->SetRenderState(D3DRS_DESTBLEND , 값B) 

--------------------------------------------------------------------------------------- 
<다양한 합성 방법> 

1. 선형 합성 

이른바 , 알파 합성이라 부르는 합성방법입니다. 이미 그려진 색과 지금부터 렌더링 하려고 하는 폴리곤의 색을 다음과 같은 비율로 합성합니다. 

최종색 = (1 - a) * 바닥색 * a * 덮일색. 

// 선형합성 C = Cd(1-As)+CsAs 
RS(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
RS(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 

--------------------------------------------------------------------------------------- 
덧셈 합성 

이합성은 바닥색의 변함없이 폴리곤의 색을 위에 겹칩니다. 

최종색 = 바닥색 + a * 덮일색 

a의 값이 커지는 것 만큼 , 위에 그려지는 폴리곤을 강하게 합성한다. 

RS(D3DRS_DESTBLEND, D3DBLEND_ONE); 
RS(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 

이상의 합성은 빛의 표현에 많이 사용, GLARE 효과. 

--------------------------------------------------------------------------------------- 

뺄셈 합성 

최종색 = 바닥색 - a* 덮일색 

// 뺄셈합성 C = Cd-CsAs 
RS(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); 
RS(D3DRS_DESTBLEND, D3DBLEND_ONE); 
RS(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 

이 합성 방법은 그림자 표현에 사용됨. 

뺄셈 합성을 하는 폴리곤을 여러번 거듭해나가면, 마지막에는 까맣게 된다. 
---------------------------------------------------------------------------------------- 
곱셈 합성 

최종색 = 바닥색 * 덮일색 

// 곱셈합성 C = Cd*Cs 
RS(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR); 
RS(D3DRS_SRCBLEND, D3DBLEND_ZERO); 
---------------------------------------------------------------------------------------- 

제곱 합성 

어두운곳은 더 어둡게 하고, 밝은 곳은 그대로 표시함. 이를 식으로 표현하면 다음과 같음. 

최종색 = 바닥색 * 바닥색 

바닥색을 제곱해서 색의 채도를 강조함. 제곱 합성은 렌더링 하는 폴리곤의 색이나 알파 값에 영향을 받지 않기 때문에, 폴리곤을 입혀 렌더링해도 텍스쳐는 효과를 미치지 않음. 

RS(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR); 
RS(D3DRS_SRCBLEND, D3DBLEND_ZERO); 

---------------------------------------------------------------------------------------- 
네거티브 포지티브 반전 

흰 폴리곤을 렌더링하면, 검은 부분은 희게, 흰 부분은 검게 출려되도록 색을 역전하는 변환을 합니다. 

최종색 = ( 1 - 바닥색) * 덮일색 

RS(D3DRS_DESTBLEND, D3DBLEND_ZERO); 
RS(D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR); 
---------------------------------------------------------------------------------------- 

불투명 

알파블렌딩을 설정한 채로 불투명한 것을 그리고 싶을때 

최종색 = 덮일색 

RS(D3DRS_DESTBLEND, D3DBLEND_ZERO); 
RS(D3DRS_SRCBLEND, D3DBLEND_ONE); 

 
 
 
 
 
D3DRS_ALPHATESTENABLE // 알파테스트 사용 유/무 디폴트: FALSE 
D3DRS_ALPHAREF // 시험 픽셀값 0x00 ~ 0xff 
D3DRS_ALPHAFUNC // D3DCMPFUNC에 대한 정의 디폴트: D3DCMP_ALWAYS 

D3DCMPFUNC 

D3DCMP_NEVER 항상시험에 실패한다. 
D3DCMP_LESS 시험 픽셀이 현재의 픽셀보다 작은 경우 통과한다. 
D3DCMP_EQUAL 시험 픽셀이 현재의 픽셀과 동일한 경우 통과한다. 
D3DCMP_LESSEQUAL 시험 픽셀이 현재의 픽셀보다 작거나 같은 경우 통과한다. 
D3DCMP_GREATER 시험 픽셀이 현재의 픽셀보다 큰 경우 통과한다. 
D3DCMP_NOTEQUAL 시험 픽셀이 현재와 같지 않은 경우 통과 한다. 
D3DCMP_GREATEREQUAL 시험 픽셀이 현재보다 크거나 같은 경우 통과한다. 
D3DCMP_ALWAYS 항상 시험에 통과한다. 


# 시험 픽셀은 D3DRS_ALPHAREF의 값이며 현재 픽셀은 출력될때 이미지의 알파픽셀의 값을 의미 합니다. 

# 시험에서 통과하지 않을경우는 그에 해당하는 현재픽셀은 무시하게 되어 출력하지 않습니다. 

통과 했을 경우는 현재픽셀의 알파값을 가지고 출력하게 됩니다. ( 말 그대로 알파 비교를 하게 되겠지여 ) 

알파 테스트는 픽셀에 들어있는 알파값을 비교해서 이 픽셀을 사용할것인지 안할것인지를 결정하게 되는 겁니다. 

이것을 잘만 사용하면 스프라이트 형식의 1555 포맷과 같은 이미지 형식이라면 알파소팅을 하지 않아도 됩니다. 

P.S 알파 테스트를 하는 목적중에 하나는 렌더링 속도를 올리기 위해서 입니다. 

이미지에서 알파를 사용하면 자신의 위치에서 뒤에 있는 이미지의 픽셀을 혼합해서 나오게 되는데 

알파테스트는 불필요한 혼합을 하지 않아도 되므로 속도 향상을 줄수가 있는 겁니다. 

설명이 제대로 됬는지 모르겠군여 틀린부분 있으면 질문&답변게시판에 지적해 주세여 
----------------------------------------------- 

벌날개의 메모... 
<알파채널이 있는 경우...(TGA)> 
텍스처 로드...(초기화에서) 
if( FAILED( D3DUtil_CreateTexture( g_pd3dDevice,"tree01s.tga", 
                                           &g_pTexture ) ) ) 
            return E_FAIL; 
(랜더링에서) 
g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,   TRUE ); 
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA ); 
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); 

랜더링..... 

 
 
 
 
텍스쳐 알파 채널을 이용한 투명 표현
 

// 선형합성 C = Cd(1-As)+CsAs

theApp.m_pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
theApp.m_pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); 
theApp.m_pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );


블렌딩이 안되는건 텍스쳐 파일에 알파채널 값이 없기 때문이였다. -_-!


그리고 그 전에 컬러끼리 섞었는데 그 결과는 좀 진한 투명 색이였다.

두 색이 합쳐진건지 원.. ㅋ

theApp.m_pDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
theApp.m_pDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR ); 
theApp.m_pDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVDESTCOLOR );





알파 블렌딩에 관하여


눈에는 보이지 않는...일종의 색상들을 섞을때 파라메터로 사용되는...그런 '값'이죠.

예를 들어 D3D의 알파블렌딩은 아래와 같이 이루어집니다.

WriteColor = SrcBlend * SrcColor + DstBlend * DstColor ;

WriteColor : 화면에 찍고자 하는 색상
SrcColor  : 텍스쳐 블렌딩(쉐이딩,멀티텍스쳐링 따위...)처리된 텍스쳐색상
DstColor  : 현재 화면에 찍혀있는 색상

SrcBlend와 DstBlend를 적당히 잘 만들어 주면 재미있는 효과를 얻을수 있습니다.

SrcBlend = 1  DstBlend = 0 
그냥 색상을 찍음.

SrcBlend = 0  DstBlend = 1 
아무색상도 찍지 않음.

SrcBlend = SrcAlpha  DstBlend = 1-SrcAlpha 
SrcColor에 있는 알파값으로 블렌딩.
( 만약 모든 SrcAlpha값이 0.5 라면  반반씩 섞이는 셈이니...정말로 반.투.명)

SrcBlend = 1  DstBlend = 1
SrcColor와 DstColor를 그냥 더해서 찍음.
텍스쳐가 찍히는 곳은 원래 찍혀있던 색상보다 밝아집니다. 눈부시게 빛나는(광원)효과.

SrcBlend = 0  DstBlend = SrcColor
SrcColor와 DstColor를 그냥 곱해서 찍음.
텍스쳐의 색상으로 원래 찍혀있는 색상을 쉐이딩한다고 생각하시면 쉽죠.
멀티텍스쳐가 지원되지 않을때 라이트매핑따위.

음.........
따지고 보니 알파블렌딩과 알파값은 사실 별 상관이 없어보이죠?
맞습니다.
그냥 텍셀마다 하나의 '확장 매개변수값'을 가지고 있다고 생각하세요.
이걸 가지고 무얼하는지는 순전히 프로그래머 맘이죠.


반응형

'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글

환경 맵(큐브 맵, Cube Map)  (0) 2012.11.08
Direct 에서 스피어함수  (0) 2012.11.02
점 그리기 -크기 변환  (0) 2012.11.02
점그리기  (0) 2012.11.02
Directx D3DXCreateSphere 구현  (0) 2012.11.02
반응형

//점의 색상에 알파값을 적용하기 위한state
   _pD3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
   _pD3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
   _pD3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );

   
   _pD3dDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,TRUE);//점이 스프라이트로 그려지기 때문에 텍스쳐 가능을 켜야 한다
   _pD3dDevice->SetRenderState(D3DRS_POINTSCALEENABLE,TRUE);//크기 크게 가능 

   //이 세 개의 상수는 거리에 따라 포인트 스프라이트의 크기가 변하는 방법을 제어한다. 야기에서 말하는 거리란 카메라와 포인트 스프라이트 간의 거리이다. 
   //이것을 쓰려면 A=x,B=y,C=z 세개다 몇시해 줘야 한다
   _pD3dDevice->SetRenderState(D3DRS_POINTSCALE_A,0); 
   _pD3dDevice->SetRenderState(D3DRS_POINTSCALE_B,0); 
   _pD3dDevice->SetRenderState(D3DRS_POINTSCALE_C,1);


   float PointSize = 10.0f;
   _pD3dDevice->SetRenderState( D3DRS_POINTSIZE , *((DWORD*)&PointSize));
   _pD3dDevice->SetRenderState(D3DRS_POINTSIZE_MAX,*((DWORD*)&PointSize));   //max 가 0 이 아니어야 한다
   
   PointSize = 0.0f;
   _pD3dDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&PointSize));

   _pD3dDevice->SetStreamSource( 0, NULL, 0, sizeof(VERTEX_POSCOLORPOINT) );
   _pD3dDevice->SetFVF( D3DFVF_POS_DIFFUSE );
   _pD3dDevice->SetIndices( NULL );

   _pointNodes[0]._color=D3DCOLOR_ARGB(33,0xff,0xff,0xff);
   _pD3dDevice->DrawPrimitiveUP( D3DPT_POINTLIST,_pointNodes.size(),(void*)&_pointNodes[0], sizeof(VERTEX_POSCOLORPOINT) );

   PointSize = 1.0f;
   _pD3dDevice->SetRenderState( D3DRS_POINTSIZE , *((DWORD*)&PointSize));
   _pD3dDevice->SetRenderState(D3DRS_POINTSCALEENABLE,FALSE);
   _pD3dDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,FALSE); 
   _pD3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
   _pD3dDevice->SetRenderState(D3DRS_POINTSCALE_C,0);

 

 

 

float 를 DWORD 로 변환할때 &,* 를 사용하는 이유

 

 

*(DWORD*)&PointSize 로 해야 제대로 소수부분또한 실수로 변환되어 DWORD 에서 실수에서의 값을 갖고 있게 된다

즉 *(DWORD*)&PointSize  에서 넘겨지는 DWORD 는 float 형을 DWORD의 비트열로 변환한 값을 필요로 한다는 것.

 

 

반응형

'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글

Direct 에서 스피어함수  (0) 2012.11.02
투명처리와 알파 합성  (0) 2012.11.02
점그리기  (0) 2012.11.02
Directx D3DXCreateSphere 구현  (0) 2012.11.02
디바이스를 잃었을때의 복구 절차  (0) 2012.11.02
반응형

typedef struct _VERTEX_POSCOLOR
{

D3DXVECTOR3 pos;

DWORD color;
 static const DWORD FVF_POS_DIFFUSE;  //==D3DFVF_POS_DIFFUSE
public :
 //생성자로 인수받아 초기화 해준다
}VERTEX_POSCOLOR;


 

 

VERTEX_POSCOLOR g_Vertices[3];

 

g_Vertices[0]=VERTEX_POSCOLOR(-10.0f,-10.0f, 0.0f, 0xffffffff);
  g_Vertices[1]=VERTEX_POSCOLOR(10.0f,-10.0f, 0.0f, 0xffffffff);
  g_Vertices[2]=VERTEX_POSCOLOR( -5.0f, 10.0f, 0.0f, 0xffffffff);

 

 

 

 

 

_pD3dDevice->SetFVF( VERTEX_POSCOLOR::FVF_POS_DIFFUSE );
 _pD3dDevice->DrawPrimitiveUP( D3DPT_POINTLIST,3, (void *)g_Vertices, sizeof(VERTEX_POSCOLOR) );

반응형

+ Recent posts