Reputation: 19
I am translating a Visual Studio C++ OpenGL
project to a Qt project to implement a UI
.
I have all the code translated and I am using Qt classes to implement OpenGL
part.
The problem I am having now is that when I link the shaderProgram
it throws me an error that says:
Vertex info (0) : error C5145: must write to gl_Position
I am implementing QOpenGLFunctions_4_1_Core
and I debug the compile function to see if the code was well read and yes
All the code is read and the compile function returns a true (well compiled).
GLuint shaderProgram::createShaderProgram(const char *fileName) {
// Creamos el shader program y almacenamos su identificador
if (handler) {
shaderP = new QOpenGLShaderProgram();
handler = shaderP->create();
if (!handler) {
fprintf(stderr, "Cannot create shader program: %s.\n", fileName);
return 0;
}
}
// Cargamos y compilamos cada uno de los shader objects que componen este
// shader program
char fileNameComplete[256];
strcpy_s(fileNameComplete, fileName);
strcat_s(fileNameComplete, "-vert.glsl");
QOpenGLShader* vertex = new QOpenGLShader(QOpenGLShader::Vertex);
GLuint vertexShaderObject = compileShader(fileNameComplete, QOpenGLShader::Vertex,vertex);
if (vertexShaderObject == 0) {
return 0;
}
strcpy_s(fileNameComplete, fileName);
strcat_s(fileNameComplete, "-frag.glsl");
QOpenGLShader* fragment = new QOpenGLShader(QOpenGLShader::Fragment);
GLuint fragmentShaderObject = compileShader(fileNameComplete, QOpenGLShader::Fragment, fragment);
if (fragmentShaderObject == 0) {
return 0;
}
// Asociamos los shader objects compilados sin errores al shader program
shaderP->addShader(vertex);
shaderP->addShader(fragment);
// Enlazamos el shader program y comprobamos si hay errores
handler = shaderP->link(); //Here is where the error is thrown
if(!handler)
{
QString error = shaderP->log();
std::cout<< error.toStdString()<<std::endl;
return 0;
}
else {
linked = true;
}
return handler;
}
bool shaderProgram::compileShader(const char *filename, QOpenGLShader::ShaderTypeBit type,QOpenGLShader* shaderComp) {
// Comprobamos si en la solución existe algún archivo de recursos con el
// nombre que se pasa como argumento
if (!fileExists(filename)) {
fprintf(stderr, "Shader source file %s not found.\n", filename);
return 0;
}
// Si existe se lee en una cadena de caracteres que contiene el listado
// completo del shader source
std::ifstream shaderSourceFile;
shaderSourceFile.open(filename);
if (!shaderSourceFile) {
fprintf(stderr, "Cannot open shader source file.\n");
return 0;
}
std::stringstream shaderSourceStream;
shaderSourceStream << shaderSourceFile.rdbuf();
std::string shaderSourceString = shaderSourceStream.str();
shaderSourceFile.close();
// - Creamos un shader object para ese archivo que se ha leído
QOpenGLShader shader(type);
QString code(QString::fromStdString(shaderSourceString));
bool result = shader.compileSourceCode(code);
if(!result){
const QString qs = shader.log();
std::cout << qs.toStdString();
this->logString = qs.toStdString();
return false;
}
//si ha compilado bien, creamos el shader
shaderComp = &shader;
return true;
}
I expect the shader program link well and I would be able to draw my objects on screen.
Upvotes: 1
Views: 1614
Reputation: 211125
There are some issues in your code.
First of all I recommend to us QOpenGLShader::compileSourceFile
:
e.g.
QOpenGLShader* vertex = new QOpenGLShader(QOpenGLShader::Vertex);
vertex->compileSourceFile( fileNameComplete );
In the function shaderProgram::compileShader
a local variable shader
is used:
QOpenGLShader shader(type);
but then a pointer to this variable is assigned to the output parameter shaderComp
.
shaderComp = &shader;
When the function has terminated, the local object shader
is destructed and the pointer finally goes to nowhere.
The parameter has to be an input parameter. Get rid of the local variable and use the existing object to compile the shader.
You can create a new QOpenGLShader
object in the shaderProgram::compileShader
and return that object by the return value:
QOpenGLShader* shaderProgram::compileShader(
const char *filename,
QOpenGLShader::ShaderTypeBit type)
{
// Comprobamos si en la solución existe algún archivo de recursos con el
// nombre que se pasa como argumento
if (!fileExists(filename)) {
fprintf(stderr, "Shader source file %s not found.\n", filename);
return nullptr;
}
// Si existe se lee en una cadena de caracteres que contiene el listado
// completo del shader source
std::ifstream shaderSourceFile;
shaderSourceFile.open(filename);
if (!shaderSourceFile) {
fprintf(stderr, "Cannot open shader source file.\n");
return nullptr;
}
std::stringstream shaderSourceStream;
shaderSourceStream << shaderSourceFile.rdbuf();
std::string shaderSourceString = shaderSourceStream.str();
shaderSourceFile.close();
// - Creamos un shader object para ese archivo que se ha leído
QString code(QString::fromStdString(shaderSourceString));
QOpenGLShader* shader = new QOpenGLShader(QOpenGLShader::Vertex);
bool result = shader->compileSourceCode(code);
if(!result){
const QString qs = shader->log();
std::cout << qs.toStdString();
this->logString = qs.toStdString();
delete shader;
return nullptr;
}
//si ha compilado bien, creamos el shader
return shader;
}
Call the method like this:
std::string vertFileName = std::string(fileName) + "-vert.glsl";
QOpenGLShader* vertex = compileShader(vertFileName.c_str(), QOpenGLShader::Vertex);
if (!vertex) {
return 0;
}
std::string fragFileName = std::string(fileName) + "-frag.glsl";
QOpenGLShader* fragment = compileShader(fragFileName.c_str(), QOpenGLShader::Fragment);
if (!fragment) {
return 0;
}
Upvotes: 2