「moreover lwjgl」 7 (古風な)Texture貼り付け(2)
続きです。TextureManagerクラスしか使わないので、それだけ貼ります。
解説
40行目 : ByteBuffer型で画像のデータを返すメソッドでデータを作成(load)しています。
42,43行目 : 第1引数で指定したターゲット(GL_TEXTURE_〇〇など)の、パラメータの設定をします。
パラメータは次のようなものが有ります。(今回も、先頭の"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_LEVEL | mipmapの初期レベル(解像度) | int: 0以上の任意の整数 | GL12から |
MAX_LEVEL | mipmapの最大レベル | int: 0以上の任意の整数 | GL12から |
MAX_LOD | mipmapのLevel Of Detailの最大値 | float:任意の数 | GL12から |
MIN_LOD | mipmapのLevel Of Detailの最小値 | float:任意の数 | GL12から |
LOD_BIAS | mipmapの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法があります。これらは、一般的にも使われる方法です。
Nearest Neighborは、最も近い点のRGBAを取り、Bilinearは周り4点のRGBAの平均を取ります。
Bilinearのほうが計算量が多いですが、綺麗に映ります。
また、OpenGLはサポートしていませんが、Bicubicという、周り16点の平均を取るものも有ります。これが一番綺麗だそうです。
(テクスチャの奥行きとか、Swizzleとかはまだよくわからないので、分かるようになったらそのうち書きます。)
45行目 : テクスチャIDに画像を付けます。
第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)で読み込んだ画像を比べてみます。(画像を変更しました)
<元の画像>
<LOAD_POT_QUALITY>
<LOAD_POT_FAST>
衝撃の、あまり変わらないという結果でした…どちらも質はよくないですね…
結局、テクスチャは、元からPOTのものにして、ふつうに読み込むのが一番きれいで制限がなさそうです。
P.S. せっかくのエイプリルフールなのに、ネタを入れる隙間すらなかったです…