更改内部格式导致纹理参数不正确
Changing internal format causes texture to have incorrect parameters
我设置了要在其上绘制场景的帧缓冲区纹理,如下所示:
glGenFramebuffers(1, &renderFBO);
glGenTextures(1, &renderTexture);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, W_WIDTH, W_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
cout << "width: " << width << " height: " << height << endl;
glBindFramebuffer(GL_FRAMEBUFFER, renderFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
通过验证 width
和 height
,它们确实具有正确的尺寸,1024, 768
。
现在我正在尝试设置第二个纹理,用作计数器,这意味着我正在尝试通过增加纹理中适当的纹素来计算每个颜色值的出现次数。由于我正在尝试计算颜色,因此我使用了大小为 256 x 3
的 2D 纹理。在每个单元格中,我想要一个无符号整数,显示特定颜色值在该点之前出现的次数。例如,如果遇到颜色 (255,5,3)
,我会增加 tex[255][0], tex[5][0], tex[3][0]
中的数字
num_bins = 256;
GLuint* hist_data = new GLuint[num_bins * color_components]();
glGenTextures(1, &tex_output);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_output);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED, GL_UNSIGNED_INT, hist_data);
glBindImageTexture(0, tex_output, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
cout << "width: " << width << " height: " << height << endl;
我使用了opengl规范中显示的大小和基本内部格式对应关系。但是,当此代码执行时,输出值为 width=0, height=0
。输入数据似乎不是问题,因为我尝试提供 NULL
作为最后一个参数,但它仍然无效。我在这里错过了什么?
编辑:
纹理中值的增加应该发生在以下计算着色器中:
#version 450
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img_input;
layout(r32ui, binding = 1) uniform uimage2D img_output;
void main() {
// grabbing pixel value from input image
vec4 pixel_color = imageLoad(img_input, ivec2(gl_GlobalInvocationID.xy));
vec3 rgb = round(pixel_color.rgb * 255);
ivec2 r = ivec2(rgb.r, 0);
ivec2 g = ivec2(rgb.g, 1);
ivec2 b = ivec2(rgb.b, 2);
uint inc = 1;
imageAtomicAdd(img_output, r, inc);
imageAtomicAdd(img_output, g, inc);
imageAtomicAdd(img_output, b, inc);
}
您收到 GL_INVALID_OPERATION
错误,因为纹理格式参数与纹理的内部格式不一致。对于无符号整数格式,您必须使用 GL_RED_INTEGER
而不是 GL_RED
(参见 glTexImage2D
):
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED, GL_UNSIGNED_INT, hist_data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, hist_data);
我推荐使用Debug Output,它可以节省很多时间并且可以让您快速找到此类错误。
我设置了要在其上绘制场景的帧缓冲区纹理,如下所示:
glGenFramebuffers(1, &renderFBO);
glGenTextures(1, &renderTexture);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, W_WIDTH, W_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
cout << "width: " << width << " height: " << height << endl;
glBindFramebuffer(GL_FRAMEBUFFER, renderFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
通过验证 width
和 height
,它们确实具有正确的尺寸,1024, 768
。
现在我正在尝试设置第二个纹理,用作计数器,这意味着我正在尝试通过增加纹理中适当的纹素来计算每个颜色值的出现次数。由于我正在尝试计算颜色,因此我使用了大小为 256 x 3
的 2D 纹理。在每个单元格中,我想要一个无符号整数,显示特定颜色值在该点之前出现的次数。例如,如果遇到颜色 (255,5,3)
,我会增加 tex[255][0], tex[5][0], tex[3][0]
num_bins = 256;
GLuint* hist_data = new GLuint[num_bins * color_components]();
glGenTextures(1, &tex_output);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_output);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED, GL_UNSIGNED_INT, hist_data);
glBindImageTexture(0, tex_output, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
int width, height;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
cout << "width: " << width << " height: " << height << endl;
我使用了opengl规范中显示的大小和基本内部格式对应关系。但是,当此代码执行时,输出值为 width=0, height=0
。输入数据似乎不是问题,因为我尝试提供 NULL
作为最后一个参数,但它仍然无效。我在这里错过了什么?
编辑:
纹理中值的增加应该发生在以下计算着色器中:
#version 450
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img_input;
layout(r32ui, binding = 1) uniform uimage2D img_output;
void main() {
// grabbing pixel value from input image
vec4 pixel_color = imageLoad(img_input, ivec2(gl_GlobalInvocationID.xy));
vec3 rgb = round(pixel_color.rgb * 255);
ivec2 r = ivec2(rgb.r, 0);
ivec2 g = ivec2(rgb.g, 1);
ivec2 b = ivec2(rgb.b, 2);
uint inc = 1;
imageAtomicAdd(img_output, r, inc);
imageAtomicAdd(img_output, g, inc);
imageAtomicAdd(img_output, b, inc);
}
您收到 GL_INVALID_OPERATION
错误,因为纹理格式参数与纹理的内部格式不一致。对于无符号整数格式,您必须使用 GL_RED_INTEGER
而不是 GL_RED
(参见 glTexImage2D
):
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED, GL_UNSIGNED_INT, hist_data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, hist_data);
我推荐使用Debug Output,它可以节省很多时间并且可以让您快速找到此类错误。