我有一个问题,一个非常简单的计算着色器,只是复制一个纹理使用imageStore。
# define KS 16 // kernel size
layout (local_size_x = KS, local_size_y = KS) in;
layout(location = 0) uniform sampler2D u_inputTex;
layout(location = 1) uniform writeonly image2D u_outImg;
void main()
{
const ivec2 gid = ivec2(gl_WorkGroupID.xy);
const ivec2 tid = ivec2(gl_LocalInvocationID.xy);
const ivec2 pixelPos = ivec2(KS) * gid + tid;
imageStore(u_outImg, pixelPos,
uvec4(255.0 * texelFetch(u_inputTex, pixelPos, 0).rgb, 255u));
}
在C++方面,我有以下代码:
int w, h;
u32 inTex = -1;
{
int nc;
auto img = stbi_load("imgs/Windmill_NOAA.png", &w, &h, &nc, 3);
if (img) {
glGenTextures(1, &inTex);
glBindTexture(GL_TEXTURE_2D, inTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
stbi_image_free(img);
}
else
printf("Error loading img\n");
}
u32 outTex;
{
glGenTextures(1, &outTex);
glBindTexture(GL_TEXTURE_2D, outTex);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, w, h);
}
u32 compProg = easyCreateComputeShaderProg("compute", shader_srcs::computeSrc);
glUseProgram(compProg);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inTex);
glBindImageTexture(0, outTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI);
glUniform1i(0, 0);
glUniform1i(1, 0);
glDispatchCompute((w+15)/16, (h+15)/16, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); // make sure the output image has been written
u8* img = new u8[w * h * 4];
glBindTexture(GL_TEXTURE_2D, outTex);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, img);
stbi_write_png("imgs/out.png", w, h, 1, img, w*4);
delete[] img;
输入图像如下所示:
但这是我在输出图像中得到的:
我进一步简化了着色器:而不是从输入纹理中阅读,我只是写一个固定值:
imageStore(u_outImg, pixelPos,
//uvec4(255.0 * texelFetch(u_inputTex, pixelPos, 0).rgb, 255u));
uvec4(1u));
我已经注意到:
- 如果我写0它就全黑了
- 如果我写255它就全是白色的
- 但是如果我在中间写一些东西(比如100),它就不是灰色的,而是白色的
我也试过这样做,但也没有成功:
imageStore(u_outImg, pixelPos,
vec4(texelFetch(u_inputTex, pixelPos, 0).rgb, 255u));
我做错了什么?我的最终目标是做一个前列腺处理过滤器,但我不能让它工作,所以我试图使它尽可能简单,但它不工作。
最小示例存储库:https://github.com/tuket/stackoverflow_image_store_problem
1条答案
按热度按时间8iwquhpp1#
如果要使用 unnormalized unsigned integer图像,则必须在sahder中将其声明为
uimage2D
。image2D
仅适用于浮点数或正规化整数(范围[0,1]
)。这是一个错误的内存障碍。这个障碍是关于如何访问由着色器修改的资源,在障碍之后,所以正确的是:
GL_TEXTURE_UPDATE_BARRIER_BIT
这在reference page中被解释为(强调我):
在屏障之后通过
glTex(Sub)Image*
、glCopyTex(Sub)Image*
、glCompressedTex(Sub)Image*
**写入纹理以及通过glGetTexImage
读取纹理将反映屏障之前着色器写入的数据。**此外,在屏障之后发出的这些命令中的纹理写入将不会执行,直到屏障之前启动的所有着色器写入完成。