0

私は OpenGL を初めて使用し、複数のチュートリアルに従っています。オブジェクトをレンダリングするために使用される複数のメソッドがあることに気付きましたが、それでもそれらの違いと、それぞれをいつ使用するかがわかりませんか?

たとえば..シェーダーを使用して立方体をレンダリングするこのに従い、「通常の」方法を使用してレンダリングしようとしたとき-これが正しい式である場合。何もレンダリングされていません。私はいつも電話する必要がありshaderProgram.setAttributeArray()shaderProgram.enableAttributeArray()そしてshaderProgram.disableAttributeArray()

しかし、別の方法を使用して直接レンダリングしようとすると、これが正しい式である場合は、 and を使用glBegin()glEnd()ます。何も機能していません

また、シェーダーの概念自体に別の質問がありますが、いつ使用すべきか、いつ使用すべきでないかがよくわかりません

これが私の例です:

#include "glwidget.h"

GlWidget::GlWidget(QWidget *parent)
    : QGLWidget(QGLFormat(/* Additional format options */), parent)
{
    alpha = 25;
    beta = -25;
    distance = 2.5;
}

void GlWidget::initializeGL()
{
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    qglClearColor(QColor(Qt::white));

    shaderProgram.addShaderFromSourceFile(QGLShader::Vertex, ":/vertexShader.vsh");
    shaderProgram.addShaderFromSourceFile(QGLShader::Fragment, ":/fragmentShader.fsh");
    shaderProgram.link();

    vertices << QVector3D(-0.5, -0.5,  0.5) << QVector3D( 0.5, -0.5,  0.5) << QVector3D( 0.5,  0.5,  0.5) // Front
             << QVector3D( 0.5,  0.5,  0.5) << QVector3D(-0.5,  0.5,  0.5) << QVector3D(-0.5, -0.5,  0.5)
             << QVector3D( 0.5, -0.5, -0.5) << QVector3D(-0.5, -0.5, -0.5) << QVector3D(-0.5,  0.5, -0.5) // Back
             << QVector3D(-0.5,  0.5, -0.5) << QVector3D( 0.5,  0.5, -0.5) << QVector3D( 0.5, -0.5, -0.5)
             << QVector3D(-0.5, -0.5, -0.5) << QVector3D(-0.5, -0.5,  0.5) << QVector3D(-0.5,  0.5,  0.5) // Left
             << QVector3D(-0.5,  0.5,  0.5) << QVector3D(-0.5,  0.5, -0.5) << QVector3D(-0.5, -0.5, -0.5)
             << QVector3D( 0.5, -0.5,  0.5) << QVector3D( 0.5, -0.5, -0.5) << QVector3D( 0.5,  0.5, -0.5) // Right
             << QVector3D( 0.5,  0.5, -0.5) << QVector3D( 0.5,  0.5,  0.5) << QVector3D( 0.5, -0.5,  0.5)
             << QVector3D(-0.5,  0.5,  0.5) << QVector3D( 0.5,  0.5,  0.5) << QVector3D( 0.5,  0.5, -0.5) // Top
             << QVector3D( 0.5,  0.5, -0.5) << QVector3D(-0.5,  0.5, -0.5) << QVector3D(-0.5,  0.5,  0.5)
             << QVector3D(-0.5, -0.5, -0.5) << QVector3D( 0.5, -0.5, -0.5) << QVector3D( 0.5, -0.5,  0.5) // Bottom
             << QVector3D( 0.5, -0.5,  0.5) << QVector3D(-0.5, -0.5,  0.5) << QVector3D(-0.5, -0.5, -0.5);
}

void GlWidget::resizeGL(int width, int height)
{
    if (height == 0) {
        height = 1;
    }

    pMatrix.setToIdentity();
    pMatrix.perspective(60.0, (float) width / (float) height, 0.001, 1000);

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

void GlWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 mMatrix;
    QMatrix4x4 vMatrix;

    QMatrix4x4 cameraTransformation;
    cameraTransformation.rotate(alpha, 0, 1, 0);
    cameraTransformation.rotate(beta, 1, 0, 0);

    QVector3D cameraPosition = cameraTransformation * QVector3D(0, 0, distance);
    QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);

    vMatrix.lookAt(cameraPosition, QVector3D(0, 0, 0), cameraUpDirection);

    shaderProgram.bind();
    shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);

    // This code is able to draw the cube
    shaderProgram.setAttributeArray("vertex", vertices.constData());
    shaderProgram.enableAttributeArray("vertex");
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());
    shaderProgram.disableAttributeArray("vertex");
    // end

    // This code is never able to draw the cube or anything
    glBegin(GL_TRIANGLES);
    for (int var = 0; var < vertices.size(); ++var) {
        glVertex3f(vertices[var][0],vertices[var][1],vertices[var][2]);
    }
    glEnd();
    // end

    shaderProgram.release();
}
4

1 に答える 1

3

OpenGL には、「即時モード」と呼ばれるものがありました。その中で、 and を使用glBegin()glEnd()、その間にデータ (ポイント、法線、テクスチャ座標) をポイントごとに指定します。これをすべてのフレームで行うため、明らかにこれは非常に低速です。この機能は長い間廃止されてきましたが、既存のソフトウェアを壊さないように、ほとんどのグラフィックス カード ドライバはまだサポートしています。ただし、最新の OpenGL を学びたい場合はglBegin()、それに含まれるチュートリアルを無視します。現在、データを一度に GPU に転送し ( Vertex Buffer Objectと呼ばれるものに)、1 つのコマンドで ( Vertex Array Objectを使用して)描画します。

あなたの他の質問は、シェーダーに関するものでした。繰り返しますが、昔は、OpenGL には固定機能のパイプラインがありました。つまり、頂点 (法線など) のデータのみを指定すると、グラフィックス カードが動作し続けます。データの処理を変更できませんでした。現代の世界では、パイプラインの一部はプログラム可能です。つまり、パイプラインの一部の機能を変更できます (独自のプログラム (シェーダー) を提供することにより)。他の方法では達成できない効果がたくさんあるので、これは非常に便利です。繰り返しになりますが、独自のシェーダーを提供しない場合、互換性の理由から、グラフィック カードはほとんどデフォルトの実装に戻ります。ただし、必ず独自のシェーダーを作成する必要があります (基本的なシェーダーは数行です)。

全体として、最新の OpenGL (VBO、VAO、シェーダー) の学習を開始すると、基本を理解するのに少し時間がかかる可能性がありますが、レガシーの学習を開始すると、いつかそれを離れて最初からやり直す必要があります。最新のOpenGLを最初から学びます。

編集: 通常、最新のコードと従来のコードを混在させることはお勧めできません。うまくいくかもしれませんが、苦労する価値はありません。

于 2015-01-12T22:57:13.763 に答える