Directx9_DrawIndexedPrimitive_UV座標について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
isanan
記事: 3
登録日時: 6年前

Directx9_DrawIndexedPrimitive_UV座標について

#1

投稿記事 by isanan » 6年前

はじめまして、
質問させていただきます。
内容は件名に書いたとおり、UV座標の仕組みが理解できないというものです。

四角形のUVを指定するときは
{0,0},{0,1},{1,0},{1,1}
のようにすればいいのはわかりますが、

立方体にテクスチャを貼り付けたいとき、
一面であれば先ほどのようにすればいいのですが、
隣の面のUVを指定する際、既に{1,0}と指定した頂点に{0,0}と指定したい。
既に{1,1}と指定した頂点に{0,1}と指定したい。
というような"隣り合わせの面でUVを切り替えたい場合"がよくわからないのです。

説明が下手なのでこれで伝わるかどうか不安ですが、よろしくお願いします。
よくわからないという方はぜひ質問ください。

Math

Re: Directx9_DrawIndexedPrimitive_UV座標について

#2

投稿記事 by Math » 6年前

当方Windows10、VC++2008にDirectX9 SDK を入れてテストをしています。
具体的にどのようなプログラムを作っておられるのかコードを提示して頂ければわかるやもしれません。
例えば次のコードは動きます。

コード:

// テクスチャ作成サンプルプログラム

#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>


struct CUSTOMVERTEX{  
   float x, y, z; // 頂点座標 
   float rhw;     // 除算数 
   float u, v;    // テクスチャ座標 
}; 

#define FVF_CUSTOM ( D3DFVF_XYZRHW | D3DFVF_TEX1 )

TCHAR gName[100] = _T("テクスチャ作成サンプルプログラム");


// 頂点位置設定関数
BOOL SetPos(IDirect3DVertexBuffer9* vtx, float Cx, float Cy, float width, float height){
   CUSTOMVERTEX v[4]= 
   {  
      { Cx + width/2, Cy - height/2, 0.0f, 1.0f, 1.0f, 0.0f},
      { Cx + width/2, Cy + height/2, 0.0f, 1.0f, 1.0f, 1.0f}, 
      { Cx - width/2, Cy - height/2, 0.0f, 1.0f, 0.0f, 0.0f}, 
      { Cx - width/2, Cy + height/2, 0.0f, 1.0f, 0.0f, 1.0f} 
   };

   void *pData;
   if(SUCCEEDED(vtx->Lock(0, sizeof(CUSTOMVERTEX)*4, (void**)&pData, 0))){
      memcpy(pData, v, sizeof(CUSTOMVERTEX)*4);
      vtx->Unlock();
      return TRUE;
   }
   return FALSE;
}


// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam){
   if(mes == WM_DESTROY) {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, CW_USEDEFAULT, 0,
                                    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 = {0,0,D3DFMT_UNKNOWN,0,D3DMULTISAMPLE_NONE,0,
                                                      D3DSWAPEFFECT_DISCARD,NULL,TRUE,0,D3DFMT_UNKNOWN,0,0}; 

   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 ) ) )
   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) )
   {
      g_pD3D->Release();
      return 0;
   }

   ShowWindow(hWnd, nCmdShow);

   // 頂点バッファの作成
   IDirect3DVertexBuffer9* pVertex;
   if(FAILED(g_pD3DDev->CreateVertexBuffer( sizeof(CUSTOMVERTEX)*4, D3DUSAGE_WRITEONLY, FVF_CUSTOM, D3DPOOL_MANAGED, &pVertex, NULL))){
           g_pD3DDev->Release(); g_pD3D->Release();
           return 0;
   }

   
     // テクスチャの作成
   IDirect3DTexture9* pTex[3];
   DWORD FilterFlag[3] = { D3DX_FILTER_POINT, D3DX_FILTER_LINEAR, (D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER)};
   int i;
   int Tex_W = 64;
   for(i=0; i<3; i++){
	   if(FAILED(D3DXCreateTextureFromFileEx(g_pD3DDev, _T("d:/dat/pict.jpg"), Tex_W, Tex_W, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT,
                   FilterFlag[i], D3DX_DEFAULT, 0, NULL, NULL, &pTex[i]))){
           return 0;
          }
   }

   // メッセージ ループ
   float width = 256.0f;
   float height= 256.0f;
   do{
      Sleep(1);
      if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ){ DispatchMessage(&msg);}
         g_pD3DDev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
         g_pD3DDev->BeginScene();

         for(i=0; i<3; i++){
             g_pD3DDev->SetTexture(0, pTex[i]);
             // 頂点バッファに頂点を書き込みできた時にだけ描画
             if(SetPos(pVertex, (10+width)*i+10+width/2, 20+height, width, height)){
                // 描画
                g_pD3DDev->SetStreamSource(0, pVertex, 0, sizeof(CUSTOMVERTEX));
                g_pD3DDev->SetFVF(FVF_CUSTOM);
                g_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
             }
         }
         g_pD3DDev->EndScene();
         g_pD3DDev->Present( NULL, NULL, NULL, NULL );
   }while(msg.message != WM_QUIT);

   for(i=0; i<3; i++) pTex[i]->Release();
   pVertex->Release();
   g_pD3DDev->Release();
   g_pD3D->Release();

   return 0;
}
/////
注:
"d:/dat/pict.jpg"必要。
[/size]

