Reputation: 95
I just started to learn about Grpahics in C++, and about shaders and sprites. I wrote a small vertex shader, and a fragment shader.
Vertex Shader:
#version 130
in vec2 vertexPosition;
void main() {
gl_Position.xy = vertexPosition;
gl_Position.z = 0.0;
gl_Position.w = 1.0;
}
Fragment Shader:
#version 130
out vec3 color;
void main() {
color = vec3(0.94, 0.37, 0.36);
}
While Compiling, I am getting the following Error Messages:
Fragment shader failed to compile with the following errors:
ERROR: 0:6: error(#143) Undeclared identifier: gl_Position
ERROR: 0:6: error(#216) Vector field selection out of range "xy"
ERROR: 0:6: error(#160) Cannot convert from: "default in highp 2-component vector of vec2" to: "float"
ERROR: 0:7: error(#216) Vector field selection out of range "z"
ERROR: 0:8: error(#216) Vector field selection out of range "w"
ERROR: error(#273) 5 compilation errors. No code generated
How do I fix these errors?
PS: I am using an AMD A10 8700P Radeon R6 processor builtin graphics. While reading other questions I noticed that using AMD Graphics Card is the root cause of several problems, so if that is the problem in my case, then how do I fix that?
I am using a seperate class for all GLSL Manipulations.
GLSLProgram.h:
#pragma once
#include <GL/glew.h>
#include <string>
class GLSLProgram
{
public:
GLSLProgram();
~GLSLProgram();
void compileShaders(const std::string &vertexShaderFilePath, const std::string &fragmentShaderFilePath);
void linkShaders();
void addAttribute(const std::string& attributeName);
void use();
void unuse();
private:
int _numAttributes;
void compileShader(const std::string &filePath, GLuint id);
GLuint _programID;
GLuint _vertexShaderID;
GLuint _fragmentShaderID;
};
GLSLProgram.cpp:
#include "GLSLProgram.h"
#include "Errors.h"
#include <fstream>
#include <vector>
GLSLProgram::GLSLProgram() :
_numAttributes(0), _programID(0), _vertexShaderID(0), _fragmentShaderID(0)
{
}
GLSLProgram::~GLSLProgram() {
}
void GLSLProgram::compileShaders(const std::string &vertexShaderFilePath, const std::string &fragmentShaderFilePath) {
_vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
if (!_vertexShaderID) {
fatalError("Vertex Shader failed to be created!");
}
_fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if (!_fragmentShaderID) {
fatalError("Fragment Shader failed to be created!");
}
compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(vertexShaderFilePath, _fragmentShaderID);
}
void GLSLProgram::linkShaders() {
// Vertex and fragment shaders are successfully compiled.
// Now time to link them together into a program.
// Get a program object.
_programID = glCreateProgram();
// Attach our shaders to our program
glAttachShader(_programID, _vertexShaderID);
glAttachShader(_programID, _fragmentShaderID);
// Link our program
glLinkProgram(_programID);
// Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(_programID, GL_LINK_STATUS, (int *)&isLinked);
if (isLinked == GL_FALSE)
{
GLint maxLength = 0;
glGetProgramiv(_programID, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
std::vector<char> errorLog(maxLength);
glGetProgramInfoLog(_programID, maxLength, &maxLength, &errorLog[0]);
// We don't need the program anymore.
glDeleteProgram(_programID);
// Don't leak shaders either.
glDeleteShader(_vertexShaderID);
glDeleteShader(_fragmentShaderID);
std::printf("%s\n", &(errorLog[0]));
fatalError("Shaders failed to link!");
}
// Always detach shaders after a successful link.
glDetachShader(_programID, _vertexShaderID);
glDetachShader(_programID, _fragmentShaderID);
glDeleteShader(_vertexShaderID);
glDeleteShader(_fragmentShaderID);
}
void GLSLProgram::addAttribute(const std::string &attributeName) {
glBindAttribLocation(_programID, _numAttributes++, attributeName.c_str());
}
void GLSLProgram::use() {
glUseProgram(_programID);
for(int i = 0; i < _numAttributes; ++i) {
glEnableVertexAttribArray(i);
}
}
void GLSLProgram::unuse() {
glUseProgram(0);
for(int i = 0; i < _numAttributes; ++i) {
glDisableVertexAttribArray(i);
}
}
void GLSLProgram::compileShader(const std::string &filePath, GLuint id)
{
std::ifstream shaderFile(filePath);
if (shaderFile.fail())
{
perror(filePath.c_str());
fatalError("Failed to open " + filePath);
}
std::string fileContents = "";
std::string line;
while (std::getline(shaderFile, line))
{
fileContents += line + "\n";
}
shaderFile.close();
const char *contentsPtr = fileContents.c_str();
glShaderSource(id, 1, &contentsPtr, nullptr);
glCompileShader(id);
GLint success = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &success);
if (success == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);
//The maxLength includes the NULL character
std::vector<char> errorLog(maxLength);
glGetShaderInfoLog(id, maxLength, &maxLength, &errorLog[0]);
glDeleteShader(id);
std::printf("%s\n", &(errorLog[0]));
fatalError("Shader " + filePath + " Failed to compile");
}
}
Fatal Error just prints the string supplied and exits.
Upvotes: 1
Views: 1324
Reputation: 210878
gl_Position
is only valid in vertex shaders.
You compile the vertex shader twice, but you don't compile the fragment shader in compileShaders
:
It has to be
compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(fragmentShaderFilePath, _fragmentShaderID);
instead of
compileShader(vertexShaderFilePath, _vertexShaderID);
compileShader(vertexShaderFilePath, _fragmentShaderID);
Upvotes: 5