# GPU-based volume raycasting

• 10-15-2012, 01:37 AM
qlizhi
GPU-based volume raycasting
hello, i have download an source code of GPU-based volume raycasting,which is based on Qt. And i upload it to my google code as below:
I have read several times of the source code, but in some place i still cannot understand.
Code :

vec2 intersectBox(vec4 texel_zero, vec4 texel_dir_norm)
{
float t1,t2;
t1=(0.0-texel_zero.x)/texel_dir_norm.x;
t2=(1.0-texel_zero.x)/texel_dir_norm.x;
float tminX=min(t1,t2);
float tmaxX=max(t1,t2);
t1=(0.0-texel_zero.y)/texel_dir_norm.y;
t2=(1.0-texel_zero.y)/texel_dir_norm.y;
float tminY=min(t1,t2);
float tmaxY=max(t1,t2);
t1=(0.0-texel_zero.z)/texel_dir_norm.z;
t2=(1.0-texel_zero.z)/texel_dir_norm.z;
float tminZ=min(t1,t2);
float tmaxZ=max(t1,t2);
float largest_tmin = max(max(tminX, tminY), max(tminX, tminZ));
float smallest_tmax = min(min(tmaxX, tmaxY), min(tmaxX, tmaxZ));
vec2 result=vec2(largest_tmin,smallest_tmax);
return result;
}

Can somebody tell me how this function get the near and far .
• 10-15-2012, 02:32 PM
carsten neumann
That looks like a (fairly standard) algorithm to intersect a ray with an axis aligned box (i.e. your favourite search engine should produce a better explanation than what follows ;) ). The basic idea is for each axis to determine the distances (t1, t2) along the ray where it enters/leaves the box. Since this is done for each axis separately you only care about where the ray crosses the planes that coincide with the box sides that are orthogonal to the axis you are processing. The ray is inside the box when it has entered it over all three planes and leaves the box as soon as it exits the first one again, that's why you want the largest of the tmin (enter distances), and the smallest of the tmax (leave distances).

FWIW, I'm pretty sure this can be vectorized for better efficiency.
• 10-15-2012, 08:18 PM
qlizhi
Thank you very much, but i still donot know what does "t1=(0.0-texel_zero.x)/texel_dir_norm.x" mean.
• 10-16-2012, 08:34 AM
carsten neumann
Ok, fair enough. I'm afraid I don't know how to describe this substantially different from what I already wrote. Perhaps someone else wants to give it a try.
• 10-19-2012, 01:51 AM
qlizhi
haha~~ i got it. thanks a lot!
• 10-19-2012, 02:09 AM
qlizhi
Code :

