简单的问题:
默认情况下,OpenGL是否将纹理值剪辑到0-1范围?如果有,有办法禁用它吗?
详细问题:
我有一个纹理,在创建时,我将一些默认值放入。
我创建RGBA值大小为16x16的纹理,如下所示:
//Generate the texture and get its ID
GLuint texID;
glGenTextures(1, &texID);
//Bind the texture
glBindTexture(GL_TEXTURE_2D, texID);
//Define the size of the texture
int width = 16;
int height = 16;
int numberOfElementsPerTexel = 4;
int size = width * height * numberOfElementsPerTexel;
//Create an empty array of texel data
float data[size];
std::fill_n(data, size, 0.0f);
//Add the empty data to the texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, GL_RGBA, GL_FLOAT, data);
在我创建并填充纹理后测试它是否正常工作我检查内容如下:
//Bind the texture
glBindTexture(GL_TEXTURE_2D, texID);
//Get the data from the texture
float texData[size];
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, texData);
{
for(int i = 0; i < size; i++)
{
printf("Value at %d: %f\n", i, texData[i]);
}
}
所以这给出了0的加载,正如我所期望的那样,然后在我调用glTexImage2D之前的另一个测试我修改了数据数组中的一个值:
data[0] = 1.0f;
正如预期的那样,这将在要打印的第一个数字中增加1.0。 0到1之间的任何数字都按预期打印出来但是大于1或小于0的任何数字都会打印到该范围内?
这听起来可能是因为纹理存储了颜色值,因此会剪切到RGBA值的范围。是这种情况还是我做错了什么?
如果是这种情况有没有办法禁用它?我想在纹理中存储任意数据而不是颜色值它只是我希望提高性能,因为纹理/纹理查找结构在GPU中高度优化
答案 0 :(得分:8)
默认情况下,OpenGL是否将纹理值剪辑到0-1范围?
有时 - 取决于您访问纹理的方式和纹理内部格式。
如果有,有办法禁用它吗?
不是,但您可以更改内部格式以获得所需内容。
GL Spec 4.6,第2.3.5节定点数据转换:
当通用顶点属性和像素颜色或深度组件是 它们代表整数,通常(但并不总是)被考虑 要正常化。规范化的整数值在特殊处理时进行处理 被转换为浮点值和从浮点值转换,通常是 称为归一化定点。这些值总是如此 签名或未签名。
...
从浮点值f到相应的转换 无符号标准化定点值c由第一个钳位定义 f到范围[0,1] ,然后
以下调用是欺骗性的,因为纹理格式给出GL_FLOAT
(只是说你给它的数据是32位浮点)。内部格式为GL_RGBA
。我相信大多数实现最终都使用GL_RGBA8来存储它,即每个通道8位,如unsigned char r, g, b, a
(虽然这不是规范要求)。根据GL规范的上一部分,输入数据值将被钳制,然后转换为固定点。 0.0f及以下变为0且1.0f及以上变为255.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, GL_RGBA, GL_FLOAT, data);
当您在着色器中使用此类纹理进行读取和写入时,也会发生同样的情况。整数值透明地缩放到[0,1]范围。在您的情况下,使用glGetTexImage
+ GL_FLOAT
进行处理也会将整数值缩放回[0,1],但您传入的数据已被限制。如果您使用GL_UNSIGNED_BYTE
和unsigned char
/ GLubyte
数组阅读,则应该看到0到255.访问纹理时,使用相同的格式访问纹理可能更快内部格式。然后就不需要转换了。
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, texData);
简而言之,是的,0到1范围之外的任何东西都会被限制(例如,使用FBO写入典型的RGB / A纹理)。如果您不需要精度但仍希望数字大于1,则可以预先缩放值。
如果您需要更高的精确度,可以使用GL_RGBA32F
,如下所示。在这种情况下,不需要转换 - 您的输入与纹理存储相同,钳位不会发生。缺点是它将占用数据的4倍,这意味着访问时传输的数量是4倍。当然,这不仅仅是常规精度,因为你得到了浮点格式的指数表示。
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, GL_RGBA, GL_FLOAT, data);