Qt GLSL 纹理只出现一种颜色

Posted

技术标签:

【中文标题】Qt GLSL 纹理只出现一种颜色【英文标题】:Qt GLSL texture only one color appears 【发布时间】:2015-06-27 12:59:39 【问题描述】:

This 是我之前的问题。

现在我想将我以前的旧 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);

在初始化GL()中

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-&gt;bind() 调用来开始使用您创建的着色器程序。如果不先使用程序,就不能在程序上设置制服等。

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

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

另外,你应该:

检查编译着色器或链接着色器程序是否失败,并转储log()

如果您有 KHR_debug 扩展名,请使用 QOpenGLDebugLogger 实例,这将报告此错误,可能还会报告许多其他错误。

【讨论】:

以上是关于Qt GLSL 纹理只出现一种颜色的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL/GLSL 颜色附件范围

GLSL将颜色数据从片段着色器发送到顶点着色器似乎总是等于0

OpenGL纹理覆盖材质颜色

glsl片段着色器颜色添加逻辑

GLSL MRT 将相同的数据写入所有颜色附件

多个视频渲染过程中出现颜色错误的图片