-2

私は現在、自分が書いているゲーム エンジン用の小さなエディターに取り組んでいます。新しいモデルを作成してレンダリング エンジン マネージャーに追加するモデルを追加するオプションがある Qt 5.6 でファイル メニューを設定しました。Mac OSX 10.11 (OpenGL 3 または 4) では問題なく動作します。Ubuntu 16.04 では、わずかにしか機能しません。メイン ループの外で、必要な数のモデルを初期化できます。ただし、メイン ループ内では、メイン ループ外で初期化した数のモデルしか初期化できません。IDE 内で gdb をプルアップすると、問題は VAO に関連しているようです。OSX では、メッシュを作成する場所に関係なく、モデルごとに新しい VAO が初期化されます。Ubuntu では、メイン ループの外側で、メッシュごとに新しい VAO が生成されます。メイン ループの内側で描画されるメッシュはすべて、メイン ループの外側で以前に作成されたメッシュと同じ VAO を持ちます。

要約すると、Ubuntu では、メイン ループの外側にあるすべてのモデルが独自の VAO を取得します。メイン ループ内で、VAO Gluint ハンドルが再び 2 から再カウントを開始します。ハンドル/タグのカウントが過ぎても、メイン ループの外で多くのモデルが初期化されると、モデルは描画を停止します。1 つの Mac OSX で問題なく動作します。これは OpenGL/Qt の問題であると思われるため、エンジン用の余分なコードがたくさんありますが、質問するのは当然だと思います。リンク: https://github.com/BennetLeff/engine

かなりの数のファイルがあるので、必要と思われるものだけを含めますが、github プロジェクトにもリンクします。大きなコード ダンプで申し訳ありませんが、他に提供できるものがあれば教えてください。

メッシュ.cpp

#include "Mesh.h"
#include "Transform.h"

#include <stdio.h>

Mesh::Mesh(std::vector<glm::vec3> vertices, std::vector<glm::vec3> normals, std::vector<glm::vec2> textures, std::vector<GLuint> indices)
{
    drawCount_ = indices.size();

  glGenVertexArrays(1, &vertexArrayObject_);
    glBindVertexArray(vertexArrayObject_);

    glGenBuffers(NUMBUFFERS, vertexBufferObject_);

    // Position Attrib
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject_[POSITION_VB]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);

    // Texture Attrib
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject_[TEXCOORD_VB]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(textures[0]) * textures.size(), textures.data(), GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);

  // Normals Attrib
  glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject_[NORMAL_VB]);
  glBufferData(GL_ARRAY_BUFFER, sizeof(normals[0]) * normals.size(), normals.data(), GL_STATIC_DRAW);
  glEnableVertexAttribArray(2);
  glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferObject_[INDEX_VB]);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(), GL_STATIC_DRAW);

    glBindVertexArray(0);

  fprintf(stderr, "vao val %d\n", vertexArrayObject_);
}

Mesh::~Mesh()
{
    glDeleteVertexArrays(1, &vertexArrayObject_);
}

