2015-06-27 38 views
1

This是我以前的问题。Qt GLSL纹理只出现一种颜色

现在我想将我以前的遗留obj加载程序移植到GLSL。

但是,纹理上只有一种颜色可以绑定到obj。

所以,当我渲染obj时,整个obj都是纯色。

#include <QVector> 
#include <QTextStream> 
#include <QVector3D> 
#include <QVector2D> 
#include <QOpenGLShaderProgram> 
#include <QOpenGLFunctions> 
#include <QMatrix4x4> 

struct Face{ 
    QVector<QVector3D> v; 
    QVector<QVector3D> vn; 
    QVector<QVector2D> t; 
    Face(){ 
     v.resize(3); 
     vn.resize(3); 
     t.resize(3); 
    } 
}; 

class ModelGLSL 
{ 
public: 
    ModelGLSL() {} 
    ModelGLSL(QString filename); 
    void render(QOpenGLShaderProgram* program, QMatrix4x4 MVPmarix); 

    QString textureName; 
    QVector<QVector3D> Faces_vertices; 
    QVector<QVector2D> Faces_textureCoordinates; 
    GLuint texture; 

private: 
    QString fileName; 
    QImage textureImg; 
    void LoadMTL(QString fn, QString MTLname); 
    void LoadTexture(); 
}; 
在ModelGLSL.cpp

#include "ModelGLSL.h" 

ModelGLSL::ModelGLSL(QString filename) 
{ 
    fileName = filename; 
    QString texturename; 
    QVector3D temp3D; 
    QVector2D temp2D; 

    QVector<Face> Faces; 
    QVector<QVector3D> Vertices; 
    QVector<QVector3D> VNormals; 
    QVector<QVector2D> UVs; 

    if(!fileName.isEmpty()) 
    { 
     QFile file(fileName); 
     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) 
     { 
      QTextStream fileText(&file); 
      while (!fileText.atEnd()) 
      { 
       QString fileLine = fileText.readLine(); 
       if(fileLine.startsWith("vn ")) 
       { 
        QStringList lineList = fileLine.split(" "); 
        temp3D.setX(lineList[1].toFloat()); 
        temp3D.setY(lineList[2].toFloat()); 
        temp3D.setZ(lineList[3].toFloat()); 
        VNormals.push_back(temp3D); 
       } 
       else if(fileLine.startsWith("vt ")) 
       { 
        QStringList lineList = fileLine.split(" "); 
        temp2D.setX(lineList[1].toFloat()); 
        temp2D.setY(lineList[2].toFloat()); 
        UVs.push_back(temp2D); 
       } 
       else if(fileLine.startsWith("v ")) 
       { 
        QStringList lineList = fileLine.split(" "); 
        temp3D.setX(lineList[1].toFloat()); 
        temp3D.setY(lineList[2].toFloat()); 
        temp3D.setZ(lineList[3].toFloat()); 
        Vertices.push_back(temp3D); 
       } 
       else if(fileLine.startsWith("f ")) 
       { 
        Face F; 
        QStringList lineList = fileLine.split(" "); 

        for(int i = 1; i <= 3; i++) 
        { 
         QStringList arg = lineList[i].split("/"); 
         F.v[i-1] = Vertices[arg[0].toInt()-1]; 
         F.t[i-1] = UVs[arg[1].toInt()-1]; 
         F.vn[i-1] = VNormals[arg[2].toInt()-1]; 
        } 
        Faces.push_back(F); 
       } 
       else if(fileLine.startsWith("mtllib ")) 
       { 
        QStringList lineList = fileLine.split(" "); 
        texturename = lineList[1]; 
       } 
      } 
      LoadMTL(":/Model/Models/", ":/Model/Models/" + texturename); 
     } 
     file.close(); 
    } 

    for(int i = 0; i < Faces.size(); i++) 
    { 
     Faces_vertices << Faces[i].v; 
     Faces_textureCoordinates << Faces[i].t; 
    } 
} 

void ModelGLSL::LoadMTL(QString fn, QString MTLname) 
{ 
    if(!MTLname.isEmpty()) 
    { 
     QFile file(MTLname); 
     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) 
     { 
      QTextStream fileText(&file); 
      while (!fileText.atEnd()) 
      { 
       QString fileLine = fileText.readLine(); 
       if(fileLine.startsWith("map_Kd ")) 
       { 
        QStringList lineList = fileLine.split(" "); 
        textureName = fn + lineList[1]; 
        LoadTexture(); 
       } 
      } 
     } 
     file.close(); 
    } 
} 

void ModelGLSL::LoadTexture() 
{ 
    textureImg = QGLWidget::convertToGLFormat(QImage(textureName)); 

    glGenTextures(1, &texture); 
    glBindTexture(GL_TEXTURE_2D, texture); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureImg.width(), textureImg.height(), 0, GL_RGBA, 
       GL_UNSIGNED_BYTE, textureImg.bits()); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

    glBindTexture(GL_TEXTURE_2D, 0); 
} 

void ModelGLSL::render(QOpenGLShaderProgram *program, QMatrix4x4 MVPmarix) 
{ 
    glEnable(GL_DEPTH_TEST); 
    glEnable(GL_TEXTURE_2D); 

    program->setUniformValue("mvpMatrix", MVPmarix); 
    program->setUniformValue("texture", 0); 

    glBindTexture(GL_TEXTURE_2D, texture); 

    program->setAttributeArray("vertex", Faces_vertices.constData()); 
    program->enableAttributeArray("vertex"); 

    program->setAttributeArray("textureCoordinate", Faces_textureCoordinates.constData()); 
    program->enableAttributeArray("textureCoordinate"); 

    glDrawArrays(GL_TRIANGLES, 0, Faces_vertices.size()); 
    program->disableAttributeArray("vertex"); 
    program->disableAttributeArray("textureCoordinate"); 

    program->release(); 
    glDisable(GL_DEPTH_TEST); 
    glDisable(GL_TEXTURE_2D); 
} 

在vs.vert

#version 430 core 

uniform mat4 mvpMatrix; 
in vec4 vertex; 
in vec2 textureCoordinate; 
out vec2 varyingTextureCoordinate; 

void main(void) 
{ 
    varyingTextureCoordinate = textureCoordinate; 
    gl_Position = mvpMatrix * vertex; 
} 

在fs.frag

#version 430 core 

uniform sampler2D texture; 
in vec2 varyingTextureCoordinate; 
out vec4 fragColor; 

void main(void) 
{ 
    fragColor = texture2D(texture, varyingTextureCoordinate); 
} 
在initializeGL

()

initializeOpenGLFunctions(); 

program = new QOpenGLShaderProgram; 

program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shader/Shaders/vs.vert"); 
program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shader/Shaders/fs.frag"); 
program->link(); 

OBJ = new ModelGLSL(":/Model/Models/OBJ.obj"); 
在paintGL

()

OBJ->render(program, projection * view * model); 

回答

1

我看到的代码很多很多奇怪的事情:

  • 您没有使用顶点数组对象,这是一个核心配置文件强制性的。

  • 您没有使用顶点缓冲对象来设置属性数组。在核心配置文件中它们的用法是强制性的更糟糕的是,你正在上传每个重绘的属性数组!

  • 没有program->bind()调用开始使用您创建的着色器程序。不能先在程序中设置制服等。

  • 你没有使用QOpenGLTexture,这意味着,你正在诉诸手动纹理分配。不仅glEnable(GL_TEXTURE_2D)是核心配置文件中的错误(没有这样的启用标志),但是你没有使用不可变的存储,并且你将自己暴露在危险之中(在你的情况中:你的纹理是mipmap-不完整的,因为它有mipmap,默认的mipmap范围是[0,1000))。

  • 使用核心配置文件时,可以使用texture()函数而不是texture2D()函数在着色器语言中采样纹理。参数的类型将自动由第一个参数推导出来(因此,对于sampler2D,您还需要通过vec2)。

此外,你应该:如果是编译着色器或链接着色器程序

  • 检查失败,并转储log()

  • 使用QOpenGLDebugLogger例如,如果你有KHR_debug扩展,这将报告这个错误,可能还有其他许多错误。