I'm doing my first steps with OpenGL and stumbled upon a problem in my vertex shader program:
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 inputTransform;
void main()
{
gl_Position = inputTransform * vec4(aPos, 1.0);
}
compiles and works well, but when I change the first line to
#version 130 core
because I'm bound to use OpenGL 3.0 at max, it first complains about the "location" statement. When I remove it, the remaining error message for the line
layout in vec3 aPos;
is
ERROR: 0:2: 'in' : syntax error syntax error
What's wrong here - how do I have to declare input variables in this version of the language?
Input layout qualifiers have been added in GLSL version 1.50 wich corresponds to OpeneGL version 3.2
See OpenGL Shading Language 1.50 Specification; - 4.3.8.1 Input Layout Qualifiers; page 37.
An input layout qualifier consists of the keyword layout followed by the layout-qualifier-id-list.
It is not sufficient to remove the layout-qualifier-id-list alone, you have to remove the keyword layout too:
in vec3 aPos;
The syntax error is caused by the fact, that it is not a proper syntax, that layout is directly followed by in.
Either you have to ask for the attribute index by glGetAttribLocation after the program is linked, or you have to specify the attribute location by glBindAttribLocation before the shader program is linked.
Related
in my shaders I like to use a syntax like this:
layout (location = 0) in vec3 aPos;
So that I can just use the index 0 in glVertexAttribPointer and the such, saving the effort for the glGetAttribLocation call. I'd like to do the same with uniform values, but if I do
layout (location = 2) uniform float offset;
My vertex shader fails to compile. Is there any way to achieve the same behavior and not use glGetUniformLocation?
OpenGL 4.3 or the ARB_explicit_uniform_location extension allows you to specify uniform locations within the shader using that syntax. So your shader #version needs to be 430 or you need to activate the extension in your shader to be able to use this syntax.
I am having trouble getting emscripten to work with openGL shaders. The project compiles just fine with both emscripten and gcc but fails when I try to run the emscripten output.
The errors I get from compiling the vertex shader:
ERROR: 0:1: 'core' : invalid version directive
ERROR: 0:3: 'layout' : syntax error
The errors I get from compiling the fragment shader:
ERROR: 0:1: 'core' : invalid version directive
ERROR: 0:3: 'in' : storage qualifier supported in GLSL ES 3.00 only
ERROR: 0:3: '' : No precision specified for (float)
ERROR: 0:5: 'out' : storage qualifier supported in GLSL ES 3.00 only
ERROR: 0:5: '' : No precision specified for (float)
I'm compiling this project with the command:
em++ src/*.cpp -Iinclude/ -o test.html -std=c++11 -s USE_GLFW=3 -s FULL_ES3=1
Vertex shader source:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 in_color;
uniform mat4 model;
uniform mat4 projection;
out vec3 out_color;
void main()
{
gl_Position = projection * model * vec4(position, 1.0f);
out_color = in_color;
}
Fragment shader source:
#version 330 core
in vec3 out_color;
out vec4 color;
void main()
{
color = vec4(out_color, 1.0);
}
The shaders are loaded as char arrays from output provided by xxd -i I'm working in c++11 on linux. The program works just fine when I run it natively and I've tried running the emscripten output in both Firefox and chromium.
It seems to be a problem between different versions. Is there a way to make emscripten work with what I currently have, or do I have to write my shaders differently? And if I do have to rewrite my shaders, how should I write them?
The shader code will have to be WebGL shader code to work on the browser. I don't think emscripten converts shader code (GLSL 3.3 in this case) to a GLSL ES 1.0 that is compatible with webGL.
You'll have to use attribute instead of in in the vertex shader, varying for out/in in the vertex/fragment shaders and use gl_FragColor as the output variable of the fragment shader. layout is not supported either, and the variables need a precision definition. Check the WebGL cheat sheet here.
In current emscripten you can use WebGL2 and GLSL ES 3.00. You need to change your #version lines to
#version 300 es
You will also need to add a default precision to your fragment shaders.
If it was me I'd just wrap my code to glShaderSource to be something like
GLint shaderSourceWrapper(GLint shader, const std::string src) {
#ifdef __EMSCRIPTEN__
// replace '#version.*' with '#version 300 es'
// if it's a fragment shader add 'precision highp float'
// do anything else relevant like warn if there are
// unsupported #extension directives
#endif
glShaderSource(shader, ... )
Or even do that at the JavaScript level like this
I just installed the latest NVidia driver for Quadro 4000 cards.From this moment any of my shaders linking fails with shader link error.
It is worth noting I am using OpenGL 4.2 with separate shader objects.My OS is Windows7 64bit .
Before the update I had 309.x version of the driver and everything worked fine.
Now I rolled back to the version 295.x and it works again.
Anyone knows something about it?Can it be a driver bug? If yes, what can be done about it?
Here is a simple pass through vertex shader that fails:
#version 420 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 uvs;
layout(location = 2) in vec3 normal;
smooth out vec2 uvsOut;
void main()
{
uvsOut=uvs;
gl_Position = position;
}
Another question ,is it possible that NVIdia tightened shader version semantics rules? I mean ,I am using OpenGL compatibility profile but in GLSL mark #version 420 core.Can it be the problem?
Update:
Some more info from Program Info Log:
error C7592: ARB_separate_shader_objects requrires built-in block gl_PerVertex to be redeclared before accesing its members.
Yeah , also the driver writer has typos "accesing " ;)
Now , I actually solved the linking error by adding this :
out gl_PerVertex
{
vec4 gl_Position;
};
It is strange that previous drivers didn't enforce redefinition of gl_PerVertex block.Now ,while this addon solved the issue with the linking, it opened another one where some varying uniforms don't work.For example I have in vertex shader:
out vec4 diffuseOut;
And in fragment shader:
in vec4 diffuseOut;
Then
OUTPUT = diffuseOut;/// returns black while red is expected.
Update 2 :
Ok , now it becomes clear - the new drivers are stricter on shaders input/output variables.With the older driver I could define several "outs" in a vertex shader but without defining also their "in" match in the fragment shader.It worked.Now it seems I am forced to have the exact match between declared "ins" and "outs" in vert and frag program.Strange that no errors are being thrown but the result is that the defined "ins" become empty in the destination.
In a GLSL vertex shader I have:
#version 330
layout (location=0) uniform mat4 wm_;
layout (location=1) uniform mat4 vm_;
...more code...
I get no compile errors when the shader is compiled. Later, I am assert()ing on glGetUniformLocation for wm_ and vm_ returning the locations specified in the shader source. The asserions fire, as glGetUniformLocation returns different values (it do not return -1, that is, the uniforms don't get optimized away, they get assigned what appear to be valid but different locations.)
Can anyone explain this behavior?
Explicit uniform locations are supported since GLSL 4.30 or by extension GL_ARB_explicit_uniform_location.
The compiler here is too tolerant and allows syntax that is not supported in GLSL 3.30
This should be considered as a driver bug.
On the OpenGL FBO wiki page there is this snippet:
You can also use layout syntax to define this directly in the shader,
as you would for attribute indices:
layout(location = 0) out vec4 mainColor;
layout(location = 1) out vec2 subsideraryInfo;
This seems to indicate that attribute indices can be specified within a shader, which would simplify things a bit my removing the need for my code to specify attribute locations and such using glBindAttribLocation.
Yes you can do that starting from GLSL 3.30 (OpenGL 3.3). Read here: http://www.opengl.org/registry/doc/GLSLangSpec.3.30.6.clean.pdf (page 35).