Miyabiarts.net

一年に一度の更新頻度

テクスチャ表示

今回はテクスチャを張ります。
今回もコードはgithubにあります。
これからは、このシリーズは1つのソリューション内に別のプロジェクトとして追加していくことにしました。

テクスチャの準備

はじめにテクスチャを管理するためのハンドラをGL.GenTexturesで作成します。
次に、そのテクスチャに対する設定を行うため、GL.BindTextureで設定対象とします。
GL.TexParameterで色々設定することができます。
とりあえずここでは、縮小・拡大するときに補間方法を線形フィルタに指定しています。

GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

テクスチャの中身を作るにはGL.TexImage2Dを使います。
以下の例では、512×512の32ビットRGBA画像を作っています。

int texSize = 512;
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texSize , texSize , 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);

通常は、ファイルから画像を読み込んでから表示したいでしょうから、その場合は以下のように画像を読み込んで、その画像データをテクスチャに転送してやります。

Bitmap bitmap = new Bitmap("texture.png");
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);

頂点形式

今回はテクスチャを張った平面を表示するためPlaneクラスを作ります。
各頂点にはテクスチャを参照するUV座標が必要となるため、以下のように頂点座標・UV座標を持った頂点形式を用います。
頂点バッファを作成する処理などは前回と同様です。

class Plane
{
  struct Vertex
  {
    public Vector3 position;
    public Vector2 texcoord;

    public Vertex(Vector3 position, Vector2 texcoord)
    {
      this.position = position;
      this.texcoord = texcoord;
    }
    public static readonly int Stride = Marshal.SizeOf(default(Vertex));
  }
  ...
}

シェーダ

頂点シェーダ(textured.vert)

頂点シェーダには、頂点形式と同様に頂点座標とUV座標をattribute変数として与えます。
また、フラグメントシェーダに対してUV座標を渡す、varying変数を用意しておきます。
uniform変数に対する値の設定方法は前回と同様です。

attribute vec3 position;
attribute vec2 texcoord;
uniform mat4 world;
uniform mat4 viewProjection;
varying vec2 uv;
void main(void)
{
	gl_Position = viewProjection * world * vec4(position, 1.0);
	uv = texcoord;
}

フラグメントシェーダ(textured.frag)

フラグメントシェーダでは、sampler2D型のuniform変数を定義することでテクスチャにアクセスします。
sampler2D型は名前が示していますが、テクスチャそのものではなく、テクスチャとそれからのサンプリング方法がセットになっている型だと考えてください。
そして、texture2D関数にsampler2DとUV座標を渡すことによって、テクスチャから色情報を取得することができます。
sampler2D型のuniform変数の設定方法は次で説明します。

uniform sampler2D tex;
varying vec2 uv;
void main(void)
{	
	gl_FragColor = texture2D(tex,uv);
}

テクスチャの設定

フラグメントシェーダが持つsampler2D型のuniform変数は、前回のようにテクスチャのハンドラを直接設定することではできません。
以下のように、一度テクスチャユニットに対して、テクスチャのハンドラを設定した後で、uniform変数に対してそのテクスチャユニットのインデックスを与えます。
テクスチャユニットは、GL.Uniform1を使って1次元の値として設定します。

あとは、正しい頂点形式を持つオブジェクトをレンダリングしてやれば、テクスチャが上手く表示されます。

GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, tex);
GL.Uniform1(GL.GetUniformLocation(program, "tex"), 0);

plane.Render();

後処理

最後にテクスチャの破棄をしましょう。

GL.DeleteTexture(1,ref tex);
広告

Comments are closed.

%d人のブロガーが「いいね」をつけました。