PDA

View Full Version : GPU-based volume raycasting



qlizhi
10-15-2012, 02:37 AM
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:
http://code.google.com/p/qt-color-delegate/downloads/list
I have read several times of the source code, but in some place i still cannot understand.
in frag_shader


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 .

carsten neumann
10-15-2012, 03:32 PM
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.

qlizhi
10-15-2012, 09:18 PM
Thank you very much, but i still donot know what does "t1=(0.0-texel_zero.x)/texel_dir_norm.x" mean.

carsten neumann
10-16-2012, 09:34 AM
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.

qlizhi
10-19-2012, 02:51 AM
haha~~ i got it. thanks a lot!

qlizhi
10-19-2012, 03:09 AM
The last question about this code is the main render 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_shaderInit)
{
_initShaders();
m_shaderInit=true;
}

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

if (!_calculateBounds()) return false;

//Setup Shader
glUseProgramObjectARB(m_GLSLProgram);

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

var = glGetUniformLocationARB(m_GLSLProgram, "M2TMatrix");
glUniformMatrix4fvARB(var,1,0,m_ModelToTextureMatr ix.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));

int shade=m_Shade?1:0;
var = glGetUniformLocationARB(m_GLSLProgram, "shade");
glUniform1iARB(var, shade);

if (m_Shade)
{
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);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf(m_PixelsToViewMatrix);

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

glBegin(GL_QUADS);
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:


// render texture
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf(m_PixelsToViewMatrix);

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

glBegin(GL_QUADS);
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 ?

carsten neumann
10-19-2012, 08:31 AM
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.



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



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


binds the lookup table texture to texture unit 1.

qlizhi
10-19-2012, 07:50 PM
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.

qlizhi
10-21-2012, 09:17 PM
When i change it to


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

it shows the same output.