3

I have a 2D floating point array with values mapped within the range 0.0f to 1.0f. I load it into OpenGL using a single channel i.e

glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_FLOAT, data);

which works fine. However, I'm trying to add two more channels in order to eventually convert it into RGB colours, as below:

// Get the current grid
Array2D<real_t> currentGrid = m_Continuum->getCurrentGrid();
float R, G, B;

std::vector<GLfloat> image;
image.resize(currentGrid.size()*3, 0.0f);

for (size_t i = 0; i != currentGrid.sizeWd(); ++i)
{
    for (size_t j = 0; j != currentGrid.sizeHt(); ++j)
    {
        // I have to switch i and j in currentGrid due to the way the Array2D type is layed out
        image[( i * currentGrid.sizeWd() + j) + 0] = currentGrid(j, i);
        image[( i * currentGrid.sizeWd() + j) + 1] = currentGrid(j, i);
        image[( i * currentGrid.sizeWd() + j) + 2] = currentGrid(j, i);
    }
}

Now, when I update and use glTexImage2D:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT,data);

the image is malformed, as shown in the comparison below: Single Channel Image

RGB Image

My texture loading function is below. I believe I've used the correct pixelstore and texture mapping parameters.

bool Texture::load(const size_t width, const size_t height, const float *data)
{
    glPixelStoref(GL_UNPACK_ALIGNMENT, 1);

    // Allocate a texture name
    //glGenTextures(1, &m_TextureObj); called in another function

    // select current texture
    glBindTexture(GL_TEXTURE_2D, m_TextureObj);

    // select replace to ensure texture retains each texel's colour
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // if texture wraps over at the edges
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT,data);

    glGenerateMipmap(GL_TEXTURE_2D);

    m_Loaded = true;
    return true;
}

Any ideas of what I could try? Here's what I've looked up:

  1. Here's a similar question on the topic, which is what I've tried following, but to no avail.
  2. My hunch is there may be a problem with the layout of the data I'm passing, such as this question. I've tried that, but it basically squashes the single channel image to the left third of the texture image area.

EDIT:

Updated resulting image, based on @Podgorskiy answer, by changing

( i * currentGrid.sizeWd() + j) + c

to

( 3 * i * currentGrid.sizeWd() + j) + c

where c is the channel 0,1,2. Resulting image below: RGB Image updated result

Community
  • 1
  • 1
ccoder83
  • 504
  • 6
  • 15

1 Answers1

3

You access elements by the index that you calculate as:

( i * currentGrid.sizeWd() + j) + c

Where c is a channel, and it takes the values of: 0, 1, 2.

However, this expression likely to be wrong. From this expression follows that two neighboring texels have offset of one float, but should have offset of three floats. Try this instead:

3 * ( i * currentGrid.sizeWd() + j) + c
Pidhorskyi
  • 1,562
  • 12
  • 19
  • I've tried that as well, and as mentioned in the second point at the end, it squashes the original image to the left third of the texture image area, albeit a slightly better result than the malformed one above, but still incorrect. – ccoder83 May 17 '15 at 19:17
  • The answer, that you refer to in the second point at the end of your question, likely to have the same misprint. Could you please provide the result image when you apply the multiplier of 3? – Pidhorskyi May 17 '15 at 19:30
  • Oops, I linked to the same question as point 1, I've updated it, and also updated the question to include the result image after applying the multiplier of 3. – ccoder83 May 17 '15 at 19:58
  • I found the problem, oh gosh, such a silly mistake, I used the bracket incorrectly `(3 * i * currentGrid.sizeWd() + j) + c` instead of `3 * ( i * currentGrid.sizeWd() + j) + c`. Accepting your answer. Thanks @Podgorskiy – ccoder83 May 17 '15 at 20:06