<p>I notice that you've enabled blending and depth testing and are drawing with a non-opaque alpha channel. What's going to happen is that if you don't draw from back to front (relative to the camera), then any objects you draw that are farther away won't get drawn, so you won't see them through the nearer objects. If you turn off depth testing does it look correct?</p>

<p>To handle this correctly, you can also use a technique known as <a href="https://en.wikipedia.org/wiki/Depth_peeling" rel="nofollow">depth peeling</a>.</p>

<p><strong>EDIT</strong> I see how you calculate your view matrix, but I don't see any code calling it, so it's hard to say whether your camera is pointing in the right direction or not for this to work as expected.</p>

<p>One other thing I notice is that your projection matrix sets the near plane to 0.1, but you're translating your geometry in increments of -0.003. If your camera is at the origin (i.e. your view matrix has a translation of &lt;0,0,0>), then you won't see any layers until you get to the 34th layer. Also, with such small increments between the layers, you may end up with <a href="https://en.wikipedia.org/wiki/Z-fighting" rel="nofollow">Z-fighting</a>, as well.</p>

<p>You might try hard-coding your loop to display just a single layer and make sure each layer is drawn correctly when drawn alone. Once you've verified that, you can figure out why drawing more than 1 layer doesn't work as expected.</p>

CC BY-SA 3.0
2016-07-13T05:00:10.230Z
Thank you for your answer. I tried with disabling the depth test, it produces the same result. However, I would like to understand what do you mean by "...drawing with a non-opaque alpha channel." For opacity I am relying on alpha channel of the texture.
Sayan Pal
CC BY-SA 3.0
2016-07-13T05:07:22.190Z
In setting the color of the texture in `transformValueToColor()`, you set the alpha value to `255 * (1 - tValue)`, which means that as long as `tValue` is not 1.0, will be somewhere between 0 and 255. An alpha value that is not 255 will produce a non-opaque (or semi-transparent) pixel - one you can see through. My point was that if the front-most geometry is semi-transparent, you must draw it after the farther away geometry or the depth test will cause the farther away geometry not to ever draw.
user1118321
CC BY-SA 3.0
2016-07-13T05:25:50.370Z
I think I am drawing the furthest quad first and the nearest one last: `model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));`. I think that should have done?
Sayan Pal
CC BY-SA 3.0
2016-07-13T15:57:55.053Z
It depends on the other matrices, too, though. How are your view and projection matrices set?
user1118321
CC BY-SA 3.0
2016-07-13T16:31:58.570Z
I have added the details of `projection` and `view` matrix in the question above.
Sayan Pal
CC BY-SA 3.0
2016-07-14T04:35:59.063Z
I've added an edit with some additional information to my answer.
user1118321
CC BY-SA 3.0
2016-07-13T03:59:42.333Z
2016-07-14T04:35:28.220Z
2016-07-14T04:35:28.220Z
user1118321
<p>I have a 3 dimensional dataset where each value of the dataset is normalized to <code>[0, 1]</code>. I want to visualize this dataset by using texture, and blending.
However, it seems that I can't make it work.</p>

<p>Here is what I have done so far:</p>

<pre><code>int main(){
    ...
    //building an image for each rectangular slice of data
    vector&lt;Texture&gt; myTextures;
    for (GLint rowIndex = 0; rowIndex &lt; ROW_NUM; rowIndex++)
    {
        auto pathToImage = "images/row" + to_string(rowIndex) + FILE_EXT;
        FIBITMAP *img = FreeImage_Allocate(SLICE_DIMENSION, SLICE_NUM, 32); //32 = RGBA

        for (GLint depthIndex = 0; depthIndex &lt; DEPTH_NUM; depthIndex++)
        {
            for (GLint colIndex = 0; colIndex &lt; COL_NUM; colIndex++)
            {
                auto value = my3DData[depthIndex][rowIndex][colIndex];

                //transform tValue to a source color
                glm::vec4 source = transformValueToColor(value);

                //note that here I am also setting the opacity. 
                RGBQUAD linRgb = { source.b, source.g, source.r, source.a }; 
                FreeImage_SetPixelColor(img, colIndex, depthIndex, &amp;linRgb);
            }
        }

        //Saving images. Saved images shows transparency. 
        FreeImage_Save(FIF_PNG, img, pathToImage.c_str());
        myTextures.push_back(Texture(pathToImage.c_str(), GL_TEXTURE0));
    }
    //create VAO, VBO, EBO for a unit quad.

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    //game loop
    while (!glfwWindowShouldClose(window))
    {
        ...
        for (int i = 0; i &lt; myTextures.size(); i++)
        {
            GLint index = myTextures.size() - i - 1;
            myTextures[index].bind(); //does glActiveTexture(...), and glBindTexture(...);

            glm::mat4 model;

            //translate
            model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));

            //scale
            model = glm::scale(model, glm::vec3(1.2f));

            glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        }
    }
}
</code></pre>

<p><code>transformValueToColor</code>for transforming data value in <code>[0,1]</code> to color value:</p>

<pre><code>//All inputs &gt;=0.6 is transformed to highly transparent white color.
glm::vec4 transformValueToColor(GLclampf tValue)
{
    if (tValue &gt;= 0.6f) {
        return glm::vec4(255, 255, 255, 10);
    }
    else {
        auto val = round(255 * tValue);
        auto valOp = round(255 * (1 - tValue));
        return glm::vec4(val, val, val, valOp);
    }    
}
</code></pre>

<p>My vertex shader:</p>

<pre><code>#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoord = vec2(texCoord.s, 1-texCoord.t);
}
</code></pre>

<p>My fragment shader:</p>

<pre><code>#version 330 core

in vec2 TexCoord;

out vec4 color; 

uniform sampler2D sliceTexture;

void main()
{
    vec4 texColor = texture(sliceTexture, TexCoord); 
    color = texColor;
}
</code></pre>

<p>I think this is the code needed for the blending to work. The images are generated correctly, and also applied as texture on the quads correctly. However, the quads on the front appears as completely opaque, though the generated images (even the one appearing at front) shows transparent area.</p>

<p>I am not sure where I am going wrong. Requesting your suggestions. </p>

<p>Thank you.</p>

<p><strong>Edit</strong> </p>

<p>Details of camera class. <code>Camera::getViewMatrix()</code> provides <code>view</code> matrix.</p>

<pre><code>Camera::Camera(GLFWwindow* window, glm::vec3 position, glm::vec3 worldUpDirection, GLfloat yaw, GLfloat pitch)
    :mouseSensitivity(0.25f), fov(45.0f), cameraSpeed(1.0f)
{
    this-&gt;position = this-&gt;originalPosition = position;
    this-&gt;worldUpDirection = worldUpDirection;
    this-&gt;yaw = this-&gt;originalYaw = yaw;
    this-&gt;pitch = this-&gt;originalPitch = pitch;

    updateCameraVectors();
}

void Camera::updateCameraVectors()
{
    glm::mat4 yawPitchRotMat;

    yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(yaw), glm::vec3(0.0f, 1.0f, 0.0f));       //y-ais as yaw axis
    yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(pitch), glm::vec3(1.0f, 0.0f, 0.0f));     //x-axis as pitch axis

    frontDirection = glm::normalize(-glm::vec3(yawPitchRotMat[2].x, yawPitchRotMat[2].y, yawPitchRotMat[2].z));

    rightDirection = glm::normalize(glm::cross(frontDirection, worldUpDirection));
    upDirection = glm::normalize(glm::cross(rightDirection, frontDirection));
}

glm::mat4 Camera::getViewMatrix()
{
    return glm::lookAt(position, position + frontDirection, upDirection);
}
</code></pre>

<p>And the <code>projection</code> matrix is given by: <code>glm::perspective(glm::radians(camera.fov), Width / Height, 0.1f, 100.0f);</code></p>

<p><strong>Update:</strong> In short, blending was working all along. I followed the advice of user1118321, tested with only 2 textures, and found that it is working. Then I understood that a good part of images appearing on front was opaque. After that it was easy. I just manipulated with the transformation function <code>transformValueToColor</code>, added additional threshold to make additional part of the image opaque. And that was it.</p>

<opengl><c++><blending>
Can't make blending work
Sayan Pal
# Can't make blending work

(Asked by: username_0 on 2016-07-12)

I have a 3 dimensional dataset where each value of the dataset is normalized to `[0, 1]`. I want to visualize this dataset by using texture, and blending.
However, it seems that I can't make it work.

Here is what I have done so far:

```
int main(){
    ...
    //building an image for each rectangular slice of data
    vector<Texture> myTextures;
    for (GLint rowIndex = 0; rowIndex < ROW_NUM; rowIndex++)
    {
        auto pathToImage = "images/row" + to_string(rowIndex) + FILE_EXT;
        FIBITMAP *img = FreeImage_Allocate(SLICE_DIMENSION, SLICE_NUM, 32); //32 = RGBA

        for (GLint depthIndex = 0; depthIndex < DEPTH_NUM; depthIndex++)
        {
            for (GLint colIndex = 0; colIndex < COL_NUM; colIndex++)
            {
                auto value = my3DData[depthIndex][rowIndex][colIndex];

                //transform tValue to a source color
                glm::vec4 source = transformValueToColor(value);

                //note that here I am also setting the opacity. 
                RGBQUAD linRgb = { source.b, source.g, source.r, source.a }; 
                FreeImage_SetPixelColor(img, colIndex, depthIndex, &linRgb);
            }
        }

        //Saving images. Saved images shows transparency. 
        FreeImage_Save(FIF_PNG, img, pathToImage.c_str());
        myTextures.push_back(Texture(pathToImage.c_str(), GL_TEXTURE0));
    }
    //create VAO, VBO, EBO for a unit quad.

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    //game loop
    while (!glfwWindowShouldClose(window))
    {
        ...
        for (int i = 0; i < myTextures.size(); i++)
        {
            GLint index = myTextures.size() - i - 1;
            myTextures[index].bind(); //does glActiveTexture(...), and glBindTexture(...);

            glm::mat4 model;

            //translate
            model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));

            //scale
            model = glm::scale(model, glm::vec3(1.2f));

            glUniformMatrix4fv(glGetUniformLocation(ourShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        }
    }
}

```

`transformValueToColor`for transforming data value in `[0,1]` to color value:

```
//All inputs >=0.6 is transformed to highly transparent white color.
glm::vec4 transformValueToColor(GLclampf tValue)
{
    if (tValue >= 0.6f) {
        return glm::vec4(255, 255, 255, 10);
    }
    else {
        auto val = round(255 * tValue);
        auto valOp = round(255 * (1 - tValue));
        return glm::vec4(val, val, val, valOp);
    }    
}

```

My vertex shader:

```
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoord = vec2(texCoord.s, 1-texCoord.t);
}

```

My fragment shader:

```
#version 330 core

in vec2 TexCoord;

out vec4 color; 

uniform sampler2D sliceTexture;

void main()
{
    vec4 texColor = texture(sliceTexture, TexCoord); 
    color = texColor;
}

```

I think this is the code needed for the blending to work. The images are generated correctly, and also applied as texture on the quads correctly. However, the quads on the front appears as completely opaque, though the generated images (even the one appearing at front) shows transparent area.

I am not sure where I am going wrong. Requesting your suggestions.

Thank you.

**Edit**

Details of camera class. `Camera::getViewMatrix()` provides `view` matrix.

```
Camera::Camera(GLFWwindow* window, glm::vec3 position, glm::vec3 worldUpDirection, GLfloat yaw, GLfloat pitch)
    :mouseSensitivity(0.25f), fov(45.0f), cameraSpeed(1.0f)
{
    this->position = this->originalPosition = position;
    this->worldUpDirection = worldUpDirection;
    this->yaw = this->originalYaw = yaw;
    this->pitch = this->originalPitch = pitch;

    updateCameraVectors();
}

void Camera::updateCameraVectors()
{
    glm::mat4 yawPitchRotMat;

    yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(yaw), glm::vec3(0.0f, 1.0f, 0.0f));       //y-ais as yaw axis
    yawPitchRotMat = glm::rotate(yawPitchRotMat, glm::radians(pitch), glm::vec3(1.0f, 0.0f, 0.0f));     //x-axis as pitch axis

    frontDirection = glm::normalize(-glm::vec3(yawPitchRotMat[2].x, yawPitchRotMat[2].y, yawPitchRotMat[2].z));

    rightDirection = glm::normalize(glm::cross(frontDirection, worldUpDirection));
    upDirection = glm::normalize(glm::cross(rightDirection, frontDirection));
}

glm::mat4 Camera::getViewMatrix()
{
    return glm::lookAt(position, position + frontDirection, upDirection);
}

```

And the `projection` matrix is given by: `glm::perspective(glm::radians(camera.fov), Width / Height, 0.1f, 100.0f);`

**Update:** In short, blending was working all along. I followed the advice of username_1, tested with only 2 textures, and found that it is working. Then I understood that a good part of images appearing on front was opaque. After that it was easy. I just manipulated with the transformation function `transformValueToColor`, added additional threshold to make additional part of the image opaque. And that was it.

**Tags:** opengl, c++, blending


---

## 1 answers

### Answer by username_1 on 2016-07-13. Score: 2 | Accepted answer

I notice that you've enabled blending and depth testing and are drawing with a non-opaque alpha channel. What's going to happen is that if you don't draw from back to front (relative to the camera), then any objects you draw that are farther away won't get drawn, so you won't see them through the nearer objects. If you turn off depth testing does it look correct?

To handle this correctly, you can also use a technique known as [depth peeling](https://en.wikipedia.org/wiki/Depth_peeling).

**EDIT** I see how you calculate your view matrix, but I don't see any code calling it, so it's hard to say whether your camera is pointing in the right direction or not for this to work as expected.

One other thing I notice is that your projection matrix sets the near plane to 0.1, but you're translating your geometry in increments of -0.003. If your camera is at the origin (i.e. your view matrix has a translation of <0,0,0>), then you won't see any layers until you get to the 34th layer. Also, with such small increments between the layers, you may end up with [Z-fighting](https://en.wikipedia.org/wiki/Z-fighting), as well.

You might try hard-coding your loop to display just a single layer and make sure each layer is drawn correctly when drawn alone. Once you've verified that, you can figure out why drawing more than 1 layer doesn't work as expected.

> **Comments:**
> **username_0**: Thank you for your answer. I tried with disabling the depth test, it produces the same result. However, I would like to understand what do you mean by "...drawing with a non-opaque alpha channel." For opacity I am relying on alpha channel of the texture.  
> **username_1**: In setting the color of the texture in `transformValueToColor()`, you set the alpha value to `255 * (1 - tValue)`, which means that as long as `tValue` is not 1.0, will be somewhere between 0 and 255. An alpha value that is not 255 will produce a non-opaque (or semi-transparent) pixel - one you can see through. My point was that if the front-most geometry is semi-transparent, you must draw it after the farther away geometry or the depth test will cause the farther away geometry not to ever draw.  
> **username_0**: I think I am drawing the furthest quad first and the nearest one last: `model = glm::translate(model, glm::vec3(0.0f, 0.0f, -index*0.003f));`. I think that should have done?  
> **username_1**: It depends on the other matrices, too, though. How are your view and projection matrices set?  
> **username_0**: I have added the details of `projection` and `view` matrix in the question above.  
> **username_1**: I've added an edit with some additional information to my answer.  

---