isanan
記事: 3
登録日時: 6年前

Re: Directx9_DrawIndexedPrimitive_UV座標について

#3

投稿記事 by isanan » 6年前

Mathさん。読んでいただきありがとうございます。

uv座標の理屈の問題であって、エラーがあるわけではないのですが、
参考になるのであればとりあえず四角形描画周りの処理を貼ります。
(立方体描画はまだuv座標がどうあるべきかわからないので作成していません。)
(StartDraw()とEndDraw()の間にSpriteやMeshのDraw関数が呼ばれます。)
(四角形描画に問題はなく、2DShaderはtex2Dしか使っておりません。)

Sprite.cpp

コード:


cSprite::cSprite(const RECT& rect, const string texPath, const string shaderPath, const string tech)
{
	m_rect = rect;

	D3DXCreateTextureFromFile(INSTANCE(Dx9)->GetDevice(), texPath.c_str(), &m_texture);

	m_vtx[0] = { D3DXVECTOR3(m_rect.left, m_rect.top, 0.0), 0.0f, 0.0f };
	m_vtx[1] = { D3DXVECTOR3(m_rect.right, m_rect.top, 0.0f), 1.0f, 0.0f };
	m_vtx[2] = { D3DXVECTOR3(m_rect.left, m_rect.bottom, 0.0f), 0.0f, 1.0f};
	m_vtx[3] = { D3DXVECTOR3(m_rect.right, m_rect.bottom, 0.0f), 1.0f, 1.0f};

	D3DXCreateEffectFromFile(INSTANCE(Dx9)->GetDevice(), shaderPath.c_str(), 0, 0, 0, 0, &m_shader, NULL);
	m_technique = tech;

}

cSprite::~cSprite()
{
	m_texture->Release();
	SAFE_DELETE(m_texture);

	m_shader->Release();
	SAFE_DELETE(m_shader);

}

void cSprite::Draw()
{
	int w, h;
	INSTANCE(Dx9)->GetClientSize(w, h);
	D3DXMATRIX proj(
		2 / (float)w, 0.0f, 0.0f, 0.0f,
		0.0f, -2 / (float)h, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		-1.0f, 1.0f, 0.0f, 1.0f
		);
	m_shader->SetTechnique(m_technique.c_str());

	UINT numPass = 0;
	m_shader->Begin(&numPass, 0);

	for (int p = 0; p < numPass; p++)
	{
		m_shader->BeginPass(p);
		m_shader->SetTexture("DecaleTexture", m_texture);
		m_shader->SetMatrix("proj", &proj);
		INSTANCE(Dx9)->GetDevice()->SetVertexDeclaration(INSTANCE(Dx9)->GetDecl2D());

		INSTANCE(Dx9)->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, m_vtx, sizeof(Vertex));

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

}
StartDraw関数、EndDraw関数

コード:


void Dx9::StartDraw()
{
	if (m_D3D_Device == NULL) return;

	m_D3D_Device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
	//m_D3D_Device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

	m_D3D_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);	//両面
	m_D3D_Device->SetRenderState(D3DRS_LIGHTING, TRUE);

	D3DXMATRIX matView, matProj;

	D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0, -23.0f, -55.0f), &D3DXVECTOR3(0, -23.0f, 0), &D3DXVECTOR3(0, 1, 0));
	m_D3D_Device->SetTransform(D3DTS_VIEW, &matView);

	D3DXMatrixOrthoLH(&matProj, (float)(m_clientRect.left-m_clientRect.right)/10.0f, (float)(m_clientRect.bottom-m_clientRect.top)/10.0f, 0.0f, 2000.0f);
	m_D3D_Device->SetTransform(D3DTS_PROJECTION, &matProj);

	m_D3D_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
	m_D3D_Device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

	m_D3D_Device->BeginScene();
}

