Opengl 在glvertexattributepointer()中使用GL_INT_2_10_10_10_REV

Opengl 在glvertexattributepointer()中使用GL_INT_2_10_10_10_REV,opengl,glsl,vertex-attributes,Opengl,Glsl,Vertex Attributes,有谁能告诉我,在glvertexattributepointer()中,我们如何使用GL_INT_2_10_10_10_10_REV作为类型参数? 我正在尝试使用此类型传递颜色值。在这种类型中,“REV”后缀的意义是什么?它是否需要在着色器中进行任何特殊处理 我的代码如下: GLuint red=1023,green=1023,blue=1023,alpha=3; GLuint val = 0; val = val | (alpha << 30); val = val | (blu

有谁能告诉我,在glvertexattributepointer()中,我们如何使用GL_INT_2_10_10_10_10_REV作为类型参数? 我正在尝试使用此类型传递颜色值。在这种类型中,“REV”后缀的意义是什么?它是否需要在着色器中进行任何特殊处理

我的代码如下:

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);
片段着色器-

#version 150

in vec4 v_color;
out vec4 fragColor;

void main()
{
    fragColor =  v_color;
}
程序对象也经过了验证。没有问题。此代码在AMD卡上运行良好,但在NVidia上失败。失败意味着我在glDrawArrays()调用时获得空指针访问权限


让我们将其分解为可理解的部分:

INT
表示格式将被读取为整数

2_10_10_10
意味着第一个整数的位数为2位,下一个整数的位数为10位。请注意,这些值加起来等于32,即4字节整数中的位数

REV
表示部件顺序颠倒

IIRC此格式最常用于打包顶点法线,以减小顶点数据的大小。我真的没见过它被用在别的地方

编辑

此外,我还发现了一些表格,这些表格精确地显示了哪些位代表哪些值。该网站主要是日文,但表格是英文的

编辑2


上面页面的链接已关闭,这是另一个页面,其中包含值的布局表。

如果您正在传递颜色,则更可能需要未签名的\u INT\u 2\u 10\u 10\u REV。所以我会假装这就是你要的

整个字段压缩为一个无符号整数。OpenGL将无符号整数定义为正好32位,因此您应该使用OpenGL提供的
GLuint
typedef来获得一个无符号整数

但是,这种格式是打包的,所以不能将数组插入其中。这是压缩的一种形式,所以当您认真考虑使顶点属性数据变小时,通常会使用它

首先,对颜色使用10/10/10/2的唯一原因是,如果原始源颜色的颜色深度高于常规的每通道8位颜色。毕竟,RGB组件每个都有10位;如果您的源颜色只有8位,那么实际上您还没有获得任何新信息

假设有一些浮点颜色值,具有浮点精度。您必须将每个组件规格化到[0,1]范围。然后将每个值乘以210-1,从而扩展到[01023]范围。然后将每个组件转换为整数

问题在于如何将其打包到实际字段中。名称中的“
REV
”表示尊重组件的顺序。通常在OpenGL中,如果您看到类似于
GL\u UNSIGNED\u SHORT\u 5\u 6\u 5
的格式,则这意味着每个UNSIGNED SHORT都被分解为5位的模式,后跟6位,再后跟5位。最左侧的5位字段为红色,6位字段为绿色,最右侧的5位字段为蓝色

REV
”的意思是扭转这种局面。因此
2_10_10_10_10_REV
意味着两个最高有效位进入alpha。接下来的10位变成蓝色。然后是绿色。然后是红色

因此,您必须将[01023]范围内的整数捆绑起来,然后将它们放入GLuint值的正确位置。对数组中的每个这样的组件都这样做

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

val=val |(alpha这很有用,谢谢。第二部分仍然没有回答。如果我使用这种类型来指定颜色值,我该如何编码?下面的代码似乎不起作用:GLint data[]={32767327673276732767};glvertexattributepointer(1,GL_BGRA,GL_INT_2_10_10_REV,GL_TRUE,0,data);还可以详细说明到底是什么吗“顶点法线填充”?我发布的表格显示了哪些位对应于着色器中的哪些值。根据,您将获得一个
GL\u INVALID\u操作
,用于将大小设置为1而不是4。顶点法线填充是当您获取顶点的法线向量时(通常为3d向量或12字节)并将其压缩为一个字节。您将失去一点准确性,但对于法线,这不是一个明显的差异,但它会显著减小每个顶点的大小。我在这里没有将大小设置为1。GL_BGRA是我传递的“大小”参数。1对应于“索引”“的属性。@Jessy找到了另一个具有类似表的。它在AMD上运行良好,但在NVidia上以某种方式失败。感谢您的回答。什么“运行良好”?它是如何成功的?它是如何失败的?用“以某种方式失败”的代码补充您的问题。”。
Access violation
    Exception Flag: 0x00000000
    Exception Addr: 0x055f32ce
GLuint val = 0;
val = val | (alpha << 30);
val = val | (blue << 20);
val = val | (green << 10);
val = val | (red << 0);