2016-07-12 17 views
0

Ich habe ein 3-dimensionales Dataset, in dem jeder Wert des Datasets auf [0, 1] normiert ist. Ich möchte diesen Datensatz mithilfe von Textur und Überblendung visualisieren. Es scheint jedoch, dass ich es nicht funktionieren lassen kann. HierMischen kann nicht durchgeführt werden

ist, was ich bisher getan haben:

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 für die Transformation von Datenwert in [0,1] zu Farbwert:

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

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

Meine Fragment-Shader:

#version 330 core 

in vec2 TexCoord; 

out vec4 color; 

uniform sampler2D sliceTexture; 

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

Ich denke, das ist der Code, der für das Mischen benötigt wird. Die Bilder werden korrekt generiert und auch als Textur auf den Quads korrekt angewendet. Die Quadrate auf der Vorderseite erscheinen jedoch als vollständig undurchsichtig, obwohl die erzeugten Bilder (sogar das vorne erscheinende) transparente Bereiche zeigen.

Ich bin mir nicht sicher, wo ich falsch liege. Ihre Vorschläge anfordern.

Vielen Dank.

Edit: Details Texture Klasse (nur die relevanten Teile Laden RGBA Bild und die Schaffung von RGBA Textur aus, dass):

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

Edit2: Added Details der Kameraklasse. Camera::getViewMatrix() bietet 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); 
} 

Antwort

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

Dieses enthält keine Informationen über Ihre Texture Klasse und wie es die Bilddateien Parsen. Selbst wenn die Dateien selbst transparent sind, ist es möglich, dass der Code zum Laden der Textur den Alphakanal verwirft, wenn Sie das Bild laden.

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

Dadurch sieht es so aus, als würden Sie von vorne nach hinten rendern. Wenn Sie transparente Objekte übereinander darstellen möchten, müssen Sie einen Algorithmus für die farbunabhängige Transparenz verwenden, oder Sie müssen von hinten nach vorne rendern.

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

Sie können auch wollen/müssen glBlendFuncSeparate so verwenden, dass das Mischen des Alphakanals anders gemacht wird. Ich bin mir aber nicht sicher.

Sie können auch erwägen, einfach ein einzelnes GL_TEXTURE_3D-Objekt zu füllen und es als Cube zu rendern, indem Sie das Mischen im Fragment-Shader durchführen, anstatt eine Reihe von Quads für jede Ebene zu rendern.

+0

Vielen Dank für Ihre Antwort. Ich habe die relevanten Details der fraglichen 'Texture'-Klasse hinzugefügt. Auch in Bezug auf die Reihenfolge denke ich, dass ich den weitesten Quad zuerst und das nächste Quad zuletzt ziehe, da ich denke, dass der "z" -Wert abnimmt, je mehr du in die vordere Richtung gehst. Was schlagen Sie vor? –

+1

Die meisten OpenGL-Setups, die ich gesehen habe, haben einen abnehmenden Z-Wert, wenn Sie vorwärts gehen. Wie es für Sie funktioniert, hängt davon ab, wie Sie Ihre View-Matrix erstellt haben, aber das zeigen Sie auch nicht. – Jherico

+0

Vielen Dank für Ihren Kommentar. Die Klassendetails für die Ansichtsmatrix wurden hinzugefügt. –