void Dx9::EndDraw()
{
	m_D3D_Device->EndScene();
	m_D3D_Device->Present(NULL, NULL, NULL, NULL);
}

Math

Re: Directx9_DrawIndexedPrimitive_UV座標について

#4

投稿記事 by Math » 6年前

スプライトなど難しい事をやっておられるのですね。私はまだ理解が進んでないので動くものしか理解しきれません。(^^;
このサイトのプログラムは動くので参考になるのではないでしょうか。
http://marupeke296.com/DXPS_No12_CalcTa ... Space.html

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: Directx9_DrawIndexedPrimitive_UV座標について

#5

投稿記事 by ISLe » 6年前

頂点情報は、頂点座標とUV座標がセットなので、UV座標が異なれば頂点情報は別個となります。

それを、D3DPT_TRIANGLESTRIPのDrawPrimitive系関数一回の呼び出しで描画したいときは、縮退ポリゴンを利用します。
縮退ポリゴンとは、面積がゼロのポリゴンのことです。

No.2のMathさんのコードに対して、26行目から32行目までを以下のコードに置き換えます。

コード:

   CUSTOMVERTEX v[]=
   {
      { Cx - width/2, Cy + height/2, 0.0f, 1.0f, 0.0f, 1.0f},
      { Cx - width/2, Cy - height/2, 0.0f, 1.0f, 0.0f, 0.0f},
      { Cx          , Cy + height/2, 0.0f, 1.0f, 1.0f, 1.0f},
      { Cx          , Cy - height/2, 0.0f, 1.0f, 1.0f, 0.0f},
      { Cx          , Cy + height/2, 0.0f, 1.0f, 0.0f, 0.0f}, // 縮退
      { Cx          , Cy - height/2, 0.0f, 1.0f, 0.0f, 1.0f},
      { Cx + width/2, Cy + height/2, 0.0f, 1.0f, 1.0f, 0.0f},
      { Cx + width/2, Cy - height/2, 0.0f, 1.0f, 1.0f, 1.0f},
   };
No.2のコードで、35,36,85行目にある頂点情報数のマジックナンバーを4→8に書き換えます。
No.2のコードで、116行目にある描画ポリゴン数を2→6に書き換えます。

このようにして、UV座標の異なるポリゴンを貼り合わせます。

オフトピック
縮退ポリゴンを利用する方法はたいてい、離れたポリゴンを一回の関数呼び出しで描画する方法として紹介されます。

No.2のコードに対して、26行目から32行目までを以下のコードに置き換えます。

コード:

   CUSTOMVERTEX v[]=
   {
      { Cx - width/2, Cy + height/2, 0.0f, 1.0f, 0.0f, 1.0f},
      { Cx - width/2, Cy - height/2, 0.0f, 1.0f, 0.0f, 0.0f},
      { Cx          , Cy + height/2, 0.0f, 1.0f, 1.0f, 1.0f},
      { Cx          , Cy - height/2, 0.0f, 1.0f, 1.0f, 0.0f},
      { Cx          , Cy - height/2, 0.0f, 1.0f, 1.0f, 0.0f}, // 縮退
      { Cx           +5, Cy + height/2 +10, 0.0f, 1.0f, 0.0f, 0.0f},
      { Cx + width/2 +5, Cy + height/2 +10, 0.0f, 1.0f, 1.0f, 0.0f},
      { Cx           +5, Cy - height/2 +10, 0.0f, 1.0f, 0.0f, 1.0f},
      { Cx + width/2 +5, Cy - height/2 +10, 0.0f, 1.0f, 1.0f, 1.0f},
   };
No.2のコードで、35,36,85行目にある頂点情報数のマジックナンバーを4→9に書き換えます。
No.2のコードで、116行目にある描画ポリゴン数を2→7に書き換えます。
(インデックス参照の)D3DPT_TRIANGLELISTのほうが適切な場合があります。

isanan
記事: 3
登録日時: 6年前

Re: Directx9_DrawIndexedPrimitive_UV座標について

#6

投稿記事 by isanan » 6年前

ISLeさん。読んでいただきありがとうございます。
やはり、ひとつの頂点が複数UVを持つ場合だと、IndexBufferを活用しての描画は不可能なんですね。
それがわかっただけで十分です。
回答ありがとうございました。

返信

“C言語何でも質問掲示板” へ戻る