PDA

View Full Version : Volume rendering, alpha blending problem



ananananda
08-12-2014, 09:09 AM
First of all, I'm newbie OpenGL developer. I found tutorial about Volume Rendering (google: getting started with volume rendering) and tried to implement my own renderer. I got to the point when I can draw all slices at once with alpha testing, which gives me more or less such result as in tutorial. Now, I want to move step forward and apply alpha blending, but after that there is no change (and even if there is, it doesn't look such nice as in tutorial). Here is my rendering code:


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);

for (int i = 0; i < z; ++i)
{
glBindTexture(GL_TEXTURE_2D, texturesObjects[i]);

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0, -1.0, 2 * i / z - 1);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0, -1.0, 2 * i / z - 1);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0, 1.0, 2 * i / z - 1);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0, 1.0, 2 * i / z - 1);

glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}

glutSwapBuffers();

where z is number of slices. Texture generation code looks like that:

GLuint* loadXZslices(const VR::DataAccessor& accessor, int& x, int& y, int& z)
{
x = accessor.getX();
y = accessor.getY();
z = accessor.getZ();

GLuint* texturesObjects = new GLuint[accessor.getZ()];

for (size_t i = 0; i < accessor.getZ(); ++i)
{
char* luminanceBuffer = accessor.getXYslice(i);
char* rgbaBuffer = new char[accessor.getX() * accessor.getY() * 4];

for (size_t j = 0; j < accessor.getX() * accessor.getY(); ++j)
{
rgbaBuffer[j * 4] = luminanceBuffer[j];
rgbaBuffer[j * 4 + 1] = luminanceBuffer[j];
rgbaBuffer[j * 4 + 2] = luminanceBuffer[j];
rgbaBuffer[j * 4 + 3] = 255;

if (luminanceBuffer[j] < 20)
{
rgbaBuffer[j * 4 + 3] = 0;
}
}

glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texturesObjects[i]);
glBindTexture(GL_TEXTURE_2D, texturesObjects[i]);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, accessor.getX(), accessor.getY(), 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)rgbaBuffer);

delete[] luminanceBuffer;
delete[] rgbaBuffer;
}

return texturesObjects;
}

DataAccessor is of course class that gives access to raw texture data.

Did I forget about setting something in my window or is there something wrong with my code? Help me, I'm desperate! :P

Dark Photon
08-12-2014, 05:28 PM
...
rgbaBuffer[j * 4] = luminanceBuffer[j];
rgbaBuffer[j * 4 + 1] = luminanceBuffer[j];
rgbaBuffer[j * 4 + 2] = luminanceBuffer[j];
rgbaBuffer[j * 4 + 3] = 255;

...
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, accessor.getX(), accessor.getY(), 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)rgbaBuffer);


Did I forget about setting something in my window or is there something wrong with my code?

Quick-scanning your code, it looks like your fragment alpha is going to be determined by the alpha of the texture, which is always set to 100% opaque (255).

Did I miss something?

ananananda
08-13-2014, 02:59 AM
Hmm, you are right. It seems to be a problem, but this idea comes from tutorial. It means that it is impossible to achive such effect with this code = there is a bug in tutorial. But some comment there claims, that with 3D texture it works, how is it possible?

Dark Photon
08-13-2014, 04:32 AM
Hmm, you are right. It seems to be a problem, but this idea comes from tutorial. It means that it is impossible to achive such effect with this code = there is a bug in tutorial. But some comment there claims, that with 3D texture it works, how is it possible?

Not having seen the full source, it's possible they are obtaining translucency from somewhere else at a higher level. But from what you quoted (including blend equation), we're not seeing that here.

Also, there are a number of different ways to do "volume rendering". Which one is this?

ananananda
08-13-2014, 09:00 AM
it is texture based volume rendering. I figured it out, there was a bug in tutorial. When I changed rgbaBuffer[j * 4 + 3] = 255; to rgbaBuffer[j * 4 + 3] = luminanceBuffer[j]; it started to looked like it should ;)

Dark Photon
08-13-2014, 07:22 PM
it is texture based volume rendering.

No, I mean which technique: maximum intensity projection, multiplanar reformatting, 3D shaded surface (marching cubes/tetrahedra), segmentation, etc. I think you're just talking about rendering all the slices with a constant translucency so you can see into the volume to some degree.