[-1024; の範囲の値の 3D ボリュームがあります。3071]。と呼びましょうinput
。これらの値を OpenGL で処理する必要があります。1 は 3071 の値に対応し、0 は -1024 に対応します。4096 の可能な値の範囲をカバーするには 12 ビットで十分なのでGL_TEXTURE_3D
、内部形式のオブジェクトを作成しますGL_INTENSITY16
。テクスチャ データを値の配列としてアップロードする前に、uint16_t
上記のように、必要なマッピングを確立するために 4 ビット左シフトを実行します。
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() );
次に、ポイントをサポートする値が常にヒットするようなステップで x 方向のラインに沿ってテクスチャの値をサンプリングします。つまり、補間は必要ありません。サンプリングを実行するために、テクスチャ オブジェクト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
位置に関連してプロットされます。
const float ry = y / float( size.y - 1 );
const float rz = z / float( size.z - 1 );
for( unsigned int x = 0; x < size.x; ++x )
{
const float rx = x / float( size.x - 1 );
gpuPlot( x, gpuSampleAt( rx, ry, rz ) );
cpuPlot( x, static_cast< signed short >
( buffer[ x + size.x * y + size.y * size.x * z ] >> 4 ) -1024 );
}
同じことが CPU でも行われますが、これは非常に簡単です。プロットの結果は下の図に示されています。CPU によって取得されたサンプルは青い曲線で示され、OpenGL によって取得されたサンプルは赤色で示されています。
結果が同じにならないのはなぜですか?