无法进行混合工作

时间:2016-07-12 21:15:27

标签: c++ opengl blending freeimage

我有一个三维数据集,其中数据集的每个值都规范化为[0, 1]。我想通过使用纹理和混合来可视化此数据集。 但是,似乎我无法使其发挥作用。

这是我到目前为止所做的:

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用于将[0,1]中的数据值转换为颜色值:

//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);
    }    
}

我的顶点着色器:

#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);
}

我的片段着色器:

#version 330 core

in vec2 TexCoord;

out vec4 color; 

uniform sampler2D sliceTexture;

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

我认为这是混合工作所需的代码。图像生成正确,并且还可以正确地作为纹理应用于四边形。然而,前面的四边形显示为完全不透明,尽管生成的图像(甚至是前面出现的图像)显示透明区域。

我不确定我哪里出错了。请求您的建议。

谢谢。

修改: Texture类的详细信息(仅与加载RGBA图片相关的部分以及从中创建RGBA纹理):

int width, height, channelCount;
unsigned char* image = SOIL_load_image(pathToImage, &width, &height, &channelCount, SOIL_LOAD_RGBA);
...    
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);

编辑2:添加了相机类的详细信息。 Camera::getViewMatrix()提供view矩阵。

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);
}

1 个答案:

答案 0 :(得分:2)

myTextures.push_back(Texture(pathToImage.c_str(), GL_TEXTURE0));

这并不包含有关您的Texture课程的任何信息以及它如何解析图片文件。即使文件本身显示透明度,当您加载图像时,纹理加载代码可能会丢弃Alpha通道。

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

这使得它看起来好像是从前到后渲染。如果要渲染透明对象,则需要使用算法来实现与顺序无关的透明度,或者需要从后向前渲染。

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

您可能还需要/需要使用glBlendFuncSeparate,以便以不同方式完成Alpha通道的混合。我不确定这个。

您可能还需要考虑简单地填充单个GL_TEXTURE_3D对象并将其渲染为多维数据集,在片段着色器中进行所有混合,而不是为每个层渲染一系列四边形。