Explanation of corner id? [solved]

I learned more about shaders the last few weeks but one thing I still don't really get and that's corner ids.

I can observe that

this line: mod(in_Colour.r * 255.0, 2.0);
returns 0 for the even vertices 0 & 2 or top-left and bottom-right and
returns 1 for the uneven vertices 1 & 3 or top-right and bottom-left

this line: abs(mod(in_Colour.b * 255.0, 2.0));
returns 0 for vertices 0 & 1 and
returns 1 for vertices 2 & 3

So logically this line: abs(mod(in_Colour.b * 255.0, 2.0) - mod(in_Colour.r * 255.0, 2.0));
returns 0 for vertices 0 & 3 and
returns 1 for vertices 1 & 2

So I realize I can use this to get interpolated normalized x/y-coords to pass to the fragment shader instead or additional to v_vTexcoord. flyingsaucerinvasion was so kind to point me to this method.

I just absolutely don't understand why this works.

What exactly is corner id?
What are those 2 bits stolen from the colour as the documentation "explains"?
Why can I retrieve a number 0, -1 or 1 when multiplying the colour by 255 and then checking for eveness by modding by 2?

Could anyone explain that to me? I hate not understanding things.

(edit: To my surprise this question was moved to the advanced programming discussion subforum. Now I hope the answers won't be too complicated for me to understand.)
 
Last edited:

Bart

WiseBart
Hi,

I haven't used shader_enable_corner_id() myself yet, but I can try to explain what it does.

The problem that enabling it solves is that you don't know which vertex of a triangle you're dealing with once you're in the vertex shader.

A vertex buffer is really just a bunch of vertices, like this:
Code:
t1    t2    t3     ...   Triangles
v0v1v2v3v4v5v6v7v8 ...   Vertices
You could also "zoom in" on a single vertex like below:

Code:
v0
x           y           z           nx          ny          nz          r  g  b  a  u           v
0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35     Byte

If you look at the contents of the above vertex buffer, you can tell exactly where each vertex is located.
t1 contains vertices v0, v1 and v2, in that order. Or: v0, v1 and v2 form t1.
t2 contains vertices v3, v4 and v5, in that order, etc. Or: v3, v4 and v5 form t2.

So when you create the vertex buffer, you can say: "I've now written the first vertex of the first triangle", "I've now written the second vertex of the first triangle", ...
You know which vertices are used to form which triangle and in which order.

If you specify pr_trianglelist in the call to vertex_submit, you tell the GPU to expect each 3 consecutive vertices in the buffer to form a triangle, in the specified order.

In the vertex shader, you only have information about the current vertex being processed, and no information on its relation to other vertices or triangles (which you did define however when filling the vertex buffer). In the vertex shader, you know you're dealing with a vertex, but is it the first, the second or the third vertex of a triangle? There's no way to tell.
(If you look at the rendering pipeline, you'll notice that "primitive assembly", which is basically putting the separate vertices back together to form their respective triangles, takes place after the vertex shader.)

One of the ways to know this is by enabling corner id's.

Since a triangle contains 3 vertices, you need 3 indices to represent each possible vertex.
3 indices can be represented with 2 bits, since 2 bits allow 4 possible combinations:
Code:
00  // vertex 0 of triangle
01  // vertex 1 of triangle
10  // vertex 2 of triangle
11  // unused
rb
One of the above combinations is actually not used, since a triangle has 3 vertices.

When you set shader_enable_corner_id(true), GM overwrites the 2 lowest bits of the r and b colour components. It 'steals' the lowest bits from r and b.
That does mean that the colour that ends up on screen might not be 'exactly' the colour that you specified when building the vertex buffer.
But visually, you won't see the difference, since those lowest bits represent the smallest change possible in those colours. If you have a look at the below image:
you cannot see the difference between red and blue where the lowest bit differs.

So if you have to know which vertex you're dealing with, using the corner id option is a good way to get this information in the vertex shader without using extra memory, yet you loose some (negligible) precision in colour.
Also, you don't have to implement it yourself. It's handled by GM.

Using mod(in_Colour.r * 255.0, 2.0) is a way to extract those lowest bits from the r and b values. You might as well do that using bitwise operations.

Hope this clarifies a bit.

Bart
 
Thank you very much, Bart. This answers even more questions I knew I had.
Additionally to what those two stolen bits are I just learned how a vertex buffer looks (and what that basîcally is for that matter) and what is lost when enabling corner id. I already assumed it would change the colour a bit but didn't understand how. Now I know I don't need to worry about that too much unless I pick a colour from the surface or buffer to compare.

So this is one of the most helpful posts I've ever seen :)

I'm currently working on a tutorial series for people struggling to understand shaders - like me. It took me a very long time to understand even the basics. Is it ok if I use your explanations in one of the tutorials and refer to this post?

And I'm trying to play around with primitves, vertices and vertex buffers now. Hope it's ok if I add questions in this thread when I hit a problem I can't figure out.

Edit Dec 25th 17: Finally the video tutorial series reached the topic "corner id". Whoever's interested, here's a link to the playlist:
https://www.youtube.com/playlist?list=PL0kTSdIvQNCNE-BDKOlYu628AalMmXy_P

and to the corner id video:
 
Last edited:

Bart

WiseBart
Nice to hear that my explanations could be helpful.
Do feel free to use them if they can be of use :).
 
Top