1

次の 3 つの方法でカラー ピッキング/選択を実装したいと思います。

void ColorIndex(uint colorIndex)
{
    glColor4ubv((GLubyte *)&colorIndex);
}

void ColorIndices(vector<uint> &colorIndices)
{
    GLubyte *colorPtr = (GLubyte *)&colorIndices[0];
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, colorPtr);
}

void ReadSelectedIndices(int x, int y, int width, int height, uint *selectedIndices)
{
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, selectedIndices);
}

基本的に、符号なし整数 (32 ビット) を 4 バイトの R、G、B、A にパックします。GL_SELECT に比べてシンプルで非常に高速です。

問題は、時々うまくいかないことです。NVIDIA 9800 グラフィックス カードを搭載した Windows では動作しません。Mac/Windows の ATI Radeon 4670 で動作します。

問題はアルファチャンネルにあると考えていたので、この実装を試しました:

union RgbColor
{
    GLuint colorIndex : 24;
    GLubyte components[3];
    struct
    {
        GLubyte r;
        GLubyte g;
        GLubyte b;
    };
};

void ColorIndex(uint colorIndex)
{
    RgbColor color;
    color.colorIndex = colorIndex;
    glColor3ubv(color.components);
}

vector<GLubyte> colorComponents;

void ColorIndices(vector<uint> &colorIndices)
{
    colorComponents.clear();

    for (uint i = 0; i < colorIndices.size(); i++)
    {
        RgbColor color;
        color.colorIndex = colorIndices[i];

        colorComponents.push_back(color.components[0]);
        colorComponents.push_back(color.components[1]);
        colorComponents.push_back(color.components[2]);
    }

    GLubyte *colorPtr = (GLubyte *)&colorComponents[0];
    glColorPointer(3, GL_UNSIGNED_BYTE, 0, colorPtr);
}

const uint kMaxSelectedIndicesCount = 2000 * 2000;  // max width * max height resolution

GLubyte colorBuffer[kMaxSelectedIndicesCount * 3];

void ReadSelectedIndices(int x, int y, int width, int height, uint *selectedIndices)
{
    uint count = (uint)width * (uint)height;

    memset(colorBuffer, 0, count * 3);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, colorBuffer);
    GetGLError();

    for (uint i = 0; i < count; i++)
    {
        RgbColor color;
        color.components[0] = colorBuffer[i * 3 + 0];
        color.components[1] = colorBuffer[i * 3 + 1];
        color.components[2] = colorBuffer[i * 3 + 2];

        selectedIndices[i] = color.colorIndex;
    }
}

グラフィックス カードと OS の両方で選択が機能するようになりましたが、不適切な頂点が選択されることがあります (選択範囲の外側)。

これはどのように起こりますか?堅牢で、さまざまなグラフィックス カードで常に正しいカラー ピッキングを実装するためのより良い方法はありますか?

4

0 に答える 0