我有一个三维数据集,其中数据集的每个值都规范化为[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);
}
答案 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对象并将其渲染为多维数据集,在片段着色器中进行所有混合,而不是为每个层渲染一系列四边形。