2016-12-28 22 views
0

QOpenGLWidgetを使用してテクスチャ付きの三角形をレンダリングしましたが、コードは見栄えが良いですが、三角形は常に黒くレンダリングされていました。OpenGLのテクスチャが現在アクティブな場合レンダリングされません

これは、テクスチャがGL_TEXTURE0の場所をデフォルトにロードされると、私は最後にglActiveTexture(GL_TEXTURE1)を呼び出さない限り、コードは動作しません、GL_TEXTURE1が、それはどんなことができる一例であり、コードでありますテクスチャが実際にあるもの以外の他のテクスチャスロット。呼び出しがなければ、オブジェクトは黒になります。私はいくつかの他の空いているスロットをアクティブ化しない限り、

QImage ready; 
    QImage image("C:/Users/Gamer/Desktop/New folder/ring.jpg"); 
    ready = image.convertToFormat(QImage::Format_RGBA8888); 


    glGenTextures(1, &texture); 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glUniform1i(glGetUniformLocation(program.programId(), "samp"), 0); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ready.width(), ready.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, ready.constBits()); 
    glGenerateMipmap(GL_TEXTURE_2D); 
    glActiveTexture(GL_TEXTURE1) 

私は、複数のテクスチャを作成し、一度にすべてを表示し、最後のアクティブなテクスチャをいくつかのテストを試してみたが、常に黒色でした。

私はこれをどうすればいいのかわかりませんが、私はOpenGLとQtの初心者ですが、これは正しいとは言えません。

EDIT:

主な機能

#include "mainwindow.h" 
#include <QApplication> 
#include <QSurfaceFormat> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    QSurfaceFormat format; 
    format.setVersion(3, 3); 
    format.setProfile(QSurfaceFormat::CoreProfile); 
    format.setDepthBufferSize(24); 
    format.setStencilBufferSize(8); 
    format.setSamples(4); 
    format.setSwapInterval(0); 
    QSurfaceFormat::setDefaultFormat(format); 

    MainWindow w; 
    w.show(); 

    return a.exec(); 
} 

ウィジェットコード

#include "openglwidget.h" 
#include <QOpenGLShaderProgram> 
#include <QImage> 
#include <QDebug> 

OpenGLWidget::OpenGLWidget(QWidget *parent) : 
    QOpenGLWidget(parent) 
{ 

} 

OpenGLWidget::~OpenGLWidget() 
{ 
    glDeleteBuffers(1, &vbo); 
    glDeleteVertexArrays(1, &vao); 
    glDeleteTextures(1, &texture); 

} 

void OpenGLWidget::initializeGL() 
{ 
    QOpenGLFunctions_3_3_Core::initializeOpenGLFunctions(); 

    GLfloat vertices[] = { 
      0.0f, 0.75f, 0.0f, 
      -0.75f, -0.75f, 0.0f, 
      0.75f, -0.75f, 0.0f, 
      0.5f, 0.0f, 
      0.0f, 1.0f, 
      1.0f, 1.0f 
     }; 

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

    program.addShaderFromSourceFile(QOpenGLShader::Vertex, "C:/Users/Gamer/Desktop/New folder/vertex.vert"); 
    program.addShaderFromSourceFile(QOpenGLShader::Fragment, "C:/Users/Gamer/Desktop/New folder/fragment.frag"); 
    program.link(); 
    program.bind(); 

    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)36); 
    glEnableVertexAttribArray(1); 

    QImage ready; 
    QImage image("C:/Users/Gamer/Desktop/New folder/ring.jpg"); 
    ready = image.convertToFormat(QImage::Format_RGBA8888); 


    glGenTextures(1, &texture); 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture); 
    glUniform1i(glGetUniformLocation(program.programId(), "samp"), 0); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ready.width(), ready.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, ready.constBits()); 
    glGenerateMipmap(GL_TEXTURE_2D); 
// glActiveTexture(GL_TEXTURE1); 

} 

void OpenGLWidget::paintGL() 
{ 
    GLfloat yellow[] = {1.0, 1.0, 0.0, 0.0}; 

    glClearBufferfv(GL_COLOR, 0, yellow); 

    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

void OpenGLWidget::resizeGL(int w, int h) 
{ 
    glViewport(0, 0, w, h); 
} 

そしてシェーダあなたが必要

#version 330 core 

layout(location = 0) in vec3 pos; 
layout(location = 1) in vec2 coord; 

out vec2 tc; 

void main(void) 
{ 
    tc = coord; 
    gl_Position = vec4(pos, 1.0); 
} 

#version 330 core 

uniform sampler2D samp; 

in vec2 tc; 
out vec4 color; 

void main(void) 
{ 
    color = texture(samp, tc); 
} 
+0

ちょうどあなたがアクティブなユニットを最初に、あなたがそれにテクスチャをバインドしていることを確かめてください。 どのようにレンダリングしますか、サンプラーのユニフォームに何か正しいテクスチャユニット番号(0,1など)を指定していますか? – Swift

+0

私はちょうどあなたが言ったすべてを行うために、より多くのコードを貼り付けましたが、唯一の違いはglActiveTextureへの最後の呼び出しです。また、私はQOpenGLTextureを使用しようとしたことを言及する必要があります、同じことが起こっている、すなわち、それは別のテクスチャユニットをアクティブにせずに動作していません。 – Goran

+0

これはあなたのコードが他のテクスチャ(または0)をバインドしているように見えます。 – derhass

答えて

2

QOpenGLWidgetは、あなたが期待していないかもしれないいくつかの副作用があり、かなり複雑な抽象化です。 Qt5 docs

すべてのレンダリングは、OpenGLフレームバッファオブジェクトで行われます。 makeCurrent()がコンテキスト内で確実にバインドされていることを確認します。 paintGL()のレンダリングコードに追加のフレームバッファオブジェクトを作成してバインドするときは、この点に注意してください。フレームバッファーをID 0で再バインドしないでください。代わりに、defaultFramebufferObject()を呼び出してバインドする必要があるIDを取得してください。

今、これ自体は問題ではありません。しかし、initializeGL()方法(私の強調)の説明を見て:

この関数が呼び出されたときに、これはすでに行われているので、makeCurrent()を呼び出す必要はありません。 ただし、フレームバッファはまだこの段階では使用できませんので、ここからdrawコールを発行しないでください。そのような呼び出しをpaintGL()に延期してください。

今、これ自体はまだ問題ではありません。しかし、Qtは​​と最初のpaintGLの間にFBOを作成することを意味します。 QtはFBOのカラーバッファとしてテクスチャを作成するので、現在アクティブなテクスチャユニットを再利用し、確立したテクスチャバインディングを​​に変更します。

glActiveTextureをユニット0以外に設定すると、Qtはユニットのバインディングを壊しますが、ユニット0のみを使用するため、あなたの例では悪影響はありません。

+0

それは理にかなっていますが、いくつか質問があります。どのようにあなたはQtがアクティブなテクスチャユニットを再利用するのかを知っています – Goran

+0

QtがFBOとテクスチャを関連付けると、別の質問が出ます。他の答えが示唆したように、私はpaintGLの同じテクスチャユニットに再度テクスチャを再バインドしようとしました。 Qtがそのユニットを使用していれば安全ですか? – Goran

+1

本当に必要なら、ソースコード内で調べることができます。 ['QOpenGLWidget'](http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/kernel/qopenglwidget.cpp)は、[' QGLFramebufferObject'](http://コード。 qt.io/cgit/qt/qtbase.git/tree/src/opengl/qglframebufferobject.cpp)それ自体[テクスチャの作成とバインド](http://code.qt.io/cgit/qt/qtbase.git /tree/src/opengl/qglframebufferobject.cpp#n501)を初期化します。そのテクスチャバインディングが変更されても、そのテクスチャユニットを使用できないというわけではありません。テクスチャ単位を消費することはなく、テクスチャを使用するだけです。 – derhass

1

描画する前にテクスチャユニットにテクスチャをバインドする。テクスチャユニットの状態は、ユニフォームとは異なり、プログラム状態の一部ではありません。プログラム起動時にテクスチャユニットの状態を設定しようとするのは珍しいことです。これは、各プログラムに異なるテクスチャユニットを割り当てることを必要とします(質問から外れるわけではありません)。

は、ドローコールの前に、 paintGLに次の行を追加します。

glBindTexture(GL_TEXTURE_2D, texture); 
関連する問題