0

立方体をQSplitter内のQGLWidgetputにレンダリングしようとしています。1:1の比率にしたいので、立方体であり、ウィンドウの寸法に関係なくその比率を維持します。しかし、私はこれを機能させることができませんでした。私が何をしても、立方体は窓に沿って伸びます。

コードの動作に関して、さらに2つの問題があります。

  • matrix.setToIdentity()の最後に発生する投影と変換を除くすべてをリセットするinitializeGL()ため、で呼び出すとresizeGL()、前に行列を同一に設定した場合でも、投影は前の投影と結合します。

  • の議論aspect ratiomatrix.perspective()何もしていないようです。効果のないいくつかの値を試しました。

  • 何らかの理由で、投影は正投影であり、遠近法ではありません。

  • マトリックスは、後もIDですが、この順序で呼び出しperspective()た場合に限ります。setToIdentity()perspective()resizeGL

  • での行列演算initializeGL()resizeGL()異なる処理を取得します。translate()を呼び出さないと、perspective()後で呼び出しinitializeGL()てもキューブは表示されませんresizeGL()

誰かが私にこれを説明できますか?クラスは行列を3D変換に保持するためにここにあると思ったQMatrix4x4ので、自分でそれらを実装する必要はありません。

いくつかのチュートリアルを見てきましたが、同じようにある種の行列を使用しているか、非推奨のOpenGL関数を使用しているようです。幅と高さをフロートにキャストし、変換に個別の行列を使用してみました。

1:1の比率を機能させるにはどうすればよいですか?

私のコードの関連部分:

void ModelView::initializeGL()
{
    m_program = new QGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentShaderSource);
    m_program->link();

    GLuint shader_id = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(shader_id, 1, vertexShaderSource, NULL);
    glCompileShader(shader_id);
    ShaderIds[2] = shader_id;

    shader_id = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(shader_id, 1, fragmentShaderSource, NULL);
    glCompileShader(shader_id);
    ShaderIds[1] = shader_id;

    glAttachShader(ShaderIds[0], ShaderIds[1]);
    glAttachShader(ShaderIds[0], ShaderIds[2]);

    glLinkProgram(ShaderIds[0]);*/

    matrix.setToIdentity(); //--------------------------------------

    float aspect = (((float)width())/((float)height()));

    matrix.perspective(60, aspect, 0.1, 100.0);
    matrix.translate(0, 0, -2);
}

void ModelView::paintGL()
{
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);

    glClearColor(.5f, .5f, .5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0, 0, width(), height());

    m_program->bind();

    m_posAttr = m_program->attributeLocation("posAttr");
    m_colAttr = m_program->attributeLocation("colAttr");
    m_matrixUniform = m_program->uniformLocation("matrix");
    m_program->setUniformValue(m_matrixUniform, matrix); //-----------------

    glGenBuffers(1, &BufferId);
    glGenBuffers(1, &IndexBufferId);

    glBindBuffer(GL_ARRAY_BUFFER, BufferId);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);

    glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, 0);
    glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid *)RgbOffset);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);

    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

    m_program->release();

}

void ModelView::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    matrix.setToIdentity();  //------------------------------------

    matrix.translate(0, 0, -2);
    matrix.perspective(60, ((float)w)/((float)h), 0.1, 100.0);

    updateGL();
}
4

1 に答える 1

1

最後に何が間違っているかを見つけました。

まず、行列演算は にあってはなりませんinitializeGL()。正確な理由はわかりません。resizeGL()最初のフレーム レンダーのどこかで呼び出されるため、正しい (考えてみれば妥当な) 場所はです。

第 2 に、行列の乗算には定義された順序があり、遠近法 > 平行移動 > 回転のようになります。そうしないと、台無しになります。

したがって、正しい(または少なくとも機能する)コードはresizeGL()次のようになります。

glViewport(startX, startY, width, height);    //resize the viewport
matrix.setToIdentity();             //reset the uniform value (matrix)
perspectiveMatrix.setToIdentity();   //reset the projection matrix
                                       //set new projection (aspect ratio)
perspectiveMatrix.perspective(angle, (float)width/(float)height, nearPlane, farPlane);

matrix *= perspectiveMatrix;    //apply transformations
matrix *= translationMatrix;
matrix *= rotationMatrix;

updateGL();                  //re-render
于 2013-03-09T23:45:14.690 に答える