Volume Rendering,VTK中带出来的深坑,不知道能填多少,例子中的代码大多是旧的。–2020年5月7日 18点17分
一点点补充,浅尝辄止。很久前已经做了很多,都是基于OpenGL,其中最简单的就是纹理映射,因为算法不用自己写,理论支撑就可以,弊端是玩不出花样。相对来说更好玩的可能是光线投射。有时间的话,最好把其他几种都动手写一下。 --2020年5月8日 09点00分
3D和2D之间的区别在于:数据在硬件缓存中保存的方式。2D省资源,3D更高效。
2D纹理映射:
// Macro to draw the quad.
// Performance can be achieved by making a call list.
// To make it simple i am not using that now :-)
#define MAP_2DTEXT( TexIndex ) \
glTexCoord2f(0.0f, 0.0f); \
glVertex3f(-dOrthoSize,-dOrthoSize,(TexIndex *2*dOrthoSize/fFrameCount)-1.0f);\
glTexCoord2f(1.0f, 0.0f); \
glVertex3f(dOrthoSize,-dOrthoSize,(TexIndex *2*dOrthoSize/fFrameCount)-1.0f);\
glTexCoord2f(1.0f, 1.0f); \
glVertex3f(dOrthoSize,dOrthoSize,(TexIndex *2*dOrthoSize/fFrameCount)-1.0f);\
glTexCoord2f(0.0f, 1.0f); \
glVertex3f(-dOrthoSize,dOrthoSize,(TexIndex *2*dOrthoSize/fFrameCount)-1.0f);
void Texture2Dscene::RenderContent()
{
fFrameCount = (float)m_uImageCount;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//glMatrixMode( GL_MODELVIEW );
//glLoadIdentity();
//glRotated( mfRotation, 0, 1.0,0 );
glEnable(GL_TEXTURE_2D);
for(int nIndx=0; nIndx <m_uImageCount;nIndx++)
{
glBindTexture(GL_TEXTURE_2D,m_puTextureIDs[nIndx]);//2D纹理贴图准备
glBegin(GL_QUADS);//2D纹理矩形
MAP_2DTEXT(nIndx);
glEnd();
glBindTexture(GL_TEXTURE_2D,0);
}
glFlush();
}
void Texture2Dscene::Init()
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glEnable( GL_ALPHA_TEST );
glAlphaFunc( GL_GREATER, 0.05f );
glGenTextures(m_uImageCount,(GLuint*)m_puTextureIDs );//重要-----纹理合成
// Holds the luminance buffer
unsigned char* chBuffer_2d = new unsigned char[ m_uImageWidth*m_uImageHeight ];
// Holds the RGBA buffer
char* chRGBABuffer = new char[ m_uImageWidth*m_uImageHeight*m_uImageCount*4 ];
//glGenTextures(1,(GLuint*)&texName );
for( int nIndx = 0; nIndx < m_uImageCount; ++nIndx )
{
for( int i = 0; i < m_uImageWidth*m_uImageHeight; ++i )
{
chBuffer_2d[i] = chBuffer[nIndx*(m_uImageWidth*m_uImageHeight)+i];
}
// Set the properties of the texture.
glBindTexture( GL_TEXTURE_2D, m_puTextureIDs[nIndx] );
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);
// Convert the data to RGBA data.
// Here we are simply putting the same value to R, G, B and A channels.
// Usually for raw data, the alpha value will
// be constructed by a threshold value given by the user
for( int j = 0; j < m_uImageWidth*m_uImageHeight; ++j )
{
chRGBABuffer[j*4] = chBuffer_2d[j];
chRGBABuffer[j*4+1] = chBuffer_2d[j];
chRGBABuffer[j*4+2] = chBuffer_2d[j];
chRGBABuffer[j*4+3] = 255;
if( chBuffer_2d[j] < 20 )
{
chRGBABuffer[j*4+3] = 0;
}
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_uImageWidth, m_uImageHeight , 0,
GL_RGBA, GL_UNSIGNED_BYTE,(GLvoid *) chRGBABuffer );
//glTranslatef( -0.5f,-0.5f, -0.5f );
glBindTexture( GL_TEXTURE_2D, 0 );
}
}
3D纹理映射:
// Macro to draw the quad.
// Performance can be achieved by making a call list.
// To make it simple i am not using that now :-)
#define MAP_3DTEXT( TexIndex ) \
glTexCoord3f(0.0f, 0.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(-dOrthoSize,-dOrthoSize,TexIndex);\
glTexCoord3f(1.0f, 0.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(dOrthoSize,-dOrthoSize,TexIndex);\
glTexCoord3f(1.0f, 1.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(dOrthoSize,dOrthoSize,TexIndex);\
glTexCoord3f(0.0f, 1.0f, ((float)TexIndex+1.0f)/2.0f); \
glVertex3f(-dOrthoSize,dOrthoSize,TexIndex);
void Texture3Dscene::RenderContent()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for ( float fIndx = -1.0f; fIndx <= 1.0f; fIndx+=0.01f )
{
glBegin(GL_QUADS);
MAP_3DTEXT( fIndx );
glEnd();
}
glFlush();
}
void Texture3Dscene::Init()
{
glTexImage3D = reinterpret_cast< PFNGLTEXIMAGE3DPROC>( ::wglGetProcAddress( "glTexImage3D") );
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_3D, texName);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
this->m_uImageWidth,
this->m_uImageHeight,
this->m_uImageCount, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata);//-------------
//glBindTexture( GL_TEXTURE_3D, 0 );
//float fFrameCount = (float)m_pRawDataProc->GetDepth();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable( GL_ALPHA_TEST );
glAlphaFunc( GL_GREATER, 0.05f );
glEnable(GL_BLEND);
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
// Translate and make 0.5f as the center
// (texture co ordinate is from 0 to 1. so center of rotation has to be 0.5f)
glTranslatef( 0.5f, 0.5f, 0.5f );
// A scaling applied to normalize the axis
// (Usually the number of slices will be less so if this is not -
// normalized then the z axis will look bulky)
// Flipping of the y axis is done by giving a negative value in y axis.
// This can be achieved either by changing the y co ordinates in -
// texture mapping or by negative scaling of y axis
glScaled( (float)256/(float)256,
-1.0f*(float)256/(float)(float)256,
(float)256/(float)109);
//CTranformationMgr* m_pTransform = new CTranformationMgr;
// Apply the user provided transformations
glMultMatrixd( m_pTransformMgr->GetMatrix());
glTranslatef( -0.5f,-0.5f, -0.5f );
glEnable(GL_TEXTURE_3D);
}
CPU based 伪3D:
void RayCasting3Dscene2::RenderContent()
{
glClearColor(0.5f,0.5f,0.5f,1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
glWindowPos2i(m_ImageOrigin[0], m_ImageOrigin[1]);//glew接口,要在glewInit后用
glDrawPixels(WIDTH,HEIGTH,GL_RGBA,GL_FLOAT,Image);//使用OpenGL的绘图函数
glFlush();
}
void RayCasting3Dscene2::Init()
{
glewInit(); // 初始化glew
}
GPU based 伪3D:(这部分暂时就不写了)
在这里插入代码片
参考文献: