DirectXのUVマッピングに関する質問です。よろしくお願いします。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
t_white

DirectXのUVマッピングに関する質問です。よろしくお願いします。

#1

投稿記事 by t_white » 16年前

こんばんは。夏の終わりぐらいからかなりお久しぶりです。

DXライブラリのLoadDivGraphのようにテクスチャを分割して描画できるクラスを作りたいのですがあるところでつまづいていて困っています。
//	テクスチャを読み込んで分割して描画できるクラス(擬似スプライトクラスでIDirect3DTexture9*(LPDIRECT3DTEXTURE9)を内部に持ってます)
	CDivSprite graphic;
	//	読み込む画像へのパス, 透過色, 総分割数, 横方向に対する分割数, 縦方向に対する分割数, 分割する横サイズ, 分割する縦サイズ
	graphic.Create("Cat.bmp", 0xff000000, 4, 2, 2, 32, 32);
	//	分割した画像の添え字(総分割数が4なので0~3), x座標, y座標 z座標
	graphic.Draw( 0, x, y, z);
という感じで扱えるように実装したいのです。
一通り書いて実行したのですが、どうも2段目以降の画像の上端がずれているらしく、上端に一段上の画像の下端が少し(1ピクセルにもみたない)表示されてしまいます。
1枚のテクスチャに分割数だけUVマッピングを行って分割するように実装しているので、そこでずれてしまっていると思うのですが、解決策を教えて貰えると助かります。
/*
	m_DivAllNum:	総分割数
	m_DivXNum:		横に対する分割数
	m_DivYNum:		縦に対する分割数
	m_TextureUV[m_DivAllNum][4]	:	D3DXVECTOR2型	各分割された画像一枚一枚のUV座標
	*/
	//--------------------------------------------------------------
	//	UVマッピング
	//--------------------------------------------------------------
	m_TextureUV = new D3DXVECTOR2[m_DivAllNum][4];
	WORD x,y,num;
	for(y = 0; y < m_DivYNum; ++y){
		for(x = 0; x < m_DivXNum; ++x){
			num = y * m_DivXNum + x;	//	番号計算
			//	分割総数を越えたら抜ける(yの条件は満たすと思うんでfor文二つとも抜けれるはず)
			if(num >= m_DivAllNum)
				break;
			m_TextureUV[num][0] = D3DXVECTOR2((float)(x * m_DivWidth) / m_TextureWidth, (float)(y * m_DivHeight) / m_TextureHeight);			//	左上
			m_TextureUV[num][1] = D3DXVECTOR2((float)((x+1) * m_DivWidth) / m_TextureWidth, (float)(y * m_DivHeight) / m_TextureHeight);		//	右上
			m_TextureUV[num][2] = D3DXVECTOR2((float)(x * m_DivWidth) / m_TextureWidth, (float)((y + 1) * m_DivHeight) / m_TextureHeight);		//	左下
			m_TextureUV[num][3] = D3DXVECTOR2((float)((x+1) * m_DivWidth) / m_TextureWidth, (float)((y + 1) * m_DivHeight) / m_TextureHeight);//	右下
		}
	}
ちなみに、左上のUV座標のV座標に+0.00001するだけでも上端のやつは消えるので、それで解決するといえば解決するのですが、ちゃんとした解決法があるなら知りたいのです。
恐らく最下位の小数点を切り上げられれば解決するような気が・・・するような関係ないような気がしてます。

すごくわかり辛くてすみません。;
言って貰えれば必要な情報を書き加えますです。
どうかよろしくお願いいたします。

Justy

Re:DirectXのUVマッピングに関する質問です。よろしくお願いします。

#2

投稿記事 by Justy » 16年前

 テクスチャを1枚にまとめようとするとよくある話です。

 テクスチャ座標は DirectXのマニュアルを見てもらうと解るのですが、
テクスチャ座標とテクセルとのマッピングには独特のルールがあります。

テクセルとピクセル間の直接マッピング
http://msdn.microsoft.com/ja-jp/library/cc373047.aspx


 上記のページを見てもらうとわかりますが、テクスチャ座標から
テクセル座標を求めるのに 0.5を引いています。

 t_whiteさんのプログラムはテクセル座標からテクスチャ座標を出していますが、
その際このあたりが考慮されていないため、ズレが発生しているのではないか、
と考えられます。

 まぁ、素材の方で境界には色を置かないようにすればいい話ではありますが。

 こちらも参考にして下さい。

テクスチャ座標 - ゲームプログラミングWiki
http://www.c3.club.kyutech.ac.jp/gamewi ... A%C2%C9%B8


 又、バイリニアフィルタを使ってしまうとこれだけでは済まず上下左右の4ピクセルも
影響するので、クランプの設定をアドレッシングモードにしたり、
やはり素材の方で境界の周囲を透明にするなど工夫しないと、周囲の色を
拾ってしまってゴミになってしまったりしますので、注意が必要です。

t_white

Re:DirectXのUVマッピングに関する質問です。よろしくお願いします。

#3

投稿記事 by t_white » 16年前

>>Justy様
わかりやすい説明&参考ページありがとうございます!
なるほど、このDirect3Dがテクセル座標を求るのに0.5を引く処理の影響で通常だと上と左に少しずれてしまうのですね。(イメージ的には合っていますように)
そうすると四方向全てを微妙に小さくする対処法もまったくの間違いという訳ではないのでしょうか。
m_TextureUV[num][0] = D3DXVECTOR2((float)(x * m_DivWidth) / m_TextureWidth + 0.000001, (float)(y * m_DivHeight) / m_TextureHeight + 0.000001);			//	左上
			m_TextureUV[num][1] = D3DXVECTOR2((float)((x+1) * m_DivWidth) / m_TextureWidth - 0.000001, (float)(y * m_DivHeight) / m_TextureHeight + 0.000001);		//	右上
			m_TextureUV[num][2] = D3DXVECTOR2((float)(x * m_DivWidth) / m_TextureWidth + 0.000001, (float)((y + 1) * m_DivHeight) / m_TextureHeight - 0.000001);		//	左下
			m_TextureUV[num][3] = D3DXVECTOR2((float)((x+1) * m_DivWidth) / m_TextureWidth - 0.000001, (float)((y + 1) * m_DivHeight) / m_TextureHeight - 0.000001);//	右下
のように。
こうすると上のやつも消えましたし、Drawに回転計算も入れたverも境界が綺麗になりました。
(以前はDXライブラリでいうDrawRotaGraphのように実装したDrawを使うと、微妙な角度の時にまたとなりの分割画像の端が見えてしまう事態が発生していた)
とりあえずはこのまま使用してみます。
本当にありがとうございました!

Justy

Re:DirectXのUVマッピングに関する質問です。よろしくお願いします。

#4

投稿記事 by Justy » 16年前


>そうすると四方向全てを微妙に小さくする対処法もまったくの間違いという訳ではない

 小さくするサイズが定数なのは気になりますが、うまく動いているなら
きっと全く間違いというわけではないのでしょう。

 ただ、素材のサイズによっては何かしらの影響を受けてしまうかもしれません。

閉鎖

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