I'm having some issues with compiling my vertex shaders under OpenGL. I have a pretty standard vertex shader:
#version 330
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;
void main(void)
{
gl_Position = in_Position;
ex_Color = in_Color;
}
and my shader loading function looks like:
string temp = LoadFile(vShaderPath);
const char* vShaderString = temp.c_str();
const char* vShaderPathC = vShaderPath.c_str();
fprintf(stderr, "File: %s \nContents: %s\n", vShaderPathC, vShaderString);
temp = LoadFile(fShaderPath);
const char* fShaderString = temp.c_str();
vShaderHandle = glCreateShader(GL_VERTEX_SHADER);
fShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShaderHandle, 1, &vShaderString, NULL);
glShaderSource(fShaderHandle, 1, &fShaderString, NULL);
GLint compiled;
glCompileShader(vShaderHandle);
glCompileShader(fShaderHandle);
glGetShaderiv(vShaderHandle, GL_COMPILE_STATUS, &compiled);
if(compiled == false)
{
fprintf(stderr, "ERROR: Vertex shader not compiled properly.\n");
GLint blen = 0;
GLsizei slen = 0;
glGetShaderiv(vShaderHandle, GL_INFO_LOG_LENGTH , &blen);
if (blen > 1)
{
GLchar* compiler_log = new GLchar[blen];
glGetInfoLogARB(vShaderHandle, blen, &slen, compiler_log);
fprintf(stderr, "compiler log:\n %s", compiler_log);
delete [] compiler_log;
}
}
but when I run my program, I get an output of:
INFO: OpenGL Version: 3.3.0 NVIDIA 310.19
File: vShader.v.glsl
Contents: #version 330
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
void main(void)
{
gl_Position = in_Position;
ex_Color = in_Color;
}
ERROR: Vertex shader not compiled properly.
compiler log:
(0) : error C0000: syntax error, unexpected $end at token "<EOF>"
Loadfile is defined:
string ShaderEffect::LoadFile(string path)
{
ifstream in(path.c_str(), ios::in);
if(in.is_open())
{
string contents;
in.seekg(0, ios::end);
contents.resize(in.tellg());
in.seekg(0, ios::beg);
in.read(&contents[0], contents.size());
in.close();
return contents;
}
else
throw "Problem reading file!";
}
I know the glsl code itself is not the problem because I have hard coded the string in:
const char * testvShader = {
"#version 330\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;"
"void main()\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}"};
and when I switch &vShaderString to &testvShader the program runs fine. But I don't see how the loading can be the problem, because the fragment shader loads the same way and compiles and runs perfectly fine, and I print the file to the console before compiling it and it looks fine. I'm at my wits end, I can't figure out what the issue is.
P.S. I'm running on Fedora, if that matters.
You call c_str() on temp and store the result in a variable, and then you modify temp and use the saved result of c_str(). This doesn't work because the result of c_str() becomes invalid if you modify the string.
This compiler error is usually caused by trailing garbage. The most simple remedy is telling OpenGL which length the source string has exactly.
Replace your glShaderSource calls with
const char* vShaderString = temp.c_str();
int vertex_shader_string_length = temp.length();
/* ... */
const char* fShaderString = temp.c_str();
int fragment_shader_string_length = temp.length();
glShaderSource(vShaderHandle, 1, &vShaderString, &vertex_shader_string_length);
glShaderSource(fShaderHandle, 1, &fShaderString, &fragment_shader_string_length);
Related
I've read all recommended posts, I've tried those solutions, but non of them helped.
In short problem lies in the third argument of
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
This code work:
const char *vertexShaderSource = "#version 120 \n"
"attribute vec3 pos;\n"
"attribute vec2 texCoord;\n"
"varying vec2 texCoord0;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
" gl_Position = transform * vec4(pos, 1.0);\n"
" texCoord0 = texCoord;\n"
"}\0";
But I want to read it from a file, following code works
std::string s= "vertex";
std::ifstream file(s.c_str());
std::stringstream buffer;
buffer << file.rdbuf();
std::string str = buffer.str();
std::cout << str;
And is outputing:
#version 120
attribute vec3 pos;
attribute vec2 texCoord;
varying vec2 texCoord0;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(pos, 1.0);
texCoord0 = texCoord;
}
I know that I cannot just simply convert string with code like this:
const char *vertexShaderSource = str.c_str();
And pass it into: glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
So I've used following code to prevent it from ceasing to exist:
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0';
Passing glShaderSource(vertexShader, 1, &writable, NULL);does not work also.
I'm getting following error all the time, even with another copy&paste code from tutorials
0:1(4): preprocessor error: syntax error, unexpected HASH_TOKEN
What else I can do?
I've read these posts:
Reading a shader from a .txt file using a structure
read GLSL shaders from file
Here is the code I use to load shader sources:
ifstream iStream(filename);
stringstream buffer;
buffer << iStream.rdbuf();
string source = buffer.str();
const char* sources[] = { source.c_str() };
glShaderSource(handle, 1, sources, 0);
As you can see, the string can be given directly to glShaderSource; there is no need to create a copy of it. Have a look at the spec for c_str() if you're not convinced.
Not sure what the problem is in your case. I have used both \r\n and \n line endings successfully. Maybe you have a U+FEFF BOM character at the start of the file? It could with the the "hash" mentioned in the compilation error.
I'm trying to use shaders in my program but i'm getting very strange error...
Vertex shader failed to compile with the following error
ERROR: 0:6: error(#132) Syntax error: "in" parse error
ERROR: error(#273) 1 compilation errors. No code generated
I thought the problem was with file reading, but after trying many ways of that it's still not working.
So here is my code:
bool ShaderProgram::LoadShaderFile(const char* shader_path, GLuint& shader_id)
{
ifstream oFileStream(shader_path);
if(oFileStream)
{
// Load shader code
string sShaderSource;
sShaderSource.assign((istreambuf_iterator<char> (oFileStream) ), istreambuf_iterator<char> () );
// Forward shader code to OGL
const GLchar* chShaderSource = sShaderSource.c_str() + '\0';
printf("%s", chShaderSource);
glShaderSource(shader_id, 1, (const GLchar**) &chShaderSource, NULL);
return true;
}
else
return false;
}
And my shaders:
// shader.vs
// Vertex Shader
#version 330
in vec3 vVertex
in vec3 vColor
smooth out vec4 vVaryingColor;
void main()
{
vVaryingColor = vec4(vColor, 1.0);
gl_Position = vec4(vVertex, 1.0);
}
// shader.fs
// Fragment Shader
#version 330
smooth in vec4 vVeryingColor;
out vec4 vVaryingColor;
void main()
{
vFragColor = vVaryingColor;
}
You are missing the semicolons at the end of the in lines.
You have:
in vec3 vVertex
in vec3 vColor
You should have:
in vec3 vVertex;
in vec3 vColor;
I have two simple shaders (vertex and fragment)
Vertex Shader
#version 330 core
//=============================================
//---[Structs/Vertex Data]---------------------
//=============================================
layout(location = 0) in vec3 vertexPosition_modelspace;
//=============================================
//---[Variables]-------------------------------
//=============================================
uniform mat4 projection;
uniform mat4 view;
//=============================================
//---[Vertex Shader]---------------------------
//=============================================
void main()
{
gl_Position = projection * view * vertexPosition_modelspace;
}
Fragment Shader
#version 330 core
//=============================================
//---[Output Struct]---------------------------
//=============================================
out vec3 colour;
//=============================================
//---[Fragment Shader]-------------------------
//=============================================
void main()
{
colour = vec3(1, 0, 0);
}
I am trying to compile them and I get the following error
error C0000: syntax error, unexpected $undefined, expecting "::" at token "undefined"
I believe this may have something to do with the way I am reading the files. Here is an example for the vertex shader file
std::string VertexShaderCode = FindFileOrThrow(vertex_file_path);
std::ifstream vShaderFile(VertexShaderCode.c_str());
std::stringstream vShaderData;
vShaderData << vShaderFile.rdbuf();
vShaderFile.close();
The file is then compiled using
char const *VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
How can I efficiently read in the files and avoid these errors?
EDIT:
Correct compile:
const std::string &shaderText = vShaderData.str();
GLint textLength = (GLint)shaderText.size();
const GLchar *pText = static_cast<const GLchar *>(shaderText.c_str());
glShaderSource(VertexShaderID, 1, &pText, &textLength);
glCompileShader(VertexShaderID);
VertexShaderCode is your filename, not the shader string. That's still in vShaderData. You need to copy the string out of vShaderData, and feed it into glShaderSource.
Finally isolated the issue of my shader not being able to be used to it failing to compile.
Here is my shader loading routine. The first part reads in the shader:
void GLSLShader::LoadFromFile(GLenum whichShader, const string filename)
{
ifstream fp;
// Attempt to open the shader
fp.open(filename.c_str(), ios_base::in);
// If the file exists, load it
if(fp)
{
// Copy the shader into the buffer
string buffer(std::istreambuf_iterator<char>(fp), (std::istreambuf_iterator<char>()));
// Debug output to show full text of shader
errorLog.writeSuccess("Shader debug: %s", buffer.c_str());
LoadFromString(whichShader, buffer);
}
else
{
errorLog.writeError("Could not load the shader %s", filename.c_str());
}
}
After it has loaded it into a string, it sends it to be loaded:
void GLSLShader::LoadFromString(GLenum type, const string source)
{
// Create the shader
GLuint shader = glCreateShader(type);
// Convert the string
const char * ptmp = source.c_str();
glShaderSource(shader, 1, &ptmp, NULL);
// Compile the shader
glCompileShader(shader);
// Check to see if the shader has loaded
GLint status;
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
errorLog.writeError("could not compile: %s", infoLog);
delete [] infoLog;
}
_shaders[_totalShaders++]=shader;
}
I am getting the debug output "could not compile: " and it seems that the error buffer is empty. This has been driving me crazy for the past 3 days. Does anyone see my error?
Here are the very simple shaders:
#version 330
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
smooth out vec4 theColor;
void main()
{
gl_Position = position;
theColor = color;
}
#version 330
smooth in vec4 theColor;
out vec4 outputColor;
void main()
{
outputColor = theColor;
}
UPDATE
It looks like for some reason there is crap being added to the end of the shader in memory. I am not sure why. I have tried reading it in to a char* and a string. Here is the output:
<-!-> Shader: #version 330
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
smooth out vec4 theColor;
void main()
{
gl_Position = position;
theColor = color;
}
n
<-!-> Shader: #version 330
smooth in vec4 theColor;
out vec4 outputColor;
void main()
{
outputColor = theColor;
}
nts/Resources
Notice the 'n' at the end of the first shader and the 'nts/Resources' at the end of the second one. Any idea why?
ANOTHER UPDATE
The crap at the end was caused by an extra line at the end. I removed it and it is back to outputting the correct shader text. Still no luck thought with compiling.
I am at a loss here. The Superbible has their extensive libraries that are unoptimized and I don't need. There doesn't seem to be a damn decent shader compiler for Mac. I really don't mind how simple it is. It just needs to work with shaders. Does anyone have an example?
You're calling glShaderSource without supplying the length of each string in the sources array. Hence the string supplied is assumed to be terminated by a null byte ('\0'). The way you're reading the file into memory does not terminate the shader source with an additional null byte. So the GLSL compiler will read beyond the end of the shader source into random memory, where it finds… garbage.
Solution: Either add a terminating null byte, or supply the shader text lengths parameter.
Following an OpenGL tutorial,
in a part, where it creates a vertex shader, it uses the following method,
const GLchar* VertexShader =
{
"#version 330\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
I just replaces this code, with my code which brings the shader from a file,
string readShaderFile(string FileName)
{
string ShaderString = "";
ifstream shaderFile;
shaderFile.open(FileName);
while(!shaderFile.eof())
{
string tempholder;
getline(shaderFile, tempholder);
ShaderString.append(tempholder);
ShaderString.append("\n");
}
shaderFile.close();
return ShaderString;
}
const GLchar *VertexShader = readShaderFile("v.vert").c_str();
and BANG!
the code doesn't work anymore. What could be the issue?
the v.vert file contains the following code:
#version 330
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;
void main(void)
{
gl_Position = in_Position;
ex_Color = in_Color;
}
You don't have to split the read file into lines, just pass the whole file as it is. Also those '\n' are in the C code, because you can't have ordinary newlines in a C string. You must escape them. But this is not neccesary reading from a file.
And then you have a problem here:
const GLchar *VertexShader = readShaderFile("v.vert").c_str();
readShaderFile returns a std::string that goes out of scope and the compiler may deconstrung the string instance right there. You must store the returned string in it's own variable and keep that around as long as you want to use its c_str();
Since this is supposedly on the global scope change it like this:
static std::string strVertexShader = readShaderFile("v.vert");
GLchar const *VertexShader = strVertexShader.c_str();
Your function to load the shader should be something like this :
string readShaderFile(const string fileName)
{
std::ifstream shaderFile( fileName.c_str() );
// find the file size
shaderFile.seekg(0,std::ios::end);
std::streampos length = shaderFile.tellg();
shaderFile.seekg(0,std::ios::beg);
// read whole file into a vector:
std::vector<char> buffer(length);
shaderFile.read(&buffer[0],length);
// return the shader string
return std::string( buffer.begin(), buffer.end() );
}
Also, what are you doing after this line :
const GLchar *VertexShader = readShaderFile("v.vert").c_str();
?
The temporary string gets destroyed, and the VertexShader contains a dangling pointer. What you need to do is this :
const std::string shaderProgram = readShaderFile("v.vert");
const GLchar *VertexShader = shaderProgram.c_str();
// create shader program
// etc