When switching to GLSL 300, met the following error - glsl

when I switch to use OpenGL ES 3 with GLSL 300, I met the following error in my frag shader
undeclared identifier gl_FragColor
when using GLSL 100, everything is fine.

Modern versions of GLSL do fragment shader outputs simply by declaring them as out values, and gl_FragColor is no longer supported, hence your error. Try this:
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Note that gl_FragDepth hasn't changed and is still available.
For more information see https://www.opengl.org/wiki/Fragment_Shader

The predefined variable gl_FragColor does not exist anymore in GLSL ES 3.00. You need to define your own out variable for the output of the fragment shader. You can use any name you want, for example:
out vec4 FragColor;
void main() {
...
FragColor = ...;
}
This follows the Core Profile of full OpenGL. The reason for not having a pre-defined fragment shader output is that it does not scale well for multiple render targets, and for render targets that need types other than float vectors.

Related

Vertex Shader for a Particle System

I'm working on a simple particle system in OpenGL; so far I've written two fragment shaders to update velocities and positions in response to my mouse, and they seem to work! I've looked at those two textures and they both seem to respond properly (going from random noise to an orderly structure in response to my mouse).
However, I'm having issues with how to draw the particles. I'm rather new to vertex shaders (having previously only used fragment shaders); it's my understanding that the usual way is a vertex shader like this:
uniform sampler2DRect tex;
varying vec4 cur;
void main() {
gl_FrontColor = gl_Color;
cur = texture2DRect(tex, gl_Vertex.xy);
vec2 pos = cur.xy;
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 0., 1.);
}
Would transform the coordinates to the proper place according to the values in the position buffer. However, I'm getting gl errors when I run this that it can't be compiled -- after some research, it seems that gl_ModelViewProjectionMatrix is deprecated.
What would be the proper way to do this now that the model view matrix is deprecated? I'm not trying to do anything fancy with perspective, I just need a plain orthogonal view of the texture.
thanks!
What version of GLSL are you using (don't see any #version directive)? Yes, i think gl_ModelViewProjectionMatrix is really deprecated. However if you want to use it maybe this could help. By the way varying qualifier is quite old too. I would rather use in and out qualifiers it makes your shader code more 'readable'.
'Proper' way of doing that is that you create your own matrices - model and view (use glm library for example) and multiply them and then pass them as uniform to your shader. Tutorial with an example can be found here.
Here is my vs shader i used for displaying texture (fullscreen quad):
#version 430
layout(location = 0) in vec2 vPosition;
layout(location = 1) in vec2 vUV;
out vec2 uv;
void main()
{
gl_Position = vec4(vPosition,1.0,1.0);
uv = vUV;
}
fragment shader:
#version 430
in vec2 uv;
out vec4 final_color;
uniform sampler2D tex;
void main()
{
final_color = texture(tex, uv).rgba;
}
and here are my coordinates (mine are static, but you can change it and update buffer - shader can be the same):
//Quad verticles - omitted z coord, because it will always be 1
float pos[] = {
-1.0, 1.0,
1.0, 1.0,
-1.0, -1.0,
1.0, -1.0
};
float uv[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0
};
Maybe you could try to turn off depth comparison before executing this shader glDisable(GL_DEPTH_TEST);

How to resolve gl_Layer not accessible in Fragment shader

I am using gl_Layer for layered rendering and I allot a layer value in geometry shader. However, when I use gl_Layer in Fragment shader I get the error:
gl_Layer is not accessible in this profile
Here is my shader:
#version 400 core
uniform sampler2DArray diffuse;
in vec2 outtexcoords;
layout(location = 0, index = 0) out vec4 FragColor;
void main()
{
FragColor = texture(diffuse, vec3(outtexcoords, gl_Layer));
}
I can ofcourse bypass this by using another in/out variable, but I want to know what is the problem in using gl_Layer in fragment shader.
I have tried using "in int gl_Layer" in Fragment program, but I guess that is not the solution because its in an inbuilt variable.
Is it because I am not using the right extension? Or that my GL version doesnt support it yet?
You specified GLSL 4.0 core profile, but its spec says that gl_Layer may be used only in geometry shader, and only as output parameter. Previous GLSL versions allowed it's use in fragment shader as read-only variable.

Invalide value when using EmitVertex in GLSL version 150

This glsl shader compiles fine, but when I try to activate it with glUseProgram(); opengl gives me an invalid value error:
#vert
#version 150
uniform mat4 projectionmodelview_matrix_;
in vec3 global_position_;
void main(void) {
gl_Position = projectionmodelview_matrix_ * vec4(global_position_, 1.0);
EmitVertex();
gl_Position = projectionmodelview_matrix_ * vec4(global_position_, 1.0);
EmitVertex();
gl_Position = projectionmodelview_matrix_ * vec4(global_position_, 1.0);
EmitVertex();
EndPrimitive();
}
#frag
#version 150
out vec4 out_color_;
void main(void) {
out_color_ = vec4(1.0, 0.0, 0.0, 1.0);
}
However, if I remove the parts which emit vertices, it works. What am I doing wrong?
Easy answer, a vertex shader cannot use EmitVertex and EndPrimitive. A vertex shader is invoked once for each vertex passed through the pipeline and puts out the varying values for that single vertex. It cannot create or discard any vertices or primitives (it doesn't even have a reasonable notion of primitives at all). What you need for this is a geometry shader (though your code doesn't make so much sense at all, putting out a triangle that has the same vertex for each corner, so there wouldn't be anything rasterized at all).
So given that this vertex shader is plain illegal, I actually doubt the truth of the statement "This glsl shader compiles fine", and the GL_INVALID_VALUE error seems reasonable. Though GL_INVALID_VALUE would actually be thrown for a program that wasn't generated by the GL (but that may also be due to some wrapper framework just deleting a not successfully compiled and linked program, strange though).

converting GLSL #130 segment to #330

I have the following piece of shader code that works perfectly with GLSL #130, but I would like to convert it to code that works with version #330 (as somehow the #130 version doesn't work on my Ubuntu machine with a Geforce 210; the shader does nothing). After several failed attempts (I keep getting undescribed link errors) I've decided to ask for some help. The code below dynamically changes the contrast and brightness of a texture using the uniform variables Brightness and Contrast. I have implemented it in Python using PyOpenGL:
def createShader():
"""
Compile a shader that adjusts contrast and brightness of active texture
Returns
OpenGL.shader - reference to shader
dict - reference to variables that can be passed to the shader
"""
fragmentShader = shaders.compileShader("""#version 130
uniform sampler2D Texture;
uniform float Brightness;
uniform float Contrast;
uniform vec4 AverageLuminance;
void main(void)
{
vec4 texColour = texture2D(Texture, gl_TexCoord[0].st);
gl_FragColor = mix(texColour * Brightness,
mix(AverageLuminance, texColour, Contrast), 0.5);
}
""", GL_FRAGMENT_SHADER)
shader = shaders.compileProgram(fragmentShader)
uniform_locations = {
'Brightness': glGetUniformLocation( shader, 'Brightness' ),
'Contrast': glGetUniformLocation( shader, 'Contrast' ),
'AverageLuminance': glGetUniformLocation( shader, 'AverageLuminance' ),
'Texture': glGetUniformLocation( shader, 'Texture' )
}
return shader, uniform_locations
I've looked up the changes that need to made for the new GLSL version and tried changing the fragment shader code to the following, but then only get non-descriptive Link errors:
fragmentShader = shaders.compileShader("""#version 330
uniform sampler2D Texture;
uniform float Brightness;
uniform float Contrast;
uniform vec4 AverageLuminance;
in vec2 TexCoord;
out vec4 FragColor;
void main(void)
{
vec4 texColour = texture2D(Texture, TexCoord);
FragColor = mix(texColour * Brightness,
mix(AverageLuminance, texColour, Contrast), 0.5);
}
""", GL_FRAGMENT_SHADER)
Is there anyone that can help me with this conversion?
I doubt that raising the shader version profile will solve any issue. #version 330 is OpenGL-3.3 and according to the NVidia product website the maximum OpenGL version supported by the GeForce 210 is OpenGL-3.1, i.e. #version 140
I created no vertex shader cause I didn't think I'd need one (I wouldn't know what I should make it do). It worked before without any vertex shader as well.
Probably only as long as you didn't use a fragment shader or before you were attempting to use a texture. The fragment shader needs input variables, coming from a vertex shader, to have something it can use as texture coordinates. TexCoord is not a built-in variable (and with higher GLSL versions any builtin variables suitable for the job have been removed), so you need to fill that with value (and sense) in a vertex shader.
the glGetString(GL_VERSION) on the NVidia machine reads out OpenGL version 3.3.0. This is Ubuntu, so it might be possible that it differs with the windows specifications?
Do you have the NVidia propriatary drivers installed? And are they actually used? Check with glxinfo or glGetString(GL_RENDERER). OpenGL-3.3 is not too far from OpenGL-3.1 and in theory OpenGL major versions map to hardware capabilities.

How does the default GLSL shaders look like? for version 330

What do the default vertex, fragment and geometry GLSL shaders look like for version #330?
I'll be using #version 330 GLSL Version 3.30 NVIDIA via Cg compiler, because that is what my graphics card supports.
With default shaders, I mean shaders that do the same exact thing as the graphics card would do when the shader program is turned off.
I can't find a good example for #version 330. Been googling all day. Not sure if the term default shader is called something else like trivial or basic and if that is why I can't find it.
Any recommendations for a book with version 330 or link to an easy beginner tutorial with version 330 would be great as well.
example of a trivial vertex shader in #version 110, does the default vertex transformation
#version 110
void main()
{
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
}
example of a trivial fragment shader in #version 110, turns color into red
#version 110
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
There are no "default" shaders with OpenGL. It looks like what you want a very simple example of a shader that transforms vertices to clip space and gives them a color, so here you go:
Vertex shader:
#version 330
layout(location = 0)in vec4 vert;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
void main()
{
gl_Position = projection * view * model * vert;
}
Fragment shader:
#version 330
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
The core OpenGL 3.3 profile drops support for a lot of old fixed-function things like the matrix stack. You are expected to handle your own matrices and send them to your shaders. There is no ftransform, and gl_Position is pretty much the only valid gl_* variable.
While glBindAttribLocation is not deprecated, the preferred method of defining the location of vertex attributes is through "layout(location = x)" in GLSL.
In the vertex shader, "attribute" is now "in" and "varying" is now "out". In the fragment shader, "varying" is now "in" and "gl_FragColor" is defined by an "out" variable. I believe that gl_FragColor is still valid, but now it's possible to use an out variable to define the color.
This tutorial is very good and teaches core OpenGL and GLSL 3.30, I would recommend you use it to help you learn more about GLSL. Also remember that the GLSL Reference Pages is your friend.