【问题标题】:Use of GL_STENCIL_TEST to render concave polygons使用 GL_STENCIL_TEST 渲染凹多边形
【发布时间】:2013-03-07 23:44:58
【问题描述】:

我正在开发一个适用于 Quartz Composer 的自定义几何库,并尝试在插件中绘制一些凹多边形。

我实现了 poly2tri 库,因此用户可以选择是否进行三角测量,但它不适合每帧多边形变换渲染。

我是 OpenGL 的菜鸟,我一直在阅读和测试很多关于模板缓冲区和奇/偶操作的内容,但即使代码似乎对其他人有用,但对我却不起作用。

渲染上下文是 CGLContextObj,我正在使用 NVidia GEForce GT650 开发 MacBook Pro Retina 显示器。我读到所有配置都没有模板缓冲区,但它看起来有时可以工作,尽管不是我想要的那样。

我想知道是否有人具有相同类型的配置正在使用有效的代码并且可以查看我的代码。特别是,我也很好奇请求的通过次数,根据我猜的顶点或“凸面缺陷”的数量......

我的信息来自:

……但还是不清楚……

这是我的代码(实际上是其中一个,因为我测试了很多配置)和结果图片。实际上,我曾经将实际渲染放在为每个多边形调用的方法中,但我将其重写为非常清晰:


编辑

事实上,我知道我必须绘制每个三角形,以便反转模板缓冲区中的位值。所以我把我的代码改写成这样:

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 中渲染似乎是不可能的。

【问题讨论】:

    标签: objective-c opengl polygon quartz-composer stencil-buffer


    【解决方案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;
    }
    

    【讨论】:

    • 对不起,我没有看到你的答案......我想你提出的这个解决方案必须有效,但现在我正在努力如何在 Quartz Composer 中“设置”模板缓冲区CGLContextObj...不正常我有...模板缓冲区中的0位...不是吗?
    • OpenGL Extensions Viewer 告诉我卡“有”,实际上,模板缓冲区中有 0 8 位...设法找到如何将其设置为 8无需重新定义像素格式(我想我在 Quartz Composer 中做不到?!?)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 2013-02-24
    • 2011-01-28
    • 1970-01-01
    相关资源
    最近更新 更多