音ゲーの出来ない雑魚のブログ

LWJGLとかのことをいうブログ

「moreover lwjgl」 7 (古風な)Texture貼り付け(2)

続きです。TextureManagerクラスしか使わないので、それだけ貼ります。



解説

40行目 : ByteBuffer型で画像のデータを返すメソッドでデータを作成(load)しています。

42,43行目 : 第1引数で指定したターゲット(GL_TEXTURE_〇〇など)の、パラメータの設定をします。

void glTexParameteri( . . . )

パラメータは次のようなものが有ります。(今回も、先頭の"GL_"は抜いてあります。

パラメータ名説明型と設定可能な値備考
TEXTURE_MIN_FILTERテクスチャ縮小時のフィルター定数:LINEAR,NEAREST,
LINEAR_MIPMAP_LINEAR,
LINEAR_MIPMAP_NEAREST,
NEAREST_MIPMAP_LINEAR,
NEAREST_MIPMAP_NEAREST
 
TEXTURE_MAG_FILTERテクスチャ拡大時のフィルター定数:LINEAR,NEAREST 
TEXTURE_WRAP_Sテクスチャの横の繰り返しのパターン定数:CLAMP,REPEAT,
CLAMP_TO_EDGE,
CLAMP_TO_BORDER,
MIRRORED_REPEAT,
MIRROR_CLAMP_TO_EDGE
定数は最初の2つ以外GL11以降の機能
TEXTURE_WRAP_Tテクスチャの縦の繰り返しのパターン上と同じ 
TEXTURE_PRIORITYテクスチャの優先度int最近のOpenGLで廃止されてます
TEXTURE_BORDER_COLORテクスチャのボーダーの色ByteBuffer(RGBA)使用するときは、glTexParameterfv()などとします
 ここまでGL11の機能ここからそれ以降 
TEXTURE_WRAP_Rテクスチャの奥行きの繰り返しのパターン定数:CLAMP,REPEAT 
BASE_LEVELmipmapの初期レベル(解像度)int: 0以上の任意の整数GL12から
MAX_LEVELmipmapの最大レベルint: 0以上の任意の整数GL12から
MAX_LODmipmapのLevel Of Detailの最大値float:任意の数GL12から
MIN_LODmipmapのLevel Of Detailの最小値float:任意の数GL12から
LOD_BIASmipmapのLevelを設定するfloat:任意の数(-4.0~4.0がいいらしい)GL14から
COMPARE_MODEテクスチャの成分比較のモード(主にシャドウマッピングで使う?)定数:NONE,
COMPARE_R_TO_TEXTURE
GL14から
COMPARE_FUNC成分比較の結果に対する関数定数:LEQUAL,GEQUAL,
LESS,GREATER,EQUAL,
NOTEQUAL,ALWAYS,NAVER
GL14から

(定数はGEQUAL以降はGL15から)

SWIZZLE_●(R/G/B/A)テクスチャをSwizzleするときの●(red/green/blue/alpha)を
テクスチャのRGBAのどこから取るか
定数:RED,GREEN,BLUE,
ALPHA,ZERO,ONE
GL33から
SWIZZLE_RGBA上のをまとめてできるByteBuffer(red/green/blue/alpha)GL33から

長々と有ります。正直後ろの方に行くつれてよくわからない感じで、使う?って感じですけど…

詳しくは、英語ですがこちらに載ってます。
GLAPI/glTexParameter - OpenGL.org


一応必要なことを書きます。

Mipmapとは

テクスチャを描画する際に、テクスチャがとても細かく、貼り付ける先のポリゴン(オブジェクト)が視点から遠かったりしたら、チカチカと見えたり、処理の無駄になってしまいます。

そこで、Mipmapというシステムで、読み込んだテクスチャを小さくしたり、逆に大きくしたりすることで、見た目に問題が無いようにして、処理を軽くするというものです。

この時のMipmapの縮小/拡大の大きさをLevelと言います。元のレベルは0です。Levelの詳細(変わり方)がLevel Of Detail(LOD)です。


そして、Mipmapでも使う、この「テクスチャの縮小,拡大」というものは、もちろんそれぞれの大きさのテクスチャを作って、それにすることも出来ますが、OpenGLが中で自動的にテクスチャを作ってくれるのです。その時の方法を、GL_TEXTURE_MIN/MAG_FILTERの設定によって変えられます。

Bilinear法とNearest Neighbor法

OpenGLが対応しているテクスチャの縮小,拡大方法として、Bilinear法と、Nearest Neighbor法があります。これらは、一般的にも使われる方法です。

f:id:cakkby:20160331124015p:plain
Nearest Neighborは、最も近い点のRGBAを取り、Bilinearは周り4点のRGBAの平均を取ります。
Bilinearのほうが計算量が多いですが、綺麗に映ります。

また、OpenGLはサポートしていませんが、Bicubicという、周り16点の平均を取るものも有ります。これが一番綺麗だそうです。

(テクスチャの奥行きとか、Swizzleとかはまだよくわからないので、分かるようになったらそのうち書きます。)


45行目 : テクスチャIDに画像を付けます。

void glTexImage2D( . . . )

第1引数はテクスチャのタイプ(2D,RECTANGLEなど)
第2引数はテクスチャ(Mipmap)のLevel
第3引数はOpenGL上のテクスチャのフォーマット(RGBか、RGBAか、RGBAの16進数かなど)
第4,5引数はテクスチャの縦,横の大きさ
第6引数はテクスチャのボーダーの太さ
第7引数は画像のフォーマット(Rだけの画像か、RGBを整数(0~255)までで表した画像かなど)
第8引数は画像の型(GL_UNSIGNED_BYTEはOpenGL上でGLubyte、JavaではByteBufferになります)
第9引数は画像のデータ

となります。基本的に、画像のデータはByteBufferになると思うので、第8引数はGL_UNSIGNED_BYTEでいいと思います。

47行目 : 使い終わった画像データをメモリから消します。





ここから、画像のデータをPNGイメージから読み取るメソッドの説明(作ったりするのに苦戦しました)
まったくOpenGL関係ないので、適当に解説します。


まず、読み込む方法(LOAD_POT_FAST,LOAD_POT_QUALITY,LOAD_NPOT)それぞれでやってること…

<LOAD_POT_FAST>
Power Of Twoの画像をすばやく生成して、データに変換します。
画像の大きさをPOTにするのに、2つのメソッドを借りています。(isPowerOfTwo,padToPowerOfTwoメソッド)ちょっと改変しました、すみません!
画像を拡大するメソッド(scaleメソッド)はStackOverFlowからもらいました。簡単に言うと、元のデータのRGB値を新しい大きさに合うように拡大してセットしています。
早いですが、質は少し悪めです。

<LOAD_POT_QUALITY>
Power Of Twoの画像を質がまあまあ良くなるように生成して、データに入れます。
上と同じようにPOTの大きさにしています。
中では、Graphicsクラスを使って新しい大きさで画像を書き直しています。
Graphicsを使うと表示までがとても遅いのですが、質はまあまあのはずです。

<LOAD_NPOT>
None Power Of Twoの画像をそのまま読み込んで、そのままデータに変換しています。
大きさを変える処理をしていないので、画像の質が保たれていて、かつ、あまり遅くないです。
ただ、OpenGL1.0では対応していなかったり、バージョンが上がって対応していても、設定できないパラメーターがあったりします。

それでは、ソースコードの解説に戻ります。適当に





52~59行目 : イメージをいれるBufferedImageを作り、ImageIOクラスを使って読み取った画像をいれます。

61行目 : 後にデータとなるByteBufferを空の状態で作ります。

63~69行目 : 読み込む方法に応じて、画像の大きさを変更しています。これは、後で使うNPOTの画像サイズにするときに使います。

70~72行目 : LOAD_POT_FASTの時は画像の大きさをここで変えます。

74~115行目 : 指定した設定のRasterを備えたBufferedImageを使って、ByteBufferにデータを書き込みます。

LOAD_NPOT,LOAD_POT_FASTの時は、画像から直接RGBAのデータを読み込んで、ByteBufferに入れています。

LOAD_POT_QUALITYの時は、GraphicsのdrawImageメソッドで大きさを変えながら描き直し、そのデータをByteBufferに入れています。

116行目 : データを入れたByteBufferを返します。






すごく長いですが、これでテクスチャを読み込むことが出来ます。

実際に2つの方法(NPOTは使えないのでPOT_QUALITYとPOD_FAST)で読み込んだ画像を比べてみます。(画像を変更しました)

<元の画像>
f:id:cakkby:20160401212137p:plain
<LOAD_POT_QUALITY>
f:id:cakkby:20160401211941p:plain
<LOAD_POT_FAST>
f:id:cakkby:20160401211958p:plain

衝撃の、あまり変わらないという結果でした…どちらも質はよくないですね…

結局、テクスチャは、元からPOTのものにして、ふつうに読み込むのが一番きれいで制限がなさそうです。

P.S. せっかくのエイプリルフールなのに、ネタを入れる隙間すらなかったです…