void Mesh::draw()
{
  glBindVertexArray(vertexArrayObject_);
    glDrawElements(GL_TRIANGLES, drawCount_, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
  if (glGetError())
      printf("GL error %d", glGetError());
}

メイン.cpp

#include <stdio.h>

#ifdef __APPLE__
    #include <OpenGL/gl3.h>
#else
    #include <GL/glew.h>
#endif

#include "Camera.h"
#include "Model.h"

#include "Editor.h"
#include "RenderEngine.h"

#include <QApplication>

bool quit = false;

int main(int argc, char* argv[])
{
    auto WIDTH = 1024;
    auto HEIGHT = 800;

    /* 
     * Sets up a QApplication
     * with the proper formatting. This allows
     * GL versions to be set and so forth. Then
     * the QApplication is polled in the main loop
     * for events.
    */

    QApplication app(argc, argv);
    QSurfaceFormat format;
    format.setSamples(16);
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(4, 3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    QSurfaceFormat::setDefaultFormat(format);

    // Sets up Rendering Engine and Editor.
    auto cam = new Camera(glm::vec3(0, 6, -20), 70.0f, (float) WIDTH / (float) HEIGHT, 0.01f, 1000.0f);
    RenderEngine* engine = new RenderEngine(cam);
    Editor editor(engine, WIDTH, HEIGHT);

    editor.showEditor();

    /*
     * Must call Editor.show() before any other
     * OpenGL calls. This is mostly because of Qt.
    */
    // auto house = Model("./res/farm house/OBJ/Farmhouse OBJ.obj", "./res/farm house/Textures/Farmhouse Texture.jpg");
    // house.transform->getPosition()->z = 40;

    // auto model = Model("./res/Alfred/Alfred.obj", "./res/Alfred/alfred_dif.png");
    // auto model2 = Model("./res/Alfred/Alfred.obj", "./res/Alfred/alfred_dif.png");

    float counter = 0.0f;

    while (editor.isVisible())
    {
        app.processEvents();
        // model.transform->getRotation()->y = float(editor.getSliderValue()) / 10;
        // model.transform->getPosition()->z = editor.getManValue();
        counter += 0.1f;

        /*
         * Just updating window for now because
         * it may be faster. Need to benchmark this
         * and determine what is necessary.
        */
        editor.getWindow()->update();
    }

    return 0;
}

GUIWindow.cpp (QOpenGLWidget、QOpenGLFunctions から継承)

#include <GL/glew.h>
#include "GUIWindow.h"

GUIWindow::GUIWindow(QWidget* parent, RenderEngine* engine) :
    QOpenGLWidget(parent), engine(engine) { }

void GUIWindow::initializeGL()
{
    // Set up the rendering context, load shaders and other resources, etc.:
    initializeOpenGLFunctions();

    // If not on OSX we need to include
    // OpenGL as an extension
    #ifndef __APPLE__
        glewExperimental = GL_TRUE;

        GLenum err = glewInit();
        if (GLEW_OK != err) {
            /* Problem: glewInit failed, something is seriously wrong. */
            fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
        }
    #endif

    // Depth test not enabled by default.
    glEnable(GL_DEPTH_TEST);
}

void GUIWindow::resizeGL(int w, int h) {  }

void GUIWindow::paintGL()
{
    // Draw the scene
    clear(0.1, 0.4, 0.6, 1.0);

    // Draw all Models
    engine->draw();
}

void GUIWindow::clear(float r, float g, float b, float a)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glClearColor(r, g, b, a);
}

GUIWindow::~GUIWindow() { }

Model.cpp (AssImp からデータを取得するモデルの読み込みを除く)

void Model::draw(Camera* cam)
{
    shader.draw();
    shader.update(transform, cam);
    tex.bind(0);
    modelMesh->draw();
}

void Model::bindTexture(Texture tex)
{
    this->tex = tex;
}

RenderingEngine.cpp

#include "RenderEngine.h"

RenderEngine::RenderEngine(Camera* cam)
    : cam(cam)
{
    this->init();
}

void RenderEngine::init()
{
    // If not on OSX we need to include
    // OpenGL as an extension
    #ifndef __APPLE__
        glewExperimental = GL_TRUE;

        GLenum err = glewInit();
        if (GLEW_OK != err) {
            /* Problem: glewInit failed, something is seriously wrong. */
            fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
        }

        glEnable(GL_DEPTH_TEST);
    #endif
}

void RenderEngine::addModel(Model model)
{
    printf("added model \n");
    this->models.push_back(model);
    for (int i = 0; i < this->models.size(); i++)
        printf("Model Pos: (%g, %g, %g) \n", models[i].transform->getPosition()->x,
               models[i].transform->getPosition()->y,
               models[i].transform->getPosition()->z);
    printf("there are %d models now \n", this->models.size());
}

void RenderEngine::draw()
{
     for (int i = 0; i < this->models.size(); i++)
        models[i].draw(this->cam);
}

Editor.cpp (ウィンドウを設定したほとんどの Qt 呼び出しを除く)

#include "Editor.h"

Editor::Editor(RenderEngine* renderEngine, int width, int height)
{
    frame = 0;
    this->width = width;
    this->height = height;
    this->engine = renderEngine;
    this->window = new GUIWindow(0, renderEngine);
}

void Editor::initialize()
{
    // Set up the rendering context, load shaders and other resources, etc.:
    // initializeOpenGLFunctions();
    glViewport(0, 0, width, height);
    setupWidgets();
}


float Editor::getRandNum()
{
    srand(time(0));
    float num = rand() % 10 + 1;
    fprintf(stderr, "%d \n", num);
    return num;
}

void Editor::addModelToScene()
{
    srand (time(NULL));

    auto trans = new Transform();
    trans->getPosition()->x = rand() % 10 + 1;
    trans->getPosition()->y = rand() % 10 + 1;
    trans->getPosition()->z = rand() % 10 + 1;
    engine->addModel(Model("./res/Alfred/Alfred.obj", "./res/Alfred/alfred_dif.png", trans));
    fprintf(stderr, "Add a Model \n");
}

void Editor::showEditor()
{
    // Sets up the rest of the widgets locations.
    setupWidgets();
    // Sets up the QMainWindow.
    this->show();
}

void Editor::addModel(Model model)
{
    engine->addModel(model);
}
4

1 に答える 1

1

反対票を投じた理由はわかりませんが、ようやく問題がわかりました。に電話する直前にEditor::addModelToScene()電話する必要がありました。なぜこれがOSXで機能するのか、まったくわかりません。また、これを試すアイデアをくれたこの回答にも感謝します。window.makeCurrent()addModel()

于 2016-05-26T05:11:22.493 に答える