I am no where near a professional in shaders but I'm currently studying OpenGL and I know a couple things. I will try my best to help by answering the questions I do know about.
What is uniform sampler2D texture? Is that only in the fragment shader? Does it need a texture passed in or does it use a default texture?
To be able to work on generated textures, the fragment shader needs a way to access that texture's object.
GLSL has a built-in data type that does exactly that and that would be the sampler
. The sampler postfix defines what type the texture object is expected to be of, for example: sampler2D
.
(There's also sampler1D
and sampler3D
but that's totally irrelevant).
To answer some of the questions I provide a simple example:
Vertex Shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
}
Fragment Shader
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0f);
}
Sometimes I see fragment shaders which write "in vec2 some_var" and state that its passed in from the vertex shader but then I don't see the vertex shader actually passing anything to the fragment shader? Is this normal?
To pass an output from the vertex shader to the fragment shader, you need to specify that the variable is an output by using the out
keyword.
In the example above, out vec3 ourColor;
is outputted from the vertex shader to the fragment shader.
Now on the other hand, in order to accept inputs, the fragment shader needs to expect it, to specify that the fragment shader will be receiving input from the vertex shader, we use the in
keyword.
In the example above, that would be in vec3 ourColor;
.
To summarize, the out
keyword is used to specify that some variable is an output and the in
keyword specifies that a certain variable type is an expected input. This works because the specified out
and in
variables have matching types which is vec3
.
One thing to note is that the vertex shader should receive an input so it has something to work on, otherwise it won't be able to do anything. That input is in form of vertex data.
On the other hand, fragment shaders are also required to output a vec4
colour output variable.
For the vertex shader shown above, these would be:
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
For the fragment shader shown above, this would be:
out vec4 FragColor;
EDIT:
To follow up on your revised question:
To put it simply, Uniforms are another way to send data to shaders.
It is important to note that uniforms are global meaning that they are accessible by all shaders at any point.
is the code I provided a vertex shader or a fragment shader? Because it wants an in vec2?
The first observation we could make in the shader code you've provided to determine which type of shader this is, is that the shader outputs a vec4, which is the required output by the fragment shader, but this isn't concrete evidence that this is a fragment shader.
To be able to better identify which shader you're currently looking at, it is important to have an idea about the role of each shader.
Put simply, the vertex shader also allows us to do stuff with the attributes of the vertices it receives as input, such as the position.
The fragment shader's responsibility is basically to calculate the final colour of pixels that are in between the vertices.
In the shader code you've provided in the question, we can determine that the operations applied are more related to calculating the final colour and outputting it using out vec4 color;
, which is the what the fragment shader is responsible of.
In the code v_tex is a vec2 does that mean the vertex shader is passing in a vec2 to this fragment shader? What exactly is v_tex?
Yes, this means that the fragment shader is expecting an input of the type vec2
. As stated above in the answer, to accept an input from the vertex shader, we need to specify that a certain variable is expecting a value of a certain type (vec2
) from the vertex shader using the in
keyword.
In the vertex shader, there's a variable of type vec2
that has the out
keyword and it matches the type of v_tex
which is vec2
.
v_tex
is a vec2
which means that it can hold 2 floats.
I believe it represents the texture coordinates for the current pixel.
As for it's role in the code you've provided, as far as I can understand, center
is being subtracted from v_tex
and then normalized, then the result is scaled by u_amount
which should represent the displacement amount.
The result of this operation is a normalized vec2
that is scaled by u_amount
. It is based on the difference between the current pixel coordinates and the centre of the texture.
To actually apply this displacement effect, we need to set the colour of the current pixel.
The color = texture(u_texture, v_tex - displacement)
operation samples the texture u_texture
at the texture coordinates v_tex - displacement
.
In simpler words, what this does is that it gets the colour of the pixel that is at the v_tex - displacement
coordinate of the u_texture
texture and assigns it to the colour of the current pixel (which is the pixel at the v_tex
coordinates).
The final colour is then outputted.
I don't know what the exact result of this shader output looks like but I hope that I was able to at least give you an idea about what this is doing.
If you'd like to understand more about shaders, I highly, highly, recommend reading the "Shaders" section in the "Getting Started" chapter of the LearnOpenGL book.
Link to the "Shaders" section: Shaders Section