1

Quartz Composer に適合したカスタム ジオメトリ ライブラリに取り組んでおり、プラグインでいくつかの凹面ポリゴンを描画しようとしています。

poly2tri ライブラリを実装したので、ユーザーは三角形化するかどうかを選択できますが、フレームごとのポリゴン変換レンダリングには適していません。

私は OpenGL の初心者で、ステンシル バッファと奇数/偶数操作について多くのことを読んでテストしてきましたが、他の人にとってはうまくいくように見えるコードでさえ、私にとってはうまくいきません。

レンダー コンテキストは CGLContextObj で、NVidia GEForce GT650 を搭載した MacBook Pro Retina ディスプレイで作業しています。すべての構成にステンシル バッファーがないことを読みましたが、私が望んでいるとは限りませんが、時々機能するように見えます。

同じ種類の構成を持つ誰かが機能するコードを使用していて、私のコードを見ることができるかどうか疑問に思っていました。特に、頂点の数または「凸欠陥」に応じて、要求されたパスの数についても興味があります...

から情報を取得しました:

...しかし、まだ明確ではありません...

これが私のコード(実際には、非常に多くの構成をテストしたため、そのうちの1つです)と結果の写真です。実際には、各ポリゴンに対して呼び出されるメソッドに実際のレンダリングを配置していましたが、より明確になるように書き直しました。


編集

実際、ステンシル バッファのビット値を反転するために、各三角形を描画する必要があることを理解しました。だから私はこれに私のコードを書き直しました:

CGLContextObj cgl_ctx = [context CGLContextObj];

CGLLockContext(cgl_ctx);

GLenum                          error;

if(cgl_ctx == NULL)
    return NO;


glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);



glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glDisable(GL_CULL_FACE);
glClear(GL_STENCIL_BUFFER_BIT);
glClearStencil(0);

glEnable(GL_STENCIL_TEST);

glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
glStencilFunc(GL_ALWAYS, 1, 1);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

// glColor4d(1., 1., 1., 1.);        ----> does it make sense ?
glBegin(GL_TRIANGLE_FAN); {

    for (int i = 1; i < [vertices count] - 1; i++) {
        // Allways drawing the first vertex
        glVertex2d([[[vertices objectAtIndex:0] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:0] objectAtIndex:1] doubleValue]);

        // Then two others to make a triangle
        glVertex2d([[[vertices objectAtIndex:i] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:i] objectAtIndex:1] doubleValue]);
        glVertex2d([[[vertices objectAtIndex:i+1] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:i+1] objectAtIndex:1] doubleValue]);

    }

}
glEnd();


glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glStencilFunc(GL_EQUAL, 1, 1);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

glColor4d(1., 0., 0., 0.5);
glBegin(GL_TRIANGLE_FAN); {
    for (id vertex in vertices) {
        glVertex2d([[vertex objectAtIndex:0] doubleValue], [[vertex objectAtIndex:1] doubleValue]);
    }
    glVertex2d([[[vertices objectAtIndex:0] objectAtIndex:0] doubleValue], [[[vertices objectAtIndex:0] objectAtIndex:1] doubleValue]);
}
glEnd();


glDisable (GL_STENCIL_TEST);




glDisable(GL_BLEND);


glPopClientAttrib();
glPopAttrib();



if((error = glGetError()))
    NSLog(@"OpenGL error %04X", error);

CGLUnlockContext(cgl_ctx);

return (error ? NO : YES);

しかし、それでもうまくいきません。これが私の結果と、元の画像と説明へのリンクです。

http://what-when-how.com/opengl-programming-guide/drawing-filled-concave-polygons-using-the-stencil-buffer-opengl-programming/

ステンシルの失敗

編集2:

実際、Quartz Composer によって有効化されたコンテキストは、ステンシル バッファーを実装していません。ステンシル バッファを使用して OpenGL で直接レンダリングすることは不可能のようです。

4

1 に答える 1

1
...
glClearStencil(0);
...

glClearStencil()少しの状態を設定するだけで、実際にはステンシル バッファーをクリアしないことに注意してください。

glClear( GL_STENCIL_BUFFER_BIT )各ポリゴンの前にどこかに追加してみてください。

編集:このように:

#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <vector>

std::vector< glm::vec2 > pts;
bool leftHeld = true;
glm::vec2* dragPt = NULL;
void mouse( int button, int state, int x, int y )
{
    glm::vec2 pt( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );

    // left mouse button starts dragging a point
    dragPt = NULL;
    leftHeld = false;
    if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
    {
        leftHeld = true;
        size_t minIdx = 0;
        for( size_t i = 0; i < pts.size(); ++i )
        {
            float newDist = glm::distance( pt, pts[ i ] );
            float oldDist = glm::distance( pt, pts[ minIdx ] );
            if( newDist <= oldDist && newDist < 15.0f )
            {
                minIdx = i;
                dragPt = &pts[ minIdx ];
            }
        }
    }

    // middle mouse button clears all points
    if( button == GLUT_MIDDLE_BUTTON && state == GLUT_UP )
    {
        pts.clear();
    }

    // right mouse button adds a point
    if( button == GLUT_RIGHT_BUTTON && state == GLUT_UP )
    {
        pts.push_back( pt );
    }

    glutPostRedisplay();
}

void motion( int x, int y )
{
    glm::vec2 pt( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
    if( dragPt && leftHeld )
    {
        *dragPt = pt;
        glutPostRedisplay();
    }
}

void glLine( const std::vector< glm::vec2 >& line, GLenum mode )
{
    glBegin( mode );
    for( size_t i = 0; i < line.size(); ++i )
    {
        glVertex2f( line[i].x, line[i].y );
    }
    glEnd();
}

void display()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    glOrtho( 0, w, 0, h, -1, 1 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    // draw polygon
    glClear( GL_STENCIL_BUFFER_BIT );
    {
        // fill stencil buffer
        glEnable( GL_STENCIL_TEST );
        glColorMask( GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE );
        glStencilOp( GL_KEEP, GL_KEEP, GL_INVERT );
        glStencilFunc( GL_ALWAYS, 0x1, 0x1 );
        glBegin( GL_TRIANGLES );
        for( size_t i = 1; i+1 < pts.size(); ++i )
        {
            glVertex2fv( glm::value_ptr( pts[ 0 ] ) );
            glVertex2fv( glm::value_ptr( pts[ i ] ) );
            glVertex2fv( glm::value_ptr( pts[ i+1 ] ) );
        }
        glEnd();

        // fill color buffer
        glColor3ub( 0, 128, 0 );
        glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
        glStencilFunc( GL_EQUAL, 0x1, 0x1 );
        glBegin( GL_TRIANGLES );
        for( size_t i = 1; i+1 < pts.size(); ++i )
        {
            glVertex2fv( glm::value_ptr( pts[ 0 ] ) );
            glVertex2fv( glm::value_ptr( pts[ i ] ) );
            glVertex2fv( glm::value_ptr( pts[ i+1 ] ) );
        }
        glEnd();
        glDisable( GL_STENCIL_TEST );
    }

    // draw polygon boundary
    glLineWidth( 1 );
    glColor3ub( 255, 255, 255 );
    glLine( pts, GL_LINE_LOOP );

    // draw vertexes
    glPointSize( 9 );
    glColor3ub( 255, 0, 0 );
    glLine( pts, GL_POINTS );

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL );
    glutInitWindowSize( 640, 480 );
    glutCreateWindow( "GLUT" );
    glutMouseFunc( mouse );
    glutMotionFunc( motion );
    glutDisplayFunc( display );
    glutMainLoop();
    return 0;
}
于 2013-03-08T01:18:43.150 に答える