0

I'm learning modern OpenGL using the tutorial from opengl-tutorial.org.

Their vertex shaders alwas use the type vec3 to pass vertex coordinates to the vertex shader. According to the manuals it should be possible to use the type float as well. As my application gets the vertex coordinates as an array of floats I tried to use float to pass them, which doesn't work as expected. Even the Tutorial 5 : A Textured Cube of the tutorials shows the effect. If I change the vertex shader code from:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

// Values that stay constant for the whole mesh.
uniform mat4 MVP;

void main(){

    // Output position of the vertex, in clip space : MVP * position
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
    
    // UV of the vertex. No special space for this one.
    UV = vertexUV;
}

To:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in float vertexPosition_modelspace[3];
layout(location = 1) in vec2 vertexUV;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

// Values that stay constant for the whole mesh.
uniform mat4 MVP;

void main(){

    // Output position of the vertex, in clip space : MVP * position
    gl_Position =  MVP * vec4(vertexPosition_modelspace[0], vertexPosition_modelspace[1], vertexPosition_modelspace[2], 1);
    
    // UV of the vertex. No special space for this one.
    UV = vertexUV;
}

The cube isn't displayed correctly. I can see that passing arrays of floats to the vertex shader and accept them there as vec3 works, but what is wrong using float[3] as the type to pass arrays of floats or how is this to be done?

Isn't float[3] equal to vec3?

Furthermore I'm somewhat surprised, that writing the following line in variants:

layout(location = 0) in float[] vertexPosition_modelspace;

layout(location = 0) in float[3] vertexPosition_modelspace;

layout(location = 0) in float vertexPosition_modelspace[3];

Seems to compile and at least to run, without proper display, however.

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • 3
    Why you don't want to use `vec3` in the shader code. (`vec3` supports extended features compared to `float[3]`.) That doesn't prevent you to bind a `float[]` on CPU/C++ side for this attribute. (You even could bind a `float[][3]` array in C++ though I'm afraid to earn complaints from C++ purists concerning this.) – Scheff's Cat Sep 10 '20 at 11:25
  • Have a read of https://stackoverflow.com/questions/38172696/should-i-ever-use-a-vec3-inside-of-a-uniform-buffer-or-shader-storage-buffer-o – Richard Critten Sep 10 '20 at 11:40
  • 1
    @RichardCritten No, that is a completely different issue. This question is about the vertex shader interface. The link is about SSBO and UBO. – Rabbid76 Sep 10 '20 at 11:42
  • 1
    "Isn't `float[3]` equal to `vec3`?" No it isn't. – derhass Sep 10 '20 at 13:30

1 Answers1

4

The declaration:

layout(location = 0) in float vertexPosition_modelspace[3];

specifies that the array of float is distributed throughout the 3 consecutive layout locations, beginning at the location 0, specified in layout(location = 0).

So, the array values:

vertexPosition_modelspace[0], vertexPosition_modelspace[1], vertexPosition_modelspace[2]

are distributed respectively throughout layout locations from 0 to 2.

Then, the next declaration:

layout(location = 1) in vec2 vertexUV;

causes overwriting of the preceding array data at location = 1, resulting in deformations.

Therefore, to avoid this, you would need to either: declare the array last in the layout:

layout(location = 1) in float vertexPosition_modelspace[3];
layout(location = 0) in vec2 vertexUV;

or declare the other variable at location = 3, after the end of the preceding array:

layout(location = 0) in float vertexPosition_modelspace[3];
layout(location = 3) in vec2 vertexUV;
  • Radoslav, your explanation sounds reasonable, but I tried all of your proposals and none of them worked... – Thomas Krebs Sep 10 '20 at 12:11
  • @ThomasKrebs Is there any difference in the display? – Radoslav Voydanovich Sep 10 '20 at 12:22
  • @ThomasKrebs Are you appropriately passing the data to the shader from your program? Do you arrange and assign the vertex attributes accordingly? – Radoslav Voydanovich Sep 10 '20 at 12:44
  • 1
    @ThomasKrebs, if you really go thar route of using a `float[3]` as the interface, then it means you have to set up an attribute pointer for _each_ of the `x`, `y` and `z` components of your vectors - and the only advantage you get from that over `vec3` is that you don't have to have packed the data as `xyz` in memory, but could also use some other forms. – derhass Sep 10 '20 at 13:33
  • @Radoslav, My changes lead to a small white bar your changes led to no graphics at all. – Thomas Krebs Sep 10 '20 at 13:38
  • @Radoslav, I did not change anything beyond what I wrote and you proposed. I would expect that vec3 and float[3] would be equal... – Thomas Krebs Sep 10 '20 at 13:40
  • @ThomasKrebs They are not equal from the perspective of language interpretation. You need to handle them differently. You need to make appropriate changes on the program side. Specifically, the attribute number must correspond to the location declared for the variable in the shader. That is explained in the tutorials up to the point you were referring to. – Radoslav Voydanovich Sep 10 '20 at 13:42
  • @derhass, does that mean that vec[] cannot be used as a receiving type in a vertex shader, rather than passing the floats as individual elements? I learn, that the documentation of GLSL may be improved... Your answer above: what is the difference between vec3 and float[3]? – Thomas Krebs Sep 10 '20 at 13:43
  • @Radoslav I did the changes you proposed to change the attribute number to conform to the layout number. It didn't solve the problem. – Thomas Krebs Sep 10 '20 at 14:39
  • @ThomasKrebs Alright. I believe you need to create an appropriate attribute pointer for every component of the array, as derhass suggested. – Radoslav Voydanovich Sep 10 '20 at 14:48
  • 2
    @ThomasKrebs "does that mean that vec[] cannot be used as a receiving type in a vertex shader, rather than passing the floats as individual elements?" no, it does not mean that. Using types `vec3[n]`, `vec3` and `float[3]` as vertex attributes are three different cases, and each has to be handled appropriately. But it is totally unclear which problem you're even trying to solve here. So far, you only _created_ problems without any benefit. – derhass Sep 10 '20 at 16:03