glTexImage2D() 参数和生成帧缓冲区

glTexImage2D() parameters and generating framebuffers

根据opengl的参考页,glTexImage2D的结构是这样的:

void glTexImage2D(  GLenum target,
    GLint level,
    GLint internalformat,
    GLsizei width,
    GLsizei height,
    GLint border,
    GLenum format,
    GLenum type,
    const GLvoid * data);

据我所知,最后 3 个参数是函数应如何解释 const GLvoid * data

给出的图像数据

同时,我正在研究帧缓冲区的主题。在这个 link https://learnopengl.com/Advanced-Lighting/HDR 的 'Floating point framebuffers' 部分,作者创建了一个像这样的帧缓冲区的颜色附件

glBindTexture(GL_TEXTURE_2D, colorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);

我的问题是,为什么他给GL_FLOAT作为GLenum type的参数?如果const GLvoid * data反正是NULL,有必要用GL_FLOAT吗?我一开始以为是和GL_RGBA16F有关的东西,但是16位是2个字节,浮点数是4个字节,所以我猜完全没有关系。

另外,在本教程之前,笔者曾经做过这样的彩色附件:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

既然如此,他为什么要用GL_UNSIGNED_BYTE作为GLenum type参数呢?

无论最后一个参数是否为 NULL(假设未使用 PBO),formattype 参数必须始终是 合法值 相对于 internalformat 参数。

话虽如此,pixel transfer format and type parameters exactly match the internalformat. But they do have to be compatible with it, in accord with the rules on pixel transfer compatibility 并不是绝对必要的。在您引用的特定情况下,formattype 值都与所使用的 internalforamt 中的任何一个兼容。所以理论上你可以这样做:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

话虽如此,您 不应该,原因有二:

  1. 您不应该编写您不想真正执行的代码。手动将无符号规范化字节转换为 16 位浮点数的实现会降低性能。即使因为指针为 NULL 而实际上不会执行该转换,您仍然不希望它实际发生。所以写出有意义的代码。

  2. 您必须记住像素传输兼容性的所有规则。因为如果你得到它们错误,如果你要求非法转换,你会得到一个 OpenGL 错误,从而破坏代码。如果你不习惯总是考虑你的 formattype 参数是什么,那么切换到整数纹理真的很容易并立即出现错误,因为你没有使用其中一个 _INTEGER 格式。然而,如果您一直在考虑代表您实际使用的 internalformat 的像素传输参数,您将永远不会遇到该错误。