[OpenGL] glVertexAttribPointer函数与glVertexAttribIPointer函数使用中遇到的小坑(int类型被自动转换为float类型)

起因:用OpenGL ES的变换反馈(transform feedback)特性,在GPU上实现图象处理中常用的查表映射功能(LookUp Table Map)。

 

这是一个工作量在五天以内的小项目(简单分为三个部分:一、分配顶点数组,二、写着色器,三、利用变换反馈把结果取回内存。)

本应该自己来做。但是凑巧有个算法移植到CUDA平台的工作在手,于是就拜托公司一位比较熟悉OpenGL ES的实习生来做,先第一部分和第三部分,第二部分可以暂时以一个简单的着色器来替代,先把整个框架搭起来。

 

过了三天,自己手头的事情做好了。就问他做的怎么样,有没有遇到什么问题。小伙子说,框架搭好了,但是遇到了一个百思不得其解的问题,传进去着色器的-1,没做任何改变,纯粹地返回,但是在读出来的时候总是-1082130432。(其中int类型的数字-1是表中较常出现的数字。)

 

简单review了一下,代码大致没什么问题。

 

排查-1变成-1082130432的问题。

 

用以下代码测试

float f = -1.0f;

printf("%d\n", *(int*)&f);

得到的输出结果就是-1082130432。

所以很明显,在传入着色器的过程当中,int类型的-1被转化成了float类型的-1,所以我们在读取以int类型再去读取它的时候,就读出了-1082130432这个数字。

bug定位好了之后,就开始排查数据进入着色器的过程中是否出现了问题。

 

最后发现,小伙子用了glVertexAttribPointer函数来指定每个顶点的属性,但是这个函数在normalized属性被设置为GL_FALSE时,非float类型的数值将被转换成float类型。于是int类型的-1就被转换成了float类型。

改用glVertexAttribIPointer函数,bug解决。

 

OpenGL ES 3中的glVertexAttribPointer与glVertexAttribIPointer的文档摘录如下:

For glVertexAttribPointer, if normalized is set to GL_TRUE, it indicates that values stored in an integer format are to be mapped to the range [-1,1] (for signed values) or [0,1] (for unsigned values) when they are accessed and converted to floating point. Otherwise, values will be converted to floats directly without normalization.

For glVertexAttribIPointer, only the integer types GL_BYTEGL_UNSIGNED_BYTEGL_SHORTGL_UNSIGNED_SHORTGL_INTGL_UNSIGNED_INT are accepted. Values are always left as integer values.

 

posted @ 2016-03-05 15:07  nipan  阅读(3214)  评论(0编辑  收藏  举报