54
\$\begingroup\$

I don't really understand how to use the in / out keywords in GLSL, and google is being uncharacteristically unhelpful.

What exactly do they do? How would I use them if, for example, I want to pass a varying variable set per vertex to the fragment shader?

Literally every tutorial I find uses the varying / attribute keywords and that's not helpful.

\$\endgroup\$

1 Answer 1

77
\$\begingroup\$

The storage qualifiers in and out actually have a purpose that contains and supersedes that of varying and attribute. They define what variables are respectively inputs and outputs for the shader. See the GLSL 4.2 reference card page 7:

  • in: linkage into shader from previous stage
  • out: linkage out of a shader to next stage
  • attribute: same as in for vertex shader
  • varying: same as out for vertex shader, same as in for fragment shader (Note: these are erroneously flipped around in the above-mentioned reference card.)

With the side note that the latter two are sort of deprecated: they are not present in the 4.2 core profile, only in the compatibility profile.


What exactly do they do?

As for usage, take the vertex shader from An intro to modern OpenGL. Chapter 2.2: Shaders:

#version 110

attribute vec2 position;    
varying vec2 texcoord;

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
    texcoord = position * vec2(0.5) + vec2(0.5);
}

It should be rewritten in 4.2 core as:

#version 420

in vec2 position;    
out vec2 texcoord;

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
    texcoord = position * vec2(0.5) + vec2(0.5);
}

in/out for function parameters

From the Parameters section in the Khronos wiki:

void MyFunction(in float inputValue, out int outputValue, inout float
inAndOutValue);

Functions in GLSL use a calling convention called "value-return." This means that values passed to functions are copied into parameters when the function is called, and outputs are copied out when the function returns.

The in, out, and inout qualifiers are not the same as type qualifiers, even though some of them are named the same. These are parameter qualifiers, and they have a different meaning here.

A parameter declared as in means that the value given to that parameter will be copied into the parameter when the function is called. The function may then modify that parameter as they see fit, but those changes will not affect the calling code.

A parameter declared as out will not have its value initialized by the caller. The function will modify the parameter, and after the function's execution is complete, the value of the parameter will be copied out into the variable that the user specified when calling the function. Note that the initial value of the parameter at the start of the function being called is undefined, just as if one had simply created a local variable.

The inout declaration combines both. The parameter's value will be initialized by the value supplied by the user, and its final value will be output

The default if no qualifier is specific is in.


Unhelpful Tutorials

I'm guessing the main reason you find "outdated" tutorial code is that not everyone has access to GLSL 3.3+ compatible hardware. Regardless, for a good and more up to date tutorial I'll gladly point you in the direction of Nicol Bolas' Learning Modern 3D Graphics Programming.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ @NicolBolas Ha! I already figured there was something fishy with that. That's an error in that reference card then. Thanks! :-) \$\endgroup\$
    – Eric
    May 26, 2012 at 21:36
  • 1
    \$\begingroup\$ Those tutorials from 2012 are outdated by now, with DSA and all that. Better get the Red and Blue book latest editions and (even better) read the specification. Compared to Vulkan, the specifications (OpenGL and GLSL) are a piece of cake. With cream. \$\endgroup\$
    – user144188
    Nov 1, 2020 at 16:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .