Jump to content

vertex UV in GLSL


jwoelper

Recommended Posts

This seems like a very basic question and is related to GLSL, so I don't know if this is the right corner of the forum.

 

I have a simple working GLSL shader that pulls in the uv attribute.

 

This is the Vertex Shader:

#version 150
in vec3 P;
in vec3 N;
in vec2 uv;


out vec3 vPos; 
out vec3 vN;
out vec2 uvCoords;


uniform mat4 glH_ObjectMatrix;
uniform mat4 glH_ViewMatrix;
uniform mat4 glH_ProjectMatrix;
uniform mat3 glH_NormalMatrix;


void main() 
{ 
    vPos = vec3(glH_ViewMatrix * glH_ObjectMatrix * vec4(P, 1.0)); 
    vN  = normalize (glH_NormalMatrix * N); 
    uvCoords = uv; 
    gl_Position = glH_ProjectMatrix * vec4(vPos, 1.0);
} 

Fragment shader:

#version 150

uniform sampler2D t_diffmap;


in vec3 vN;
in vec2 uvCoords;
out vec4 color;


void main() {
    vec3 diff;
    diff = texture(t_diffmap, uvCoords).rgb;
    color = vec4(diff,1.0);  
}

Now, this works with point UVs. If my UVs are of vertex type, this does not work any more (the shader shows a single color only). Since 99% of my meshes will be vertex UV, I am seriously wondering how I get access to them in the GLSL shader...

 

Any help is appreciated!

 

 

Thanks in advance 

 

Johann

Link to comment
Share on other sites

OpenGL natively supports two attribute classes - detail and point attributes. Primitive and Vertex attributes are not natively supported and require extra shader support. Vertex attributes in particular require a geometry shader stage to assign the vertex attribute to each vertex of the triangle primitive.

 

If you do a File > New Operator Type, then SHOP:GLSL, you'll see a sample GLSL shader in the Code tab which shows how this is accomplished. The relevant code in the geometry shader is:

in parms
{
    vec4  pos;
    vec3  normal;
    vec4  color;
    vec2  texcoord0;
    float selected;
} gsIn[];

out wparms {
    vec4 pos;
    vec3 normal;
    vec4 color;
    vec2 texcoord0;
    noperspective out vec3 edgedist;
    flat out int edgeflags;
    float selected;
} gsOut;

uniform int     attrmodeuv;
uniform samplerBuffer attruv;

int  HOUprimitiveInfo(out ivec3 vertex); // will be linked in

void main()
{
....

     ivec3 vertex;
     int prim = HOUprimitiveInfo(vertex);
     
    if(attrmodeuv == 0) // point
        gsOut.texcoord0 = gsIn[0].texcoord0;
    else // vertex
        gsOut.texcoord0 = texelFetch(attruv, vertex.r).rg;
....
}

The 'attrmodeuv' uniform selects between point and vertex normals. The attruv texture buffer object contains the uv vertex data. The code assigning to gsOut needs to be done once per vertex, though with gsIn[0] and vertex.r, gsIn[1] and vertex.g, and gsIn[2] and vertex.b.

  • Like 2
Link to comment
Share on other sites

I might be off with this idea, but would it be possible to "simulate" a Houdini primitive attribute by propagating it "down" to the vertex level? For instance, if I have a texture file name attribute at the primitive level, is it possible to copy it on that primitive's every vertex and access it in the fragment shader to load that primitive?

 

To implement this, I have the attribute "problem" but I also need to know how I can instantiate all the textures I will need and be able to refer to it based on that attribute in the fragment shader. For instance, on the Mantra Surface "OpenGL" tab, you can attach more than one diffuse texture "layers". But I don't now how they are used or if it is possible to alternate between those based on a vertex attribute (demoted from a primitive attribute)…

 

Thanks!

 

Vincent

Link to comment
Share on other sites

I might be off with this idea, but would it be possible to "simulate" a Houdini primitive attribute by propagating it "down" to the vertex level? For instance, if I have a texture file name attribute at the primitive level, is it possible to copy it on that primitive's every vertex and access it in the fragment shader to load that primitive?

 

To implement this, I have the attribute "problem" but I also need to know how I can instantiate all the textures I will need and be able to refer to it based on that attribute in the fragment shader. For instance, on the Mantra Surface "OpenGL" tab, you can attach more than one diffuse texture "layers". But I don't now how they are used or if it is possible to alternate between those based on a vertex attribute (demoted from a primitive attribute)…

 

 

Primitive attributes are actually easier to support than vertex attributes, as they don't require a geometry shader. Fragment shaders can access the GL-builtin gl_PrimitiveId just like the geometry shader, and this can be used to look up a primitive attribute in TBO. But yes, you could promote a prim attribute to a vertex one and achieve the same effect - though the addition of the geometry shader stage does introduce a performance hit and the resulting TBO would be larger.

 

Prior to GL3, the way that Primitive and Vertex attributes were supported was to have the CPU "unroll" the attributes to vertex frequency. Take a cube - it has 8 points, 6 primitives (quads) and 24 vertices. When using just point or detail attributes, the position array is 8 elements long, and it uses an element index buffer to connect the quads up using those 8 elements.

 

However, when a primitive or vertex attribute is added to the cube, each point now has differing values for both the primitive and the vertex - and this isn't allowed by GL. So what happened was that the position array was promoted to vertex frequency, taking up 24 elements (3x larger). The primitive attribute would also be 24 elements (4x larger).

 

For a simple cube, this isn't a big deal. But for a 10M point mesh model with 40M vertex UVs - well, the extra storage require by vertex promotion becomes quite substantial. Turns out that using a geometry shader to access a TBO for the UVs is roughly the same performance as drawing the model as 40M unique points for P and UV, while saving a lot of VRAM and CPU->GPU transfer bandwidth (uploads are faster).

 

So that's the reason why the shaders are slightly more complex for primitive and vertex attributes.

Link to comment
Share on other sites

Hi Mark,

 

Thanks for this! What I want to do, then, is to have a primitive attribute to point to a specific texture set (diffuse, specular, opacity, displacement) to be used by the shader. Is it possible (you are mentioning that it is, "post-GL3", but can I do it in Houdini)? Thanks again!

 

Vincent

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...