在Opengl ES 2.0上设置透视投影会使对象消失

时间:2011-08-15 17:18:06

标签: matrix opengl-es-2.0 projection-matrix

我正在使用opengl-es 2.0开发一个项目,我在设置透视投影时遇到了一些麻烦。

如果我没有设置透视投影并简单地将对象到世界矩阵(我相信它也称为模型矩阵)乘以顶点位置,则屏幕上的对象会正确渲染,它们会显示为拉伸,但是据我所知,投影矩阵会解决这个问题。问题是,每当我设置透视矩阵并使用它时,屏幕上的对象就会消失,无论我移动多少它们都不会出现在屏幕上。

获取模型 - 视图 - 投影矩阵的计算是在CPU中完成的,最后的乘法MVP-Matrix是由实际的对象空间顶点数据在顶点着色器中完成的,这就是为什么我认为问题可能是关于获得MVP-Matrix的过程。我已经运行了一系列单元测试,但根据这些测试(以及我对线性代数的基本知识),这些矩阵正在被正确计算,而我整天的网络研究现在都无济于事。 : - /

这是我用来计算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会使该矩阵成为Perspective或Identity矩阵。对Matrix4D对象的getRawData()调用将矩阵数据作为以float-major表示法的float数组返回,而mMesh变量是另一个对象,当调用draw时,它将简单地将所有顶点和材质数据发送到着色器。 / p>

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;
}

以防万一,正在渲染的物体在位置(0.0f,0.0f,-3.0f)上渲染,0.5f比例应用于所有三个轴。

我真的不知道可能出现什么问题,我希望有人能发现我可能遗漏的内容,任何帮助都会受到赞赏。如果我可以在着色器上获得每顶点结果,那么调试这将更容易: - /。

作为旁注,我对如何计算视图或相机矩阵有疑问,据我所知它只是一个带有相机必须做的倒置变换的矩阵,我明白这一点,如果我想将相机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轴将最接近近界限(0.0001f)的顶点定位在-2.0f位置,因此立方体位于摄像机前方并且具有视锥体。有人提出任何线索吗?

0 个答案:

没有答案