bool VolRenCore::Render()
{
glClearColor(m_BackgroundColor[0], m_BackgroundColor[1], m_BackgroundColor[2], 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CCW);
if (!m_Data || !m_Data->GetData()) return false;
if (m_DataModified || m_Data->GetVersion()!=m_DataVersion)
{
_updateData();
m_DataModified=false;
m_DataVersion=m_Data->GetVersion();
m_VolTextureNeedUpdate=true;
}
if (!m_glewInit)
{
glewInit();
_initA2OTexture();
m_glewInit=true;
}

{
}

if (m_NeedCalculateMatrix)
{
_calculateMatrix();
m_NeedCalculateMatrix=false;
}

if (!_calculateBounds()) return false;

glUseProgramObjectARB(m_GLSLProgram);

GLint var = glGetUniformLocationARB(m_GLSLProgram, "P2MMatrix");
glUniformMatrix4fvARB(var,1,0,m_PixelsToModelMatrix.ele);

var   = glGetUniformLocationARB(m_GLSLProgram, "M2TMatrix");
glUniformMatrix4fvARB(var,1,0,m_ModelToTextureMatrix.ele);

var   = glGetUniformLocationARB(m_GLSLProgram, "sampleDistance");
glUniform1fARB(var,GetSampleDistance());

var   = glGetUniformLocationARB(m_GLSLProgram, "A2OTexture");
glUniform1iARB(var, 0);

if (m_VolTexture ==0 || m_VolTextureNeedUpdate)
{
_genVolTexture();
m_VolTextureNeedUpdate=false;
}

var   = glGetUniformLocationARB(m_GLSLProgram, "VolTexture");
glUniform1iARB(var, 1);

if (m_TFTexture==0 || m_TF->IsModified())
{
_genTFTexture();
m_TF->SetUnmodified();
}

var   = glGetUniformLocationARB(m_GLSLProgram, "TF");
glUniform1iARB(var, 2);

float typeMin,typeMax;
if (m_Data->GetDataType()!=VolumeData::FLOAT)
{
VolumeData::DataType type=m_Data->GetDataType();
typeMin=(float)VolumeData::typemin[type];
typeMax=(float)VolumeData::typemax[type];
}
else
{
typeMin=0.0f;
typeMax=1.0f;
}
float tfMax=m_TF->GetMaxPos();
float tfMin=m_TF->GetMinPos();

var   = glGetUniformLocationARB(m_GLSLProgram, "scale");
glUniform1fARB(var, (typeMax-typeMin)/(tfMax-tfMin));

var   = glGetUniformLocationARB(m_GLSLProgram, "shift");
glUniform1fARB(var, (typeMin-tfMin)/(tfMax-tfMin));

{
Vector worldPoint;
Vector modelPoint;
float lightPosition[3], lightFocalPoint[3];
Vector lightDirection;

worldPoint.ele[3]=1.0f;

worldPoint.ele[0]=m_LightPosition[0];
worldPoint.ele[1]=m_LightPosition[1];
worldPoint.ele[2]=m_LightPosition[2];
modelPoint=m_InvertModelViewMatrix*worldPoint;

lightPosition[0]=modelPoint.ele[0];
lightPosition[1]=modelPoint.ele[1];
lightPosition[2]=modelPoint.ele[2];

worldPoint.ele[0]=m_LightFocalPoint[0];
worldPoint.ele[1]=m_LightFocalPoint[1];
worldPoint.ele[2]=m_LightFocalPoint[2];
modelPoint=m_InvertModelViewMatrix*worldPoint;

lightFocalPoint[0]=modelPoint.ele[0];
lightFocalPoint[1]=modelPoint.ele[1];
lightFocalPoint[2]=modelPoint.ele[2];

lightDirection.ele[0]=lightFocalPoint[0]-lightPosition[0];
lightDirection.ele[1]=lightFocalPoint[1]-lightPosition[1];
lightDirection.ele[2]=lightFocalPoint[2]-lightPosition[2];

lightDirection.Normalize();

float lightColor[3];
lightColor[0]=m_LightColor[0]*m_LightIntensity;
lightColor[1]=m_LightColor[1]*m_LightIntensity;
lightColor[2]=m_LightColor[2]*m_LightIntensity;

float ambient[3];
float diffuse[3];
float specular[3];
float spacings[3];
float specThreshold;

ambient[0]=m_Ambient*lightColor[0];
ambient[1]=m_Ambient*lightColor[1];
ambient[2]=m_Ambient*lightColor[2];

diffuse[0]=m_Diffuse*lightColor[0];
diffuse[1]=m_Diffuse*lightColor[1];
diffuse[2]=m_Diffuse*lightColor[2];

specular[0]=m_Specular*lightColor[0];
specular[1]=m_Specular*lightColor[1];
specular[2]=m_Specular*lightColor[2];

m_Data->GetSpacings(spacings);

specThreshold=pow(0.001f/max(max(specular[0],specular[1]),specular[2]),1.0f/m_SpecularPower);

var   = glGetUniformLocationARB(m_GLSLProgram, "ambient");
glUniform3fARB(var, ambient[0],ambient[1],ambient[2]);

var   = glGetUniformLocationARB(m_GLSLProgram, "diffuse");
glUniform3fARB(var, diffuse[0],diffuse[1],diffuse[2]);

var   = glGetUniformLocationARB(m_GLSLProgram, "specular");
glUniform3fARB(var, diffuse[0],diffuse[1],diffuse[2]);

var   = glGetUniformLocationARB(m_GLSLProgram, "specular_power");
glUniform1fARB(var, m_SpecularPower);

var   = glGetUniformLocationARB(m_GLSLProgram, "light_direction");
glUniform4fARB(var, lightDirection.ele[0],lightDirection.ele[1],lightDirection.ele[2],0.0f);

var   = glGetUniformLocationARB(m_GLSLProgram, "spacings");
glUniform4fARB(var,spacings[0],spacings[1],spacings[2],1.0f);

var   = glGetUniformLocationARB(m_GLSLProgram, "spec_threshold");
glUniform1fARB(var, specThreshold);
}

float ratio=m_SampleDistance/m_StdSampleDistance;
float alphaToOpacity[256];
int i;
for (i=0;i<256;i++)
alphaToOpacity[i]=1.0f-pow(1.0f-i/256.0f,ratio);

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_1D,m_A2OTexture);
glTexSubImage1D(GL_TEXTURE_1D,0,0,256,GL_LUMINANCE,GL_FLOAT,alphaToOpacity);

