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),format
和 type
参数必须始终是 合法值 相对于 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 并不是绝对必要的。在您引用的特定情况下,format
和 type
值都与所使用的 internalforamt
中的任何一个兼容。所以理论上你可以这样做:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
话虽如此,您 不应该,原因有二:
您不应该编写您不想真正执行的代码。手动将无符号规范化字节转换为 16 位浮点数的实现会降低性能。即使因为指针为 NULL 而实际上不会执行该转换,您仍然不希望它实际发生。所以写出有意义的代码。
您必须记住像素传输兼容性的所有规则。因为如果你得到它们错误,如果你要求非法转换,你会得到一个 OpenGL 错误,从而破坏代码。如果你不习惯总是考虑你的 format
和 type
参数是什么,那么切换到整数纹理真的很容易并立即出现错误,因为你没有使用其中一个 _INTEGER
格式。然而,如果您一直在考虑代表您实际使用的 internalformat
的像素传输参数,您将永远不会遇到该错误。
根据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),format
和 type
参数必须始终是 合法值 相对于 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 并不是绝对必要的。在您引用的特定情况下,format
和 type
值都与所使用的 internalforamt
中的任何一个兼容。所以理论上你可以这样做:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
话虽如此,您 不应该,原因有二:
您不应该编写您不想真正执行的代码。手动将无符号规范化字节转换为 16 位浮点数的实现会降低性能。即使因为指针为 NULL 而实际上不会执行该转换,您仍然不希望它实际发生。所以写出有意义的代码。
您必须记住像素传输兼容性的所有规则。因为如果你得到它们错误,如果你要求非法转换,你会得到一个 OpenGL 错误,从而破坏代码。如果你不习惯总是考虑你的
format
和type
参数是什么,那么切换到整数纹理真的很容易并立即出现错误,因为你没有使用其中一个_INTEGER
格式。然而,如果您一直在考虑代表您实际使用的internalformat
的像素传输参数,您将永远不会遇到该错误。