はじめまして、
質問させていただきます。
内容は件名に書いたとおり、UV座標の仕組みが理解できないというものです。
四角形のUVを指定するときは
{0,0},{0,1},{1,0},{1,1}
のようにすればいいのはわかりますが、
立方体にテクスチャを貼り付けたいとき、
一面であれば先ほどのようにすればいいのですが、
隣の面のUVを指定する際、既に{1,0}と指定した頂点に{0,0}と指定したい。
既に{1,1}と指定した頂点に{0,1}と指定したい。
というような"隣り合わせの面でUVを切り替えたい場合"がよくわからないのです。
説明が下手なのでこれで伝わるかどうか不安ですが、よろしくお願いします。
よくわからないという方はぜひ質問ください。
Directx9_DrawIndexedPrimitive_UV座標について
Re: Directx9_DrawIndexedPrimitive_UV座標について
当方Windows10、VC++2008にDirectX9 SDK を入れてテストをしています。
具体的にどのようなプログラムを作っておられるのかコードを提示して頂ければわかるやもしれません。
例えば次のコードは動きます。
注:
"d:/dat/pict.jpg"必要。
[/size]
具体的にどのようなプログラムを作っておられるのかコードを提示して頂ければわかるやもしれません。
例えば次のコードは動きます。
// テクスチャ作成サンプルプログラム
#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]
Re: Directx9_DrawIndexedPrimitive_UV座標について
Mathさん。読んでいただきありがとうございます。
uv座標の理屈の問題であって、エラーがあるわけではないのですが、
参考になるのであればとりあえず四角形描画周りの処理を貼ります。
(立方体描画はまだuv座標がどうあるべきかわからないので作成していません。)
(StartDraw()とEndDraw()の間にSpriteやMeshのDraw関数が呼ばれます。)
(四角形描画に問題はなく、2DShaderはtex2Dしか使っておりません。)
Sprite.cpp
StartDraw関数、EndDraw関数
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();
}
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);
}
Re: Directx9_DrawIndexedPrimitive_UV座標について
スプライトなど難しい事をやっておられるのですね。私はまだ理解が進んでないので動くものしか理解しきれません。(^^;
このサイトのプログラムは動くので参考になるのではないでしょうか。
http://marupeke296.com/DXPS_No12_CalcTa ... Space.html
このサイトのプログラムは動くので参考になるのではないでしょうか。
http://marupeke296.com/DXPS_No12_CalcTa ... Space.html
Re: Directx9_DrawIndexedPrimitive_UV座標について
頂点情報は、頂点座標とUV座標がセットなので、UV座標が異なれば頂点情報は別個となります。
それを、D3DPT_TRIANGLESTRIPのDrawPrimitive系関数一回の呼び出しで描画したいときは、縮退ポリゴンを利用します。
縮退ポリゴンとは、面積がゼロのポリゴンのことです。
No.2のMathさんのコードに対して、26行目から32行目までを以下のコードに置き換えます。
No.2のコードで、35,36,85行目にある頂点情報数のマジックナンバーを4→8に書き換えます。
No.2のコードで、116行目にある描画ポリゴン数を2→6に書き換えます。
このようにして、UV座標の異なるポリゴンを貼り合わせます。
(インデックス参照の)D3DPT_TRIANGLELISTのほうが適切な場合があります。
それを、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のコードで、116行目にある描画ポリゴン数を2→6に書き換えます。
このようにして、UV座標の異なるポリゴンを貼り合わせます。
オフトピック
縮退ポリゴンを利用する方法はたいてい、離れたポリゴンを一回の関数呼び出しで描画する方法として紹介されます。
No.2のコードに対して、26行目から32行目までを以下のコードに置き換えます。
No.2のコードで、35,36,85行目にある頂点情報数のマジックナンバーを4→9に書き換えます。
No.2のコードで、116行目にある描画ポリゴン数を2→7に書き換えます。
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のコードで、116行目にある描画ポリゴン数を2→7に書き換えます。
Re: Directx9_DrawIndexedPrimitive_UV座標について
ISLeさん。読んでいただきありがとうございます。
やはり、ひとつの頂点が複数UVを持つ場合だと、IndexBufferを活用しての描画は不可能なんですね。
それがわかっただけで十分です。
回答ありがとうございました。
やはり、ひとつの頂点が複数UVを持つ場合だと、IndexBufferを活用しての描画は不可能なんですね。
それがわかっただけで十分です。
回答ありがとうございました。