Qt5

2013-06-20 24 views
5
ile kapalı ekran oluşturma (openGL)

Bazı görüntü işleme yapmak için openGL kullanarak, ilk deneme renkli görüntüyü griye dönüştürür, her şey yolundadır, ancak ben istemiyorum.Qt5

“show()” i çağırmazsam, QGLWidget dokuyu oluşturmaya başlamaz Dokümanı pencere öğesi olmadan gösterebilir miyim? QGLKullanmak için doğru bir araç mı? kodlarının

bölüm

#include <QDebug> 

#include "toGray.hpp" 

toGray::toGray(std::string const &vertex_file, std::string const &fragment_file, QWidget *parent) 
    :basicGLWidget(vertex_file, fragment_file, parent) //read shaders, compile them, allocate VBO 
{ 
} 

void toGray::initializeVertexBuffer() 
{ 
    std::vector<GLfloat> const vertex{ 
     -1.0f, 1.0f, 0.0f, 1.0f, 
     1.0f, 1.0f, 0.0f, 1.0f, 
     -1.0f, -1.0f, 0.0f, 1.0f, 
     1.0f, 1.0f, 0.0f, 1.0f, 
     1.0f, -1.0f, 0.0f, 1.0f, 
     -1.0f, -1.0f, 0.0f, 1.0f, 
    }; 

    initializeVertexBufferImpl(vertex); //copy the data into QOpenGLBuffer 

    QImage img(":/simpleGPGPU/images/emili.jpg"); 
    texture_addr_ = bindTexture(img); 
    resize(img.width(), img.height()); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
} 

void toGray::paintGL() 
{ 
    qglClearColor(Qt::white); 
    glClear(GL_COLOR_BUFFER_BIT); 

    program_.bind(); 
    bind_buffer(); 
    program_.enableAttributeArray("qt_Vertex"); 
    program_.setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 4); 

    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture_addr_); 

    glDrawArrays(GL_TRIANGLES, 0, get_buffer(0).size()); 

    program_.disableAttributeArray("qt_Vertex"); 
    program_.release(); 
    glActiveTexture(0); 
    release_buffer(); 
} 

tepe tarayıcı

attribute highp vec4 qt_Vertex; 
varying highp vec2 qt_TexCoord0; 

void main(void) 
{  
    gl_Position = qt_Vertex; 
    qt_TexCoord0 = (qt_Vertex.xy + vec2(1.0)) * 0.5; 
} 

parça gölgelendirici

uniform sampler2D source; 
varying highp vec2 qt_TexCoord0; 

vec3 toGray(vec3 rgb) 
{ 
    return vec3(rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114); 
} 

void main(void) 
{   
    vec3 gray = toGray(texture2D(source, qt_TexCoord0).rgb); 
    gl_FragColor = vec4(gray, 0.0); 
} 

Düzenleme: işlemek ekran dışında yapmak QWindow FBO kullanın, ancak sonuç boş bir resimdir

kodları derleyebilir, ancak QOpenGLFrameBufferObject tarafından döndürülen QImage boştur.

.hpp

#ifndef OFFSCREENEXP_HPP 
#define OFFSCREENEXP_HPP 

#include <QOpenGLFunctions> 
#include <QWindow> 

class QImage; 
class QOpenGLContext; 

class offScreenExp : public QWindow, protected QOpenGLFunctions 
{ 
public: 
    explicit offScreenExp(QWindow *parent = 0); 

    QImage render(); 

private: 
    QOpenGLContext *context_; 
}; 

#endif // OFFSCREENEXP_HPP 

.Cpp

#include <QImage> 
#include <QOpenGLBuffer> 
#include <QOpenGLContext> 
#include <QOpenGLFramebufferObject> 
#include <QOpenGLShaderProgram> 
#include <QString> 
#include <QWidget> 

#include <QDebug> 

#include "offScreenExp.hpp" 

offScreenExp::offScreenExp(QWindow *parent) : 
    QWindow(parent), 
    context_(nullptr) 
{ 
    setSurfaceType(QWindow::OpenGLSurface); 
    setFormat(QSurfaceFormat()); 
    create(); 
} 

QImage offScreenExp::render() 
{ 
    //create the context 
    if (!context_) { 
     context_ = new QOpenGLContext(this); 
     QSurfaceFormat format; 
     context_->setFormat(format); 

     if (!context_->create()) 
      qFatal("Cannot create the requested OpenGL context!"); 
    } 

    context_->makeCurrent(this); 
    initializeOpenGLFunctions(); 

    //load image and create fbo 
    QString const prefix("/Users/Qt/program/experiment_apps_and_libs/openGLTest/simpleGPGPU/"); 
    QImage img(prefix + "images/emili.jpg"); 
    if(img.isNull()){ 
     qFatal("image is null"); 
    } 
    QOpenGLFramebufferObject fbo(img.size()); 
    qDebug()<<"bind success? : "<<fbo.bind(); 

    //if(glCheckFramebufferStatus(fbo.handle()) != GL_FRAMEBUFFER_COMPLETE){ 
    // qDebug()<<"frame buffer error"; 
    //} 
    qDebug()<<"has opengl fbo : "<<QOpenGLFramebufferObject::hasOpenGLFramebufferObjects(); 

    //use two triangles two cover whole screen 
    std::vector<GLfloat> const vertex{ 
     -1.0f, 1.0f, 0.0f, 1.0f, 
     1.0f, 1.0f, 0.0f, 1.0f, 
     -1.0f, -1.0f, 0.0f, 1.0f, 
     1.0f, 1.0f, 0.0f, 1.0f, 
     1.0f, -1.0f, 0.0f, 1.0f, 
     -1.0f, -1.0f, 0.0f, 1.0f, 
    }; 

    //initialize vbo 
    QOpenGLBuffer buffer(QOpenGLBuffer::VertexBuffer); 
    buffer.create(); 
    buffer.setUsagePattern(QOpenGLBuffer::StaticDraw); 
    buffer.bind(); 
    buffer.allocate(&vertex[0], vertex.size() * sizeof(GLfloat)); 
    buffer.release(); 

    //create texture 
    GLuint rendered_texture; 
    glGenTextures(1, &rendered_texture); 

    // "Bind" the newly created texture : all future texture functions will modify this texture 
    glBindTexture(GL_TEXTURE_2D, rendered_texture); 

    //naive solution, better encapsulate the format in a function 
    if(img.format() == QImage::Format_Indexed8){ 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, img.width(), img.height(), 0, GL_RED, GL_UNSIGNED_BYTE, img.scanLine(0)); 
    }else if(img.format() == QImage::Format_RGB888){ 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, img.scanLine(0)); 
    }else{ 
     QImage temp = img.convertToFormat(QImage::Format_RGB888); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.width(), img.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, temp.scanLine(0)); 
    } 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    glBindTexture(GL_TEXTURE_2D, 0); 

    //compile and link program 
    QOpenGLShaderProgram program; 
    if(!program.addShaderFromSourceCode(QOpenGLShader::Vertex, 
             "attribute highp vec4 qt_Vertex;" 
             "varying highp vec2 qt_TexCoord0;" 

             "void main(void)" 
             "{" 
             " gl_Position = qt_Vertex;" 
             " qt_TexCoord0 = (qt_Vertex.xy + vec2(1.0)) * 0.5;" 
             "}")){ 
     qDebug()<<"QOpenGLShader::Vertex error : " + program.log(); 
    } 

    // Compile fragment shader 
    if (!program.addShaderFromSourceCode(QOpenGLShader::Fragment, 
             "uniform sampler2D source;" 
             "varying highp vec2 qt_TexCoord0;" 

             "vec3 toGray(vec3 rgb)" 
             "{" 
             " return vec3(rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114);" 
             "}" 

             "void main(void)" 
             "{" 
             "vec3 gray = toGray(texture2D(source, qt_TexCoord0).rgb);" 
             "gl_FragColor = vec4(gray, 0.0);" 
             "}" 
             )){ 
     qDebug()<<"QOpenGLShader::Fragment error : " + program.log(); 
    } 

    // Link shader pipeline 
    if (!program.link()){ 
     qDebug()<<"link error : " + program.log(); 
    } 

    //render the texture as usual 
    //render the texture as usual 
glClearColor(0, 0, 0, 1); 
glClear(GL_COLOR_BUFFER_BIT); 
glViewport(0, 0, img.width(), img.height()); 

program.bind(); 
buffer.bind(); 
program.enableAttributeArray("qt_Vertex"); 
program.setAttributeBuffer("qt_Vertex", GL_FLOAT, 0, 4); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, rendered_texture); 

//bind and create fbo 
QOpenGLFramebufferObject fbo(img.size()); 
qDebug()<<"bind success? : "<<fbo.bind(); 

glDrawArrays(GL_TRIANGLES, 0, buffer.size()); 
QImage result = fbo.toImage(); 

program.disableAttributeArray("qt_Vertex"); 
program.release();  
buffer.release(); 

fbo.release(); 
glActiveTexture(0); 
glBindTexture(GL_TEXTURE_2D, 0); 
context_->doneCurrent(); 

    return result; 
} 

Ben kodlarını basitleştirmek için elimden geleni, ama bir QOpenGLFramebufferObject içine render deneyin ekran dışında render için oldukça ayrıntılı

+0

'# version' direktifleriniz nelerdir? – genpfault

+0

Hangi sürümü kullanmam gerektiği konusunda kafam karıştı, ama #version ile belirtmeme bile, openGL ile Qt, opengl es 2.0'a yapıştığım sürece glsl'yi anlayabilir. Yanlışsam beni düzeltin. openGL'yi çok komplike bulduğu bir newb tarafından. – StereoMatching

cevap

9

hala converted into a QImage olabilir, bu da kolayca diske kaydedilebilir. Bunun için

ancak, yine de bu nedenle tek seçenek aslında kullanıyor, ( QOpenGLContext::makeCurrent() gerektirdiği gibi) QWindow veya QGLWidget böyle bir yüzey elde etmek üzerine işlemek için bir yüzey gerekir.

Qt 5.1'de, muhtemelen sizin için en uygun olan QOffscreenSurface adlı yeni bir sınıf olacaktır. OpenGL context için bir yüzey almak ve QOpenGLFramebufferObject kullanarak bir FBO'ya dönüştürmek için QOffscreenSurface kullanın ve sonra piksellere erişmek için QOpenGLFramebufferObject::toImage() numaralı telefonu arayın.

+0

Teşekkürler, "OpenGL Pencere örneği", openGL bağlamında çalışıyorum ve FBO'nun ne olduğunu anlamaya çalışıyorum, oldukça karmaşık şeyler (openGL'nin çok karmaşık olduğunu düşünen tek kişi ben miyim?). istediğimi yapmak için. Qml2 bile kullanımı kolaydır, grafikler hakkında daha fazla güce ihtiyaç duyduğunuzda, openGL bilgisi bir zorunluluktur. – StereoMatching

İlgili konular