体绘制基础知识

Volume Rendering,VTK中带出来的深坑,不知道能填多少,例子中的代码大多是旧的。–2020年5月7日 18点17分
一点点补充,浅尝辄止。很久前已经做了很多,都是基于OpenGL,其中最简单的就是纹理映射,因为算法不用自己写,理论支撑就可以,弊端是玩不出花样。相对来说更好玩的可能是光线投射。有时间的话,最好把其他几种都动手写一下。 --2020年5月8日 09点00分

纹理映射(Texture Mapping)

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);
}
光线投射算法( Ray-casting )

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:(这部分暂时就不写了)

在这里插入代码片
错切 - 变形算法( Shear-warp )
频域体绘制算法( Frequency Domain )
抛雪球算法( Splatting )

参考文献:

  1. 体绘制(Volume Rendering)概述_网络_brilliantyoho的博客-CSDN博客
    https://blog.csdn.net/brilliantyoho/article/details/38556773
  2. 基于CUDA实现Ray-Casting - Windsper - 博客园
    https://www.cnblogs.com/fengyuheliu/archive/2011/08/28/2155627.html

你可能感兴趣的:(修仙之道,#,图形用户界面)