const GLchar* vertexSource1 = "#version 330 core\n"
"layout (location = 0) in vec2 position;\n"
"layout (location = 1) in vec3 color;\n"
"out vec3 Color;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position, 0.0, 1.0);\n"
"Color = color;\n"
"}\0";
const GLchar* fragmentSource1 = "#version 330 core\n"
" in vec3 Color;\n"
" out vec4 outColor;\n"
" void main()\n"
" {\n"
" outColor = vec4(Color, 1.0);\n"
" }\n";
GLuint shaderProgram1 = glCreateProgram();
glAttachShader(shaderProgram1, vertexShader1);
glAttachShader(shaderProgram1, fragmentShader1);
// glBindFragDataLocation(shaderProgram1, 0, "Color");
glLinkProgram(shaderProgram1);
Whether I add glBindFragDataLocation or not, the GL works correctly, Why?
Because you're "lucky". The OpenGL specification provides no guarantees about how fragment shader output locations are assigned if you don't assign them. It only says that each one will have a separate location; what locations those are is up to the implementation.
However, considering the sheer volume of code that writes to a single output variable without explicitly assigning it to a location, it's highly unlikely that an OpenGL implementation would ever assign the first FS output location to anything other than 0. So while it isn't a spec guarantee, at this point, it is a de-facto requirement of implementations.
Note: That doesn't mean you shouldn't assign that location manually. It's always best to be on the safe and explicit side.
FYI: layout(location) works for fragment shader outputs too. So you should use that if you're using it on vertex attributes. Then you don't have to worry about doing it from code.
Related
Can you write OpenGL shader in a different file and later link it to the program? and if it's possible how? writing OpenGL shader in string makes my code messy.
Here is example code for shaders:
const char* vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"\n"
"out vec3 ourColor;\n"
"uniform vec2 angleValues;\n"
"\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x * angleValues.x - aPos.y * angleValues.y, aPos.y * angleValues.x + aPos.x * angleValues.y , aPos.z, 1.0);\n"
"ourColor = aColor;\n"
"}\n";
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"in vec3 ourColor;\n"
"\n"
"void main()\n"
"{\n"
"FragColor = vec4(ourColor, 1.0);\n"
"}\n";
Yes, you can have files like my_shader.vs or my_fragment.fs and link them like in this Shader class
Just initialize it like this:
shader = Shader("./shaders/my_shader.vs", "./shaders/my_fragment.fs");
I have a single VBO with the following vertex attributes:
3 floats for x,y,z
3 floats for r,g,b
2 floats for velocity_x,velocity_y
I'd like to apply the velocity of a given vertex to its position, in the vertex shader and have done this so far, but it doesn't seem to be applying any changes:
"#version 330 core\n"
"layout (location = 0) in vec3 vertexPos;\n"
"layout (location = 1) in vec3 vertexColor;\n"
"layout (location = 2) in vec2 vertexVelocity;\n"
"vec3 newPosition;\n"
"out vec3 vertexColorRes;\n"
"uniform mat4 viewMatrix;\n"
"uniform mat4 projectionMatrix;\n"
"void main()\n"
"{\n"
" newPosition = vertexPos + vec3(vertexVelocity, 1.0);\n"
" gl_Position = projectionMatrix * viewMatrix * vec4(newPosition, 1.0);\n"
" vertexColorRes = vertexColor;\n"
"}\0"));
What seems to be the problem?
I've created a very basic shader:
static const char *frag_showImage =
"#version 150\n"
"uniform sampler2D textureSampler;\n"
"in mediump vec2 texc;\n"
"out highp vec4 fragColor;\n"
"void main() {\n"
" fragColor = texture2D(textureSampler, texc.st);\n"
"}\n";
And it works as expected, now a bit more complex one:
"#version 150\n"
"uniform sampler2D textureSampler;\n"
"uniform sampler2D maskSampler;\n"
"in mediump vec2 texc;\n"
"out highp vec4 fragColor;\n"
"void main() {\n"
" fragColor = texture2D(textureSampler, texc.st);\n"
" fragColor.x = texture2D(maskSampler, texc.st).x;\n"
" fragColor.y =0;\n"
"}\n";
It doesn't work but it has no warnings neither errors:
in both cases I bind the first texture as:
QOpenGLFunctions *f =this->context()->functions();
f->glActiveTexture(GL_TEXTURE0);
glBaseTexture->bind();
m_program->setUniformValue("textureSampler", 0);
and the second texture is binded as:
f->glActiveTexture(GL_TEXTURE1);
glMaskTexture->bind();
m_program->setUniformValue("maskSampler", 1);
Notice that if I bind glMaskTexture for the first shader it works ok so the problem is not on that QOpenGlTexture.
Any idea? Thank you in advance!
Goblins: renaming maskSampler to other name it works ok, I have no idea about why this is happening since "maskSampler" is not used in any other part of the code.
I am writing an OpenGL / C++ plugin using VBO and GLSL shaders. However, while I can compile the shaders successfully, and link them to the program, its status link check with glGetProgramiv(...,GL_LINK_STATUS,...) returns a "No definition of main in vertex shader" error.
The vertex shader is sending a color to the fragment shader. If I remove this color-passing, the link is successfully validated.
What's wrong in my code if I want to pass color to fragment shader ?
const GLchar *vert_src =
"#version 410\n"
"layout (location = 0) in vec3 Pos;\n"
"layout (location = 1) in vec3 vColor;\n"
"uniform mat4 projectionMatrix;\n"
"uniform mat4 modelViewMatrix;\n"
"out vec3 color;\n"; // -> REMOVING THIS LINE MAKES THE VALIDATION WORK
"void main() {\n"
" color=vColor;\n" // -> AND THIS LINE TOO
" gl_Position = projectionMatrix*modelViewMatrix*vec4(Pos.x, Pos.y, Pos.z, 1.0);"
"}\n";
const GLchar *frag_src =
"#version 410\n"
"in vec3 color;\n";
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vec4(color, 1.0);"
"}\n";
GLuint program = glCreateProgram();
GLuint v_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint f_shader = glCreateShader(GL_FRAGMENT_SHADER);
int len=(GLint)strlen(vert_src);
glShaderSource(v_shader, 1, &vert_src, &len);
glCompileShader(v_shader);
glGetShaderiv(v_shader, GL_COMPILE_STATUS, &success); --> SUCCESS
len=(GLint)strlen(frag_src);
glShaderSource(f_shader, 1, &frag_src, &len);
glCompileShader(f_shader);
glGetShaderiv(f_shader, GL_COMPILE_STATUS, &success); --> SUCCESS
glAttachShader(program, v_shader); --> SUCCESS
glAttachShader(program, f_shader); --> SUCCESS
glLinkProgram(program); --> SUCCESS
glValidateProgram(program); --> SUCCESS
glGetProgramiv(program, GL_LINK_STATUS, &success); --> ERROR: Program is not successfully linked
[...] rest of code
You have semicolons outside the strings that should not be there:
const GLchar *vert_src =
"#version 410\n"
"layout (location = 0) in vec3 Pos;\n"
"layout (location = 1) in vec3 vColor;\n"
"uniform mat4 projectionMatrix;\n"
"uniform mat4 modelViewMatrix;\n"
"out vec3 color;\n"; // <- HERE YOU HAVE A SEMICOLON
"void main() {\n"
" color=vColor;\n"
" gl_Position = projectionMatrix*modelViewMatrix*vec4(Pos.x, Pos.y, Pos.z, 1.0);"
"}\n";
const GLchar *frag_src =
"#version 410\n"
"in vec3 color;\n"; // <- HERE YOU HAVE ANOTHER SEMICOLON
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vec4(color, 1.0);"
"}\n";
In GLSL I didnt understood what is "in" and "out" variables, what does it mean?
Here is a sample of my code that I copied from a tutorial.
// Shader sources
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"in vec3 color;"
"out vec3 Color;"
"void main() {"
" Color = color;"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"in vec3 Color;"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(Color, 1.0);"
"}";
Variables declared in and out at "file" scope like that refer to stage input/output.
In a vertex shader, a variable declared in is a vertex attribute and is matched by an integer location to a vertex attribute pointer in OpenGL.
In a fragment shader, a variable declared in should match, by name, an output from the vertex shader (same name, but out).
In a fragment shader, a variable declared out is a color output and has a corresponding color attachment in the framebuffer you are drawing to.
In your vertex shader, you have two vertex attributes (position and color) used to compute the interpolated input in the fragment shader (Color). The fragment shader writes the interpolated color to the color buffer attachment identified by outColor.
It is impossible to tell what vertex attributes position and color and what color buffer outColor are associated with from your shader code. Those must be set in GL code through calls like glBindAttribLocation (...) and glBindFragDataLocation (...) prior to linking.