Reputation: 199
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);
Upvotes: 1
Views: 376
Reputation: 22796
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.
Upvotes: 1