// render texture

glMatrixMode(GL_PROJECTION);

glMatrixMode(GL_MODELVIEW);
glMultMatrixf(m_PixelsToViewMatrix);

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

glTexCoord2i(m_ImageOrigin[0],m_ImageOrigin[1]);
glVertex2i(m_ImageOrigin[0],m_ImageOrigin[1]);
glTexCoord2i(m_ImageOrigin[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glVertex2i(m_ImageOrigin[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glTexCoord2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glVertex2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glTexCoord2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]);
glVertex2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]);
glEnd();

glUseProgramObjectARB(0);
glActiveTextureARB(GL_TEXTURE0_ARB);

return true;
}

I donot understand about the below codes:
Quote:

// render texture
glMatrixMode(GL_PROJECTION);

glMatrixMode(GL_MODELVIEW);
glMultMatrixf(m_PixelsToViewMatrix);

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

glTexCoord2i(m_ImageOrigin[0],m_ImageOrigin[1]);
glVertex2i(m_ImageOrigin[0],m_ImageOrigin[1]);
glTexCoord2i(m_ImageOrigin[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glVertex2i(m_ImageOrigin[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glTexCoord2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glVertex2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]+m_ImageInUseSize[1]);
glTexCoord2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]);
glVertex2i(m_ImageOrigin[0]+m_ImageInUseSize[0],m_ImageOrigin[1]);
glEnd();

glUseProgramObjectARB(0);
glActiveTextureARB(GL_TEXTURE0_ARB);
why need to render texture and the texture is GL_TEXTURE1_ARB ?
• 10-19-2012, 07:31 AM
carsten neumann
As far as I can tell the program uses two textures, one 3D one that contains the volume data and a 1D texture that contains some lookup table (for alpha values, going by the name). The use of texture unit 1 is a fairly arbitrary choice, the author could have used texture units 3 and 6 just as well. The only thing that needs to match is which texture is bound to which texture unit and the values assigned to the sampler uniforms (i.e.

Code :

var   = glGetUniformLocationARB(m_GLSLProgram, "VolTexture");
glUniform1iARB(var, 1);

)

Hmm, those actually seem to be mixed up in the code you posted. The "VolTexture" sampler is assigned value 1, but then

Code :

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_1D,m_A2OTexture);

binds the lookup table texture to texture unit 1.
• 10-19-2012, 06:50 PM
qlizhi
Yes, i think it use texture m_A2OTexture, and then render it to a 2D quads. It is hard to understand. If you have time , you can download the source code.
• 10-21-2012, 08:17 PM
qlizhi
When i change it to
Code :

glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_1D,m_A2OTexture);

it shows the same output.