Dom*_*yre 3 c++ opengl textures
简单的问题:
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);
Run Code Online (Sandbox Code Playgroud)
为了测试这在我创建和填充纹理后正常工作,我检查内容如下:
//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]);
}
}
Run Code Online (Sandbox Code Playgroud)
所以这给出了0的负载,正如我所期望的那样,然后在调用glTexImage2D之前作为另一个测试我修改了数据数组中的一个值:
data[0] = 1.0f;
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,在第一个要打印的数字中增加了1.0.0到1之间的任何数字都按预期打印出来,但是大于1或小于0的任何数字都会截断到该范围?
这听起来可能是因为纹理存储颜色值,因此剪切到RGBA值的范围.是这种情况还是我做错了什么?
如果是这种情况有没有办法禁用它?我想在纹理中存储任意数据而不是颜色值它只是我希望提高性能,因为纹理/纹理查找结构在GPU中高度优化
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);
Run Code Online (Sandbox Code Playgroud)
当您在着色器中使用此类纹理进行读取和写入时,也会发生相同的情况.整数值透明地缩放到[0,1]范围.在您的情况下,使用glGetTexImage+ GL_FLOAT也可以将整数值缩放回[0,1],但传入的数据已经被钳制.如果您使用GL_UNSIGNED_BYTE和unsigned char/ GLubytearray 读取,则应该看到0到255.访问纹理时,使用与内部格式相同的格式访问它可能更快.然后就不需要转换了.
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, texData);
Run Code Online (Sandbox Code Playgroud)
简而言之,是的,0到1范围之外的任何东西都会被钳制(例如,使用FBO写入典型的RGB/A纹理).如果您不需要精度但仍希望数字大于1,则可以预先缩放值.
如果您需要更高的精度,可以使用GL_RGBA32F,如下所示.在这种情况下,不需要转换 - 您的输入与纹理存储相同,并且不会发生夹紧.缺点是它将占用数据的4倍,这意味着访问时传输的数量是4倍.当然,这不仅仅是更常规的精度,因为您获得了浮点格式的指数表示.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, GL_RGBA, GL_FLOAT, data);
Run Code Online (Sandbox Code Playgroud)