Using GL_INT_2_10_10_10_REV in glVertexAttribPointer()

妖精的绣舞 提交于 2019-12-21 23:21:10

问题


Can anybody tell me how exactly do we use GL_INT_2_10_10_10_REV as type parameter in glVertexAttribPointer() ? I am trying to pass color values using this type. Also what is the significance of "REV" suffix in this type ? Does it require any special treatment in the shaders ?

My code is as follows :

GLuint red=1023,green=1023,blue=1023,alpha=3;

GLuint val = 0;
val = val | (alpha << 30);
val = val | (blue << 20);
val = val | (green << 10);
val = val | (red << 0);

GLuint test_data[]={val,val,val,val};

loadshaders();

glBindAttribLocation(ps,0,"tk_position");

glBindAttribLocation(ps,1,"color");

LinkShader();

glUseProgram(ps);

glEnableVertexAttribArray (0);

glVertexAttribPointer(0, 4, GL_FLOAT, 0, 0, vertices);

glEnableVertexAttribArray (1);

glVertexAttribPointer(1,GL_BGRA,GL_UNSIGNED_INT_2_10_10_10_REV,GL_TRUE,0,test_data);

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

The shaders are : Vertex Shader -

#version 150

in vec4 tk_position;
in vec4 color;

out vec4 v_color;

void main()
{
    v_color = color;
    gl_Position = tk_position; 
}

Fragment shader -

#version 150

in vec4 v_color;
out vec4 fragColor;

void main()
{
    fragColor =  v_color;
}

The program object is validated as well. No issues there. This code works fine on AMD card,but fails on NVidia. Failing means I get NULL Pointer access at glDrawArrays() call.

Access violation
    Exception Flag: 0x00000000
    Exception Addr: 0x055f32ce

回答1:


If you are passing colors, then more likely than not you want UNSIGNED_INT_2_10_10_10_REV. So I'll pretend that's what you asked for.

The entire field is packed into a single unsigned integer. OpenGL defines an unsigned integer to be exactly 32-bits in size, so you should use the GLuint typedef that OpenGL provides to get one.

However, this format is packed, so you can't just shove an array into it. It's a form of compression, so it's generally going to be used when you're serious about making your vertex attribute data small.

First, the only reason to use 10/10/10/2 for colors is if your original source colors have higher color-depth colors than, for example, the regular 8-bit-per-channel colors. After all, the RGB components will each have 10 bits; if your source colors only had 8 bits, you haven't actually gained any new information.

So let's say you have some floating-point color values, with floating-point precision. You have to normalize each component down to the [0, 1] range. Then you multiply each value by 210 - 1, thus expanding to the [0, 1023] range. Then you convert each component into integers.

The problem comes with packing it into the actual field. The "REV" in the name means that the order of components is revered. Normally in OpenGL, if you see a format like GL_UNSIGNED_SHORT_5_6_5, then this means that each unsigned short is broken down into a pattern of 5 bits, followed by 6 bits, followed by 5 more. The left-most 5-bit field is the Red, the 6-bit field is Green, and the right-most 5-bit field is Blue.

The "REV" means to reverse this. So 2_10_10_10_REV means that the two most significant bits go to the alpha. The next 10 bits go to Blue. Then Green. Then Red.

So you have to bundle your integers on the [0, 1023] range, and then shove them into the right place in the GLuint value. And you do that for every such component in the array.

GLuint val = 0;
val = val | (alpha << 30);
val = val | (blue << 20);
val = val | (green << 10);
val = val | (red << 0);

This code assumes that alpha only has 2 non-zero bits, and blue, green, and red each have only 10 non-zero bits.




回答2:


So let's break this down into understandable parts:

INT means that the format will be read as an integer.

2_10_10_10 means that the division of bits between is 2 bits for the first int and 10 bits for the next 3. Notice that these values add up to 32, the number of bits in a 4-byte integer.

REV means that the order of the components are reversed.

IIRC this format is most commonly used for packing vertex normals, in order to reduce the size of vertex data. Haven't really seen it used for anything else.

EDIT

Also, I found this cool page with tables that visualize exactly which bits represent which values. The site is mostly in Japanese, but the tables are in English.

EDIT 2

Link to the above page is dead, here is another page with a table of how the values are laid out.



来源:https://stackoverflow.com/questions/14036892/using-gl-int-2-10-10-10-rev-in-glvertexattribpointer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!