OpenGL—ES 1.0 2d rounded rectangle

后端 未结 7 455
生来不讨喜
生来不讨喜 2020-12-28 09:46

How to make rounded rectangle in OpenGL, or any polygon with rounded corners?

7条回答
  •  借酒劲吻你
    2020-12-28 10:34

    Bit of a bump but I was stuck on the same problem today, this is what I output, its created with Desktop GL, but should be very easy to convert to GLES, everything is a strip. It is probably not as optimized as it should be but if someone want to have a stab at it please be my guest ;)

    typedef struct
    {
        float x;
        float y;
    
    } Vector2f;
    
    
    void RoundRect( int x,
                int y,
                int width,
                int height,
                int radius,
                int resolution )
    {
    float step = ( 2.0f * M_PI ) / resolution,
          angle = 0.0f,
          x_offset,
          y_offset;
    
    int i = 0;
    
    unsigned int index = 0,
                 segment_count = ( int )( resolution / 4 );
    
    Vector2f *top_left             = ( Vector2f * ) malloc( segment_count * sizeof( Vector2f ) ), 
             *bottom_left         = ( Vector2f * ) malloc( segment_count * sizeof( Vector2f ) ),
             *top_right             = ( Vector2f * ) malloc( segment_count * sizeof( Vector2f ) ),
             *bottom_right         = ( Vector2f * ) malloc( segment_count * sizeof( Vector2f ) ),
              bottom_left_corner = { x + radius,
                                     y - height + radius }; 
    
    while( i != segment_count )
    {
        x_offset = cosf( angle );
        y_offset = sinf( angle );
    
    
        top_left[ index ].x = bottom_left_corner.x - 
                              ( x_offset * radius );
        top_left[ index ].y = ( height - ( radius * 2.0f ) ) + 
                                bottom_left_corner.y - 
                              ( y_offset * radius );
    
    
        top_right[ index ].x = ( width - ( radius * 2.0f ) ) + 
                                 bottom_left_corner.x + 
                               ( x_offset * radius );
        top_right[ index ].y = ( height - ( radius * 2.0f ) ) + 
                                 bottom_left_corner.y -
                               ( y_offset * radius );
    
    
        bottom_right[ index ].x = ( width - ( radius * 2.0f ) ) +
                                    bottom_left_corner.x + 
                                  ( x_offset * radius );
        bottom_right[ index ].y = bottom_left_corner.y + 
                                  ( y_offset * radius );
    
    
        bottom_left[ index ].x = bottom_left_corner.x - 
                                 ( x_offset * radius );
        bottom_left[ index ].y = bottom_left_corner.y +
                                 ( y_offset * radius );
    
    
        top_left[ index ].x = roundf( top_left[ index ].x );
        top_left[ index ].y = roundf( top_left[ index ].y );
    
    
        top_right[ index ].x = roundf( top_right[ index ].x );
        top_right[ index ].y = roundf( top_right[ index ].y );
    
    
        bottom_right[ index ].x = roundf( bottom_right[ index ].x );
        bottom_right[ index ].y = roundf( bottom_right[ index ].y );
    
    
        bottom_left[ index ].x = roundf( bottom_left[ index ].x );
        bottom_left[ index ].y = roundf( bottom_left[ index ].y );
    
        angle -= step;
    
        ++index;
    
        ++i;
    }
    
    
    glBegin( GL_TRIANGLE_STRIP );
    {
        // Top
        {
            i = 0;
            while( i != segment_count )
            {
                //glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
                glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
                glVertex2i( top_left[ i ].x,
                            top_left[ i ].y );
    
                //glColor4f( 0.0f, 1.0f, 0.0f, 1.0f );
                glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
                glVertex2i( top_right[ i ].x,
                            top_right[ i ].y );
    
                ++i;
            }
        }
    
    
        // In order to stop and restart the strip.
        glColor4f( 0.0f, 1.0f, 0.0f,  1.5f );
        glVertex2i( top_right[ 0 ].x,
                    top_right[ 0 ].y );
    
        glColor4f( 0.0f, 1.0f, 0.0f,  1.5f );
        glVertex2i( top_right[ 0 ].x,
                    top_right[ 0 ].y );
    
    
        // Center
        {
            //glColor4f( 0.0f, 1.0f, 0.0f,  1.0f );
            glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
            glVertex2i( top_right[ 0 ].x,
                        top_right[ 0 ].y );
    
    
            //glColor4f( 1.0f, 0.0f, 0.0f,  1.0f );
            glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
            glVertex2i( top_left[ 0 ].x,
                        top_left[ 0 ].y );
    
    
            //glColor4f( 0.0f, 0.0f, 1.0f,  1.0f );
            glColor4f( 0.5f, 0.5f, 0.5f,  1.0f );
            glVertex2i( bottom_right[ 0 ].x,
                        bottom_right[ 0 ].y );
    
    
            //glColor4f( 1.0f, 1.0f, 0.0f,  1.0f );
            glColor4f( 0.5f, 0.5f, 0.5f,  1.0f );
            glVertex2i( bottom_left[ 0 ].x,
                        bottom_left[ 0 ].y );
        }
    
    
        // Bottom
        i = 0;
        while( i != segment_count )
        {
            //glColor4f( 0.0f, 0.0f, 1.0f,  1.0f );
            glColor4f( 0.5f, 0.5f, 0.5f,  1.0f );
            glVertex2i( bottom_right[ i ].x,
                        bottom_right[ i ].y );    
    
            //glColor4f( 1.0f, 1.0f, 0.0f,  1.0f );
            glColor4f( 0.5f, 0.5f, 0.5f,  1.0f );
            glVertex2i( bottom_left[ i ].x,
                        bottom_left[ i ].y );                                    
    
            ++i;
        }    
    }
    glEnd();
    
    
    
    glBegin( GL_LINE_STRIP );
    
    //glColor4f( 0.0f, 1.0f, 1.0f, 1.0f );
    glColor4f( 1.0f, 0.5f, 0.0f, 1.0f );
    
    // Border
    {
        i = ( segment_count - 1 );
        while( i > -1 )
        {    
            glVertex2i( top_left[ i ].x,
                        top_left[ i ].y );
    
            --i;
        }
    
    
        i = 0;
        while( i != segment_count )
        {    
            glVertex2i( bottom_left[ i ].x,
                        bottom_left[ i ].y );
    
            ++i;
        }
    
    
        i = ( segment_count - 1 );
        while( i > -1 )
        {    
            glVertex2i( bottom_right[ i ].x,
                        bottom_right[ i ].y );
    
            --i;
        }
    
    
        i = 0;
        while( i != segment_count )
        {    
            glVertex2i( top_right[ i ].x,
                        top_right[ i ].y );
    
            ++i;
        }
    
    
        // Close the border.
        glVertex2i( top_left[ ( segment_count - 1 ) ].x,
                    top_left[ ( segment_count - 1 ) ].y );
    }
    glEnd();
    
    
    
    
    glBegin( GL_LINES );
    
    //glColor4f( 0.0f, 1.0f, 1.0f, 1.0f );
    glColor4f( 0.0f, 0.5f, 1.0f, 1.0f );
    
    // Separator
    {
        // Top bar
        glVertex2i( top_right[ 0 ].x,
                    top_right[ 0 ].y );
    
        glVertex2i( top_left[ 0 ].x,
                    top_left[ 0 ].y );    
    
    
        // Bottom bar
        glVertex2i( bottom_left[ 0 ].x,
                    bottom_left[ 0 ].y );    
    
        glVertex2i( bottom_right[ 0 ].x,
                    bottom_right[ 0 ].y );    
    }
    glEnd();
    
    
    
    free( top_left );
    free( bottom_left );
    free( top_right );
    free( bottom_right );
    }
    

    To draw the rounded rectangle simply call something like inside an orthographic view:

    RoundRect( 200, /* x */
               400, /* y */
               400, /* width */
               300, /* height */
               25,  /* Corner radius, at least less than 140? */
               64  /* need to be "dividable" by 4 */ );
    

提交回复
热议问题