I know that there is another question with exactly the same title here however the solution provided over there does not work for my case.
I am trying to access pixel value from my compute shader. But the imageLoad
function always returns 0.
Here is how I load the image:
void setTexture(GLuint texture_input, const char *fname)
{
// set texture related
int width, height, nbChannels;
unsigned char *data = stbi_load(fname, &width, &height, &nbChannels, 0);
if (data)
{
GLenum format;
if (nbChannels == 1)
{
format = GL_RED;
}
else if (nbChannels == 3)
{
format = GL_RGB;
}
else if (nbChannels == 4)
{
format = GL_RGBA;
}
glActiveTexture(GL_TEXTURE0 + 1);
gerr();
glBindTexture(GL_TEXTURE_2D, texture_input);
gerr();
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);
gerr();
glTexImage2D(GL_TEXTURE_2D, // target
0, // level, 0 means base level
format, // internal format of image specifies color components
width, height, // what it says
0, // border, should be 0 at all times
format, GL_UNSIGNED_BYTE, // data type of pixel data
data);
gerr();
glBindImageTexture(1, // unit
texture_input, // texture id
0, // level
GL_FALSE, // is layered
0, // layer no
GL_READ_ONLY, // access type
GL_RGBA32F);
// end texture handling
gerr();
glBindTexture(GL_TEXTURE_2D, 0); // unbind
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
}
And here is the relevant declaration and calling code in the shader:
layout(rgba32f, location = 1, binding = 1) readonly uniform image2D in_image;
struct ImageTexture
{
int width;
int height;
};
vec3 imageValue(ImageTexture im, float u, float v, in vec3 p)
{
u = clamp(u, 0.0, 1.0);
v = 1 - clamp(v, 0.0, 1.0);
int i = int(u * im.width);
int j = int(v * im.height);
if (i >= im.width)
i = im.width - 1;
if (j >= im.height)
j = im.height - 1;
vec3 color = imageLoad(in_image, ivec2(i, j)).xyz;
if (color == vec3(0))
color = vec3(0, u, v); // debug
return color;
}
I am seeing a green gradient instead of the contents of the image, which means my debugging code is in effect.
Either the internal format of the texture does not match the format which is specified at glBindImageTexture
or the format argument is not a valid enumerator constant, when the two-dimensional texture image is specified, because format
is used twice, for the internal format and the format (see glTexImage2D
):
glTexImage2D(GL_TEXTURE_2D, // target 0, // level, 0 means base level format, // internal format of image specifies color // components width, height, // what it says 0, // border, should be 0 at all times format, GL_UNSIGNED_BYTE, // data type of pixel data data);
The format argument to glBindImageTexture
is GL_RGBA32F
:
glBindImageTexture(1, // unit texture_input, // texture id 0, // level GL_FALSE, // is layered 0, // layer no GL_READ_ONLY, // access type GL_RGBA32F);
Hence, internal format has to be GL_RGBA32F
. A possible fomrat is GL_RGBA
:
glTexImage2D(GL_TEXTURE_2D, // target
0, // level, 0 means base level
GL_RGBA32F, // internal format of image specifies color
// components
width, height, // what it says
0, // border, should be 0 at all times
GL_RGBA, GL_UNSIGNED_BYTE, // data type of pixel data
data);