我的3D体积值在[-1024; 3071。让我们称之为input
。我需要以这种方式使用OpenGL处理这些值,1对应于值3071而0映射到-1024。由于12位足以覆盖4096个可能值的范围,因此我创建了一个内部格式为GL_TEXTURE_3D
的{{1}}对象。在将纹理数据作为GL_INTENSITY16
值数组上传之前,我确实执行左移4位以建立所需的映射,如上所述:
uint16_t
然后我按照这些步骤沿着x方向的线对纹理的值进行采样,使得支持点的值始终被命中,这意味着不需要插值。为了执行采样,将点绘制到帧缓冲对象,该对象使用纹理对象const std::vector< signed short >& inputBuffer = input.buffer();
std::vector< uint16_t > buffer( inputBuffer.size() );
for( unsigned int i = 0; i < inputBuffer .size(); ++i )
{
buffer[ i ]
= static_cast< uint16_t >( ( inputBuffer[ i ] + 1024 ) << 4 );
}
glBindTexture( GL_TEXTURE_3D, volumeTextureID );
glTexImage3D( GL_TEXTURE_3D, 0, GL_INTENSITY16
, size.x, size.y, size.z
, 0, GL_RED, GL_UNSIGNED_SHORT, &buffer.front() );
作为其colorBufferID
颜色缓冲区:
GL_RGBA16F
如上所述,上述函数是针对不同的float gpuSampleAt( float x, float y, float z )
{
bindFramebufferObject();
glBindTexture( GL_TEXTURE_3D, volumeTextureID );
glBegin( GL_POINTS );
glTexCoord3f( x, y, z );
glVertex3f( 0, 0, 0 );
glEnd();
unbindFramebufferObject();
float intensity;
glBindTexture( GL_TEXTURE_2D, colorBufferID );
glGetTexImage( GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &intensity );
return intensity * 4095 - 1024;
}
值执行的。获得的强度相对于它们的x
位置绘制:
x
在CPU上完成同样的操作,这非常简单。绘图结果如下图所示 - 由CPU获得的样本用蓝色曲线显示,通过OpenGL获得的样本用红色显示:
为什么结果不一样?