在glVertexAttribPointer()中使用GL_INT_2_10_10_10_REV

时间:2012-12-26 06:42:22

标签: opengl glsl vertex-attributes

有人能告诉我在glVertexAttribPointer()中我们如何使用GL_INT_2_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 tk_position;
in vec4 color;

out vec4 v_color;

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

片段着色器 -

#version 150

in vec4 v_color;
out vec4 fragColor;

void main()
{
    fragColor =  v_color;
}

程序对象也经过验证。没问题。这段代码在AMD卡上工作正常,但在NVidia上失败了。失败意味着我在glDrawArrays()调用时获得NULL指针访问。

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

2 个答案:

答案 0 :(得分:16)

如果你传递颜色,那么你很可能想要 UNSIGNED _ INT_2_10_10_10_REV。所以我会假装这就是你所要求的。

整个字段打包成一个无符号整数。 OpenGL将无符号整数定义为大小为32位,因此您应该使用OpenGL提供的GLuint typedef来获取它。

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

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

因此,假设您有一些具有浮点精度的浮点颜色值。您必须将每个组件标准化为[0,1]范围。然后将每个值乘以2 10 - 1,从而扩展到[0,1023]范围。然后将每个组件转换为整数。

问题在于将其打包到实际领域。名称中的“REV”表示组件的顺序受到尊重。通常在OpenGL中,如果你看到像GL_UNSIGNED_SHORT_5_6_5这样的格式,那么这意味着每个无符号短路被分解成5位的模式,接着是6位,接着是5位。最左边的5位字段是红色,6位字段是绿色,最右边的5位字段是蓝色。

REV”意味着反过来。所以2_10_10_10_REV意味着两个最重要的位转到 alpha 。接下来的10位转到蓝色。然后是格林。然后是红色。

所以你必须在[0,1023]范围内捆绑整数,然后将它们推到GLuint值的正确位置。你可以为数组中的每个这样的组件做到这一点。

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

此代码假定alpha只有2个非零位,bluegreenred每个只有10个非零位。

答案 1 :(得分:4)

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

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

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

REV表示组件的顺序相反。

IIRC这种格式最常用于打包顶点法线,以减小顶点数据的大小。还没有真正看到它用于其他任何东西。

修改

另外,我发现this cool page的表格可以准确地显示哪些位代表哪些值。该网站主要使用日语,但表格均为英文。

编辑2

上述页面的链接已失效,here是另一个页面,其中包含如何布置值的表格。