简体   繁体   中英

Qt GLSL texture only one color appears

This is my previous question.

Now I want to port my previous legacy obj loader to GLSL.

However, only one color on the texture can be bound to the obj.

So, when I render the obj, the whole obj is Solid Color.

#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();
};

in 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 );
}

in 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;
}

in fs.frag

#version 430 core

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

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

in 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");

in paintGL()

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

I see many many strange things in the code:

  • You are not using Vertex Array Objects, which are mandatory in a core profile.

  • You are not using Vertex Buffer Objects to set attribute arrays. Their usage is mandatory in the core profile. What's worse, you're uploading the attribute arrays for each redraw!

  • There's no program->bind() call to start using the shader program that you've created. You can't set uniforms etc. on a program without using it first.

  • You are not using QOpenGLTexture, which means, you're resorting to manual texture allocation. Not only glEnable(GL_TEXTURE_2D) is an error in the core profile (there's no such enable flag), but you're not using immutable storage, and you're exposing yourself at the dangers of that (in your case: your texture is mipmap-incomplete, since it has mipmaps and the default mipmap range is [0, 1000)).

  • When using a core profile, you sample a texture in the shader languages by using the texture() function, not texture2D() . The type of the arguments will be automatically deduced by the first argument (so, for a sampler2D you will need to pass also a vec2 ).

Also, you should:

  • check if compiling a shader or linking a shader program fails, and dump the log()

  • Use a QOpenGLDebugLogger instance if you have the KHR_debug extension, which will report this mistake and possibly many others.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM