0

[-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 方向のラインに沿ってテクスチャの値をサンプリングします。つまり、補間は必要ありません。サンプリングを実行するために、テクスチャ オブジェクトcolorBufferIDGL_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 によって取得されたサンプルは赤色で示されています。

得られたデータのプロット - 青: CPU によって取得されたサンプル - 赤: OpenGL によって取得されたもの

結果が同じにならないのはなぜですか?

4

0 に答える 0