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.
Related
From https://learnopengl.com/Getting-started/Shaders I read:
Shaders always begin with a version declaration, ...
But on OpenGL Window Example there is no version on shader code. What's the version then?
static const char *vertexShaderSource =
"attribute highp vec4 posAttr;\n"
"attribute lowp vec4 colAttr;\n"
"varying lowp vec4 col;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position = matrix * posAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"varying lowp vec4 col;\n"
"void main() {\n"
" gl_FragColor = col;\n"
"}\n";
Following seems to be related: How to Convert GLSL #version 330 core to GLSL ES #version 100?
In qt 5.12.2 source file : qopenglshaderprogram.cpp
LINE 604:
bool QOpenGLShader::compileSourceCode(const char *source){
Q_D(QOpenGLShader);
// This method breaks the shader code into two parts:
// 1. Up to and including an optional #version directive.
// 2. The rest.
// If a #version directive exists, qualifierDefines and redefineHighp
// are inserted after. Otherwise they are inserted right at the start.
// In both cases a #line directive is appended in order to compensate
// for line number changes in case of compiler errors.
if (d->shaderGuard && d->shaderGuard->id() && source) {
const QVersionDirectivePosition versionDirectivePosition = findVersionDirectivePosition(source);
QVarLengthArray<const char *, 5> sourceChunks;
QVarLengthArray<GLint, 5> sourceChunkLengths;
QOpenGLContext *ctx = QOpenGLContext::currentContext();
if (versionDirectivePosition.hasPosition()) {
// Append source up to and including the #version directive
sourceChunks.append(source);
sourceChunkLengths.append(GLint(versionDirectivePosition.position));
} else {
// QTBUG-55733: Intel on Windows with Compatibility profile requires a #version always
if (ctx->format().profile() == QSurfaceFormat::CompatibilityProfile) {
const char *vendor = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_VENDOR));
if (vendor && !strcmp(vendor, "Intel")) {
static const char version110[] = "#version 110\n";
sourceChunks.append(version110);
sourceChunkLengths.append(GLint(sizeof(version110)) - 1);
}
}
}
and
static QVersionDirectivePosition findVersionDirectivePosition(const char *source){
Q_ASSERT(source);
// According to the GLSL spec the #version directive must not be
// preceded by anything but whitespace and comments.
// In order to not get confused by #version directives within a
// multiline comment, we need to do some minimal comment parsing
// while searching for the directive.
If version is not available, "#version 110\n" will be added.
static const char version110[] = "#version 110\n";
sourceChunks.append(version110);
Im having trouble with getting a proper location of my uniform in my opengl shaders. I always but always get -1 returned from the glGetUniformLocation Function.
maybe I didnt load it well?
I read online that uniforms can get optimized out for not-using them, but I do use my uniforms in a way that can affect my shaders(or do I,I think I do).
also, everytime I encounter an answer that is related to this problem on stackoverflow or on some other site,they do talk about this fact, but NO ONE EXPLAINS about an alternative solution for this, and that realy got me struggling. is it something new just for new opengl iterations?
here is my vertex shader code:
#version 410 core
in vec4 position;
uniform mat4 mvmatrix;
uniform mat4 projmatrix;
void main(void)
{
gl_Position = projmatrix * mvmatrix * position;
}
here is my fragment shader code:
#version 410 core
out vec4 color;
void main(void)
{
color = vec4(1.0,1.0,1.0,1.0)
}
and here is the whole source code for the whole program..for now I didnt implement the whole code itself,only the part that compliles the program and shaders, but yet, Im struggling to get the location for the uniforms, Ive been struggling with this for several days...hoping someone could save me here:
codeHere
also if you need only the specific part that Im talking about:
//creating program and shaders, compiling shaders, compiling program
GLchar * v_Shader[] = {
"#version 410 core \n"
" \n"
"in vec4 position; \n"
" \n"
" \n"
"uniform mat4 mvmatrix; \n"
"uniform mat4 projmatrix; \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = proj_matrix * mv_matrix * position; \n"
"} \n"
};
GLchar * f_Shader[] = {
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(1.0,1.0,1.0,1.0) \n"
"} \n"
};
//creating a opengl program
program = glCreateProgram();
//creating the vertex shader and compiling it
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, v_Shader, NULL);
glCompileShader(vertexShader);
//creating the fragment shader and compiling it
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, f_Shader, NULL);
glCompileShader(fragmentShader);
//attaching the shaders to the program and linking the program
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glUseProgram(program);
//getting the program's uniform locations
modelViewMatrixLocation = glGetUniformLocation(program, "mvmatrix");
projectionMatrixLocation = glGetUniformLocation(program, "projmatrix");
And nope, I dont like using glfw/sdl/glew/freeglut or any other library. they just confuse me all around.
You are misspelling the uniform names in the vertex shader:
uniform mat4 mvmatrix;
uniform mat4 projmatrix;
...
gl_Position = proj_matrix * mv_matrix * position;
To fix, replace gl_Position line with
gl_Position = projmatrix * mvmatrix * position;
To catch errors like this in the future, check the shader compile status:
GLint wasCompiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &wasCompiled );
GLint logLength;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLength );
if (logLength > 0)
{
GLchar* log = new GLchar[ (std::size_t)logLength + 1 ];
GLsizei charsWritten = 0;
glGetShaderInfoLog( shader, logLength, &charsWritten, log );
std::cout << std::string( log );
}
You also have a syntax error in your fragment shader:
color = vec4(1.0,1.0,1.0,1.0)
It's missing ; at the end. You should check for shader compile errors.
Your fragment shader takes color as input from vertex shader, but vertex shader doesn't output it and you don't use color input in the fragment shader. To fix, remove these lines:
"in VS_OUT \n"
"{ \n"
" vec4 color; \n"
"} fs_in; \n"
In the latest version in the comments you have a line:
color = vec4(1.0,0.0,0.0.1.0)
There are 2 errors. You are missing ; and the character before 1.0 should be ,, not .
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);
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.
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