私は opengl-es 2.0 を使用するプロジェクトに取り組んでおり、透視投影の設定に問題があります。
透視投影を設定せず、オブジェクトからワールドへのマトリックス (モデル マトリックスとも呼ばれると思います) に頂点位置を単純に掛けると、画面上のオブジェクトは正しくレンダリングされ、引き伸ばされて表示されますが、私は知っています、それは射影行列が修正するものです。問題は、パースペクティブ マトリックスを設定して使用するたびに、画面上のオブジェクトが消え、どれだけ動かしても画面に表示されないことです。
Model-View-Projection マトリックスを取得するための計算は CPU で行われ、MVP-Matrix と実際のオブジェクト空間の頂点データとの最後の乗算は頂点シェーダーで行われます。これが、問題がプロセスにあると思われる理由です。その MVP-Matrix を取得します。一連の単体テストを実行しましたが、それらのテスト (および線形代数に関する私の基本的な知識) によると、これらの行列は正しく計算されており、1 日中インターネットで調査しても今のところ役に立ちません。:-/
これは、MVP-Matrix を計算するために使用するコードです。
Matrix4D projection_matrix;
projection_matrix.makePerspective(45.0f, 0.001f, 100.0f, 480.0f/320.0f);
Matrix4D view_matrix;
view_matrix.makeIdentity(); //Should be a real view matrix. TODO.
Matrix4D model_matrix(getWorldMatrix());
Matrix4D mvp_matrix(projection_matrix);
mvp_matrix *= view_matrix;
mvp_matrix *= model_matrix;
mMesh->draw(time, mvp_matrix.getRawData());
このコードは一目瞭然だと思いますが、念のため、これらの Matrix4D は 4x4 マトリックスであり、それらに対して makePerspective/makeIdentity を呼び出すと、そのマトリックスがパースペクティブまたはアイデンティティ マトリックスになります。Matrix4D オブジェクトの getRawData() 呼び出しは、行列データを列優先表記の float 配列として返します。mMesh 変数は別のオブジェクトであり、draw が呼び出されると、すべての頂点とマテリアル データをシェーダーに単純に送信します。
makePerspective 関数のコードは次のとおりです。
Matrix4D& Matrix4D::makePerspective(const float field_of_view,
const float near, const float far, const float aspect_ratio) {
float size = near * tanf(DEGREES_TO_RADIANS(field_of_view) / 2.0f);
return this->makeFrustum(-size, size, -size / aspect_ratio,
size / aspect_ratio, near, far);
}
Matrix4D& Matrix4D::makeFrustum(const float left, const float right,
const float bottom, const float top, const float near,
const float far) {
this->mRawData[0] = 2.0f * near / (right - left);
this->mRawData[1] = 0.0f;
this->mRawData[2] = 0.0f;
this->mRawData[3] = 0.0f;
this->mRawData[4] = 0.0f;
this->mRawData[5] = 2.0f * near / (top - bottom);
this->mRawData[6] = 0.0f;
this->mRawData[7] = 0.0f;
this->mRawData[8] = (right + left) / (right - left);
this->mRawData[9] = (top + bottom) / (top - bottom);
this->mRawData[10] = - (far + near) / (far - near);
this->mRawData[11] = -1.0f;
this->mRawData[12] = 0.0f;
this->mRawData[13] = 0.0f;
this->mRawData[14] = -2.0f * far * near / (far - near);
this->mRawData[15] = 0.0f;
return *this;
}
getWorldMatrix() 呼び出しはこれを行います (いくつかの関連コードを使用):
const Matrix4D& getWorldMatrix() {
return mWorldMatrix =
getTranslationMatrix() *
getRotationMatrix() *
getScaleMatrix();
}
const Matrix4D& getRotationMatrix() {
return this->mRotationMatrix.makeRotationFromEuler(this->mPitchAngle,
this->mRollAngle, this->mYawAngle);
}
const Matrix4D& getTranslationMatrix() {
return this->mTranslationMatrix.makeTranslation(this->mPosition.x,
this->mPosition.y, this->mPosition.z);
}
const Matrix4D& getScaleMatrix() {
return this->mScaleMatrix.makeScale(this->mScaleX, this->mScaleY, this->mScaleZ);
}
///This code goes in the Matrix4D class.
Matrix4D& Matrix4D::makeTranslation(const float x, const float y,
const float z) {
this->mRawData[0] = 1.0f;
this->mRawData[1] = 0.0f;
this->mRawData[2] = 0.0f;
this->mRawData[3] = 0.0f;
this->mRawData[4] = 0.0f;
this->mRawData[5] = 1.0f;
this->mRawData[6] = 0.0f;
this->mRawData[7] = 0.0f;
this->mRawData[8] = 0.0f;
this->mRawData[9] = 0.0f;
this->mRawData[10] = 1.0f;
this->mRawData[11] = 0.0f;
this->mRawData[12] = x;
this->mRawData[13] = y;
this->mRawData[14] = z;
this->mRawData[15] = 1.0f;
return *this;
}
Matrix4D& Matrix4D::makeScale(const float x, const float y,
const float z) {
this->mRawData[0] = x;
this->mRawData[1] = 0.0f;
this->mRawData[2] = 0.0f;
this->mRawData[3] = 0.0f;
this->mRawData[4] = 0.0f;
this->mRawData[5] = y;
this->mRawData[6] = 0.0f;
this->mRawData[7] = 0.0f;
this->mRawData[8] = 0.0f;
this->mRawData[9] = 0.0f;
this->mRawData[10] = z;
this->mRawData[11] = 0.0f;
this->mRawData[12] = 0.0f;
this->mRawData[13] = 0.0f;
this->mRawData[14] = 0.0f;
this->mRawData[15] = 1.0f;
return *this;
}
Matrix4D& Matrix4D::makeRotationFromEuler(const float angle_x,
const float angle_y, const float angle_z) {
float a = cosf(angle_x);
float b = sinf(angle_x);
float c = cosf(angle_y);
float d = sinf(angle_y);
float e = cosf(angle_z);
float f = sinf(angle_z);
float ad = a * d;
float bd = b * d;
this->mRawData[0] = c * e;
this->mRawData[1] = -bd * e + a * f;
this->mRawData[2] = ad * e + b * f;
this->mRawData[3] = 0.0f;
this->mRawData[4] = -c * f;
this->mRawData[5] = bd * f + a * e;
this->mRawData[6] = -ad * f + b * e;
this->mRawData[7] = 0.0f;
this->mRawData[8] = -d;
this->mRawData[9] = -b * c;
this->mRawData[10] = a * c;
this->mRawData[11] = 0.0f;
this->mRawData[12] = 0.0f;
this->mRawData[13] = 0.0f;
this->mRawData[14] = 0.0f;
this->mRawData[15] = 1.0f;
return *this;
}
最後に、頂点シェーダーはほぼ次のとおりです。
#version 110
const float c_one = 1.0;
const float c_cero = 0.0;
uniform float time;
uniform mat4 mvp_matrix;
attribute vec3 position;
attribute vec3 normal;
attribute vec2 texture_coordinate;
varying vec2 v_texture_coordinate;
void main()
{
gl_Position = mvp_matrix * vec4(position, c_one);
v_texture_coordinate = texture_coordinate;
}
念のため、レンダリングされるオブジェクトは、3 つの軸すべてに 0.5f スケールが適用された位置 (0.0f、0.0f、-3.0f) にレンダリングされます。
何が間違っている可能性があるのか よくわかりません。誰かが私が見逃している可能性があるものを見つけてくれることを願っています。シェーダーで頂点ごとの結果を取得できれば、これをデバッグするのがずっと簡単になります:-/。
補足として、私が知っている限り、ビューまたはカメラの行列を計算する方法について疑問があります。カメラを右に 100 単位移動します。私は左に 100 単位移動しますよね?
編集:より多くの情報を提供しようとしているだけで、誰かが私を助けることができるかもしれません. 上記のコードではモデル マトリックスが正しくないことに気付きました。主にマトリックスの順序が原因で、次のように変更したところ、モデル マトリックスは適切に見えます。
const Matrix4D& getWorldMatrix() {
return mWorldMatrix =
getScaleMatrix() * getRotationMatrix() * getTranslationMatrix();
}
それにもかかわらず、まだ運がありません。私のテストデータから得られた行列は次のとおりです。
Projection matrix:
[1.609506,0.000000,0.000000,0.000000]
[0.000000,2.414258,0.000000,0.000000]
[0.000000,0.000000,-1.000020,-0.002000]
[0.000000,0.000000,-1.000000,0.000000]
Model matrix:
[0.500000,0.000000,0.000000,0.000000]
[0.000000,0.500000,0.000000,0.000000]
[0.000000,0.000000,0.500000,-3.000000]
[0.000000,0.000000,0.000000,1.000000]
MVP matrix:
[0.804753,0.000000,0.000000,0.000000]
[0.000000,1.207129,0.000000,0.000000]
[0.000000,0.000000,2.499990,-0.001000]
[0.000000,0.000000,-1.000000,0.000000]
そして、これらすべてをテストするために私が使用しているメッシュは、原点を中心として、各軸で 1.0f から -1.0f までの単純な立方体です。私が知る限り、これにより、z 軸に沿って -2.0f の位置に近い限界 (0.0001f) に最も近い頂点を配置する必要があるため、立方体はカメラの前にあり、視錐台の内側にあります。誰かの手がかりはありますか?