日別アーカイブ: 2009年8月2日

OpenGLES2.0 D3D座標系

Direct3D と OpenGL は座標系が違います。
そのためデータの Exporter を作るときは、どのプラットフォームにも対応できるよう
いつも両対応で作っています。

Direct3D から見ると両対応は簡単です。
というのも、Maya や XSI など多くのツールが OpenGL の右手座標系なので、
D3D の左手系に合わせるにはもともと座標系の変換処理が必要だからです。
OpenGL に対応するには反転しなければ良いだけ。

ただ OpenGLES 2.0 の場合ジオメトリもライティングもシェーダーだけで行いますし
演算式も任意です。汎用化された GPU では実装に任されているので、座標系の
違いをあまり意識しなくても良いのかもしれません。

普段使っているライブラリやシェーダーを流用することを考えて、Direct3D の
左手座標系でそのまま使ってみました。いつもの感覚でシェーダーやマトリクスの
セットを行っていたら自然にそうなりました。

OpenGL の場合も Depth Buffer の初期値はデフォルトで 1.0 を設定するようです。
比較関数も初期値は GL_LESS なので D3D と違いはありません。
Matrix の設定もモデルデータもシェーダーも D3D と同じパラメータで良いようです。

唯一変更したのは下記の設定のみ。
デフォルトは GL_CCW なので GL から見るとカリングが逆になります。

glFrontFace( GL_CW );

あとはデータもシェーダーも matrix も D3D 互換で使えます。

シェーダーはまだ GLSL のテストをしている状態です。
アニメーションはまだ未確認。

// vsh
uniform mat4	pmatrix;

attribute vec3	vposition;
attribute vec3	vnormal;
attribute vec2	vtexcoord;

varying vec4	ocolor;
varying vec2	otexcoord;

void main()
{
    gl_Position= pmatrix * vec4( vposition.xyz, 1 );

    vec3  lightdir= vec3( 0.0, 0.0, -1.0 );
    ocolor= vec4( 1.0, 1.0, 1.0, 1.0 ) * clamp( dot( vnormal, lightdir ), 0.0, 1.0 ) + 0.2;
    otexcoord= vtexcoord;
}
// fsh
precision mediump float;
varying	vec4   ocolor;
varying	vec2   otexcoord;

uniform sampler2D   texture0;

void main()
{
    vec4   tcol= texture2D( texture0, otexcoord );
    gl_FragColor= ocolor * tcol;
}
// cpp
struct v_type3 {
    float x, y, z;
};
struct v_type2 {
    float x, y;
};

static const v_type3	vdata_p[]= {
    {	-1.0f,	 1.0f,	0.0f,	},
    {	 1.0f,	 1.0f,	0.0f,	},
    {	-1.0f,	-1.0f,	0.0f,	},
    {	 1.0f,	-1.0f,	0.0f,	},
};

static const v_type3	vdata_n[]= {
    {	0.0f,	0.0f,	-1.0f,	},
    {	0.0f,	0.0f,	-1.0f,	},
    {	0.0f,	0.0f,	-1.0f,	},
    {	0.0f,	0.0f,	-1.0f,	},
};

static const v_type2	vdata_t[]= {
    {	0.0f,	0.0f,	},
    {	1.0f,	0.0f,	},
    {	0.0f,	1.0f,	},
    {	1.0f,	1.0f,	},
};

glVertexAttribPointer( attr_vposition, 3, GL_FLOAT, GL_FALSE, sizeof(v_type3), vdata_p );
glVertexAttribPointer( attr_vnormal, 3, GL_FLOAT, GL_FALSE, sizeof(v_type3), vdata_n );
glVertexAttribPointer( attr_vtexcoord, 2, GL_FLOAT, GL_FALSE, sizeof(v_type2), vdata_t );

glEnableVertexAttribArray( attr_vposition );
glEnableVertexAttribArray( attr_vnormal );
glEnableVertexAttribArray( attr_vtexcoord );

static unsigned short	idata[]= {
    0, 1, 2,
    2, 1, 3,
};

MatrixF	projection;
MatrixF	view;
MatrixF	world;

projection.SetProjection( ScreenWidth, ScreenHeight, 1.0f, 5000.0f, DEGtoRAD( 30.0f ) );
view.SetIdentity();
view.Translation( 0.0f, 0.0f, 20.0f );
world.SetIdentity();
world.RotationY( rotang );

MatrixF	mat;
mat.Mul( projection, view );
mat.Mul( world );

glUniformMatrix4fv( attr_pmatrix, 1, GL_FALSE, &mat._11 );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, idata );

関連エントリ
OpenGLES2.0 シェーダー管理