使用OpenGL ES中的单个glDrawElement(triangle_strip ...)调用绘制圆角矩形

时间:2013-10-24 08:17:08

标签: c++ opengl-es rounded-corners

我想在Opengl es中绘制一个圆角矩形,只需一个glDraw调用。 我也尝试过了。并在答案中分享。

希望它会有所帮助。

2 个答案:

答案 0 :(得分:2)

我试图在单个glDraw调用中在opengl中绘制一个圆角矩形 以下是代码段:

// -0.3f,   -0.2f,  0.0f,   // 0
//  0.3f,  -0.2f,  0.0f,    // 1
// -0.3f,   0.2f,  0.0f,    // 2
//  0.3f,    0.2f,  0.0f,   // 3
//  0.6f,   0.2f,  0.0f,    // 4
//  0.6f,   -0.2f,  0.0f,   // 5
//  0.6f,  -0.5f,  0.0f,    // 6
//  0.3f,  -0.5f,  0.0f,    // 7
// -0.3f,   -0.5f,  0.0f,   // 8
// -0.6f,  -0.5f,  0.0f,    // 9
// -0.6f,  -0.2f,  0.0f,    // 10
// -0.6f,   0.2f,  0.0f,    // 11
// -0.6f,    0.5f,  0.0f,   // 12
// -0.3f,   0.5f,  0.0f,    // 13
//  0.3f,    0.5f,  0.0f,   // 14
//  0.6f,   0.5f,  0.0f // 15
//
//            8_______________________7
//            /|                      |\
//          9/ |                      | \6
//        10/  |                      |  \5
//         /___|______________________|___\
//       1 |   |2                    3|   |4
//         |   |                      |   |
//         |   |                      |   |
//      12 |___|______________________|___|19
//         \   |0                    1|   /
//        13\  |                      |  /18
//         14\ |                      | /17
//            \|______________________|/
//            15                      16
//

static GLfloat vertRndRect[N];
// first store the vertices 0,1,2,3,4 in vertRndRect array
// then calculate the value for vertices 5 and 6 using the below code
for (i = 30; i < 90; i = i + 30)  // change this line to create more vertices but 'indices' array will change
{
float X_cen = vert1[9]; 
float Y_cen = vert1[10];
    vertRndRect[iVertCnt++]  = X_cen + (cos(degreesToRadians(i)) * rad); 
    vertRndRect[iVertCnt++]  = Y_cen + (sin(degreesToRadians(i)) * rad); 
vertRndRect[iVertCnt++]  = 0.0f; // Z
}
// Then store  vertices 7 and 8 to vertRndRect array
// then calculate the value for vertices 9 and 10 using the below code
for (i =  120; i < 180; i = i + 30)
{
float X_cen = vert1[6];
float Y_cen = vert1[7];
    vertRndRect[iVertCnt++]  = X_cen + (cos(degreesToRadians(i)) * rad);
    vertRndRect[iVertCnt++]  = Y_cen + (sin(degreesToRadians(i)) * rad);
vertRndRect[iVertCnt++]  = 0.0f; // Z
}

// Then store  vertices 11 and 12 to vertRndRect array
// then calculate the value for vertices 13 and 14 using the below code
for (i = 210; i < 270;  i = i + 30)
{
float X_cen = vert1[0];
float Y_cen = vert1[1];
    vertRndRect[iVertCnt++]  = X_cen + (cos(degreesToRadians(i)) * rad);
    vertRndRect[iVertCnt++]  = Y_cen + (sin(degreesToRadians(i)) * rad);
vertRndRect[iVertCnt++]  = 0.0f; // Z
}

// Then store  vertices 15 and 16 to vertRndRect array
// then calculate the value for vertices 13 and 14 using the below code
for (i = 300; i < 360;  i = i + 30)
{
float X_cen = vert1[3];
float Y_cen = vert1[4];
    vertRndRect[iVertCnt++]  = X_cen + (cos(degreesToRadians(i)) * rad);
    vertRndRect[iVertCnt++]  = Y_cen + (sin(degreesToRadians(i)) * rad);
vertRndRect[iVertCnt++]  = 0.0f; // Z
}
// Then store  vertices 19
//////////////////////////
GLushort indices[] = {  0, 1, 2, 3, 3, 4, 
                            5, 5, 3, 6, 7, 7, 
                            3, 8, 2, 9, 10, 10, 
                            2, 11, 0, 12, 13, 13, 
                            0, 14, 15, 15, 0, 16, 
                            1, 17, 18, 18, 1, 19, 3, 4
                         };
//////////////////////////
glDrawElements(GL_TRIANGLE_STRIP, 38, GL_UNSIGNED_SHORT,indices); // 38 is size of 'indices' array

在这里,我为每个圆角仅计算了2个顶点 但是可以增加它以获得更多的平滑度 但必须在'indices'数组

中进行相应的更改

可以在此代码中完成大量优化。

答案 1 :(得分:2)

我修改了代码以获取输入(TopLeft角位置,宽度和高度),并为每个圆角及其纹理坐标动态生成10个顶点。

     // Vertices and Texture Coordinates Generation.
    Input: Width and Height, Sx, Sy,Sz (Top Left Vertex Position)
    // To get smooth rounded rectangle, 10 vertices are generated for each rounded corner 

    float Sx = 0.0;
    float Sy = 0.0;
    float verCz = Sz = 0.0;

    float rad;

    if (fWidth > fHeight)
    {
        rad = 0.3f * (fHeight/fWidth);
    }
    else 
    {
        rad = 0.3f * (fWidth/fHeight);
    }

    float invWidth    = 1.0/fWidth ;
    float invHeight   = 1.0/fHeight;
    float radbywidth  = rad * invWidth;
    float radbyheight = rad * invHeight;

    float texCx   = (Sx + fWidth - rad) * invWidth;
    float texCy   = (Sy - rad)          * invHeight; 

    //0 to 9 vertices
    for (i = 0; i <= 90; i = i + 10)
    {
        vertices[iVertCnt++]  = (Sx + fWidth - rad) + (cos(degreesToRadians(i)) * rad); //centre point-X + r*cos
        vertices[iVertCnt++]  = (Sy - rad)          + (sin(degreesToRadians(i)) * rad); //centre point-Y + r*sin
        vertices[iVertCnt++]  = verCz;

        texcoord_RndRect [tex++]  = texCx + (cos(degreesToRadians(i)) * radbywidth); 
        texcoord_RndRect [tex++]  = texCy + (sin(degreesToRadians(i)) * radbyheight); 
    }

    GLfloat vert1[] =
    {
        (Sx + rad),   Sy       , 0.0f,  // 10
        (Sx + rad),   (Sy -rad), 0.0f,  // 11 
    };

    for (i = 0; i < 6; i = i+3)
    {
        vertices[iVertCnt++]        =  vert1[i];
        vertices[iVertCnt++]        =  vert1[i+1];
        vertices[iVertCnt++]        =  vert1[i+2];
        texcoord_RndRect [tex++]    =  vert1[i]   * invWidth;
        texcoord_RndRect [tex++]    =  vert1[i+1] * invHeight;
    }

    texCx   =  (Sx + rad) * invWidth;
    texCy   =  (Sy - rad) * invHeight; 
    ////12 to 21 vertices
    for (i = 90; i <= 180; i = i + 10)   
    {
        vertices[iVertCnt++]  = (Sx + rad) + (cos(degreesToRadians(i)) * rad); //centre point-X + r*cos
        vertices[iVertCnt++]  = (Sy - rad) + (sin(degreesToRadians(i)) * rad); //centre point-Y + r*sin
        vertices[iVertCnt++]  = verCz;

        texcoord_RndRect [tex++]  = texCx +(cos(degreesToRadians(i)) * radbywidth);  // texture will be from 0 to 1 only
        texcoord_RndRect [tex++]  = texCy +(sin(degreesToRadians(i)) * radbyheight); 
    }

    GLfloat vert2[] =
    {
        (Sx)        , (Sy - fHeight + rad),  0.0f,  // 22 
        (Sx + rad ),  (Sy - fHeight + rad),  0.0f,  // 23 
    };

    for (i = 0; i < 6; i = i+3)
    {
        vertices[iVertCnt++]        =  vert2[i];
        vertices[iVertCnt++]        =  vert2[i+1];
        vertices[iVertCnt++]        =  vert2[i+2];
        texcoord_RndRect [tex++]    =  vert2[i]   * invWidth;
        texcoord_RndRect [tex++]    =  vert2[i+1] * invHeight;
    }


    texCx   = (Sx + rad )          * invWidth;
    texCy   = (Sy - fHeight + rad)  * invHeight;
    ////24 to 33 vertices
    for (i = 180; i <= 270; i = i + 10) 
    {
        vertices[iVertCnt++]  = (Sx + rad )         + (cos(degreesToRadians(i)) * rad); //centre point-X + r*cos
        vertices[iVertCnt++]  = (Sy - fHeight + rad) + (sin(degreesToRadians(i)) * rad); //centre point-Y + r*sin
        vertices[iVertCnt++]  = verCz;

        texcoord_RndRect [tex++]  = texCx +(cos(degreesToRadians(i)) * radbywidth);  
        texcoord_RndRect [tex++]  = texCy +(sin(degreesToRadians(i)) * radbyheight); 
    }

    GLfloat vert3[] =
    {
        (Sx + fWidth - rad),   (Sy - fHeight)       ,  0.0f,    // 34
        (Sx + fWidth - rad),   (Sy - fHeight + rad) ,  0.0f,    // 35
    };

    for (i = 0; i < 6; i = i+3)
    {
        vertices[iVertCnt++]        =  vert3[i];
        vertices[iVertCnt++]        =  vert3[i+1];
        vertices[iVertCnt++]        =  vert3[i+2];
        texcoord_RndRect [tex++]    =  vert3[i]   * invWidth;
        texcoord_RndRect [tex++]    =  vert3[i+1] * invHeight;
    }

    //36th vertices
    vertices[iVertCnt++]  = (Sx + fWidth - rad);
    vertices[iVertCnt++]  = (Sy - fHeight + rad);
    vertices[iVertCnt++]  = 0.0f;

    texcoord_RndRect [tex++]  = (Sx + fWidth - rad) * invWidth;  // 11
    texcoord_RndRect [tex++]  = (Sy - fHeight + rad)* invHeight;

    texCx   = (Sx + fWidth - rad) * invWidth;
    texCy   = (Sy - fHeight + rad) *invHeight ; 

    ////37 to 46 to  vertices
    for (i = 270; i <= 360; i = i + 10) 
    {
        vertices[iVertCnt++]  = (Sx + fWidth - rad)  + (cos(degreesToRadians(i)) * rad); //centre point-X + r*cos
        vertices[iVertCnt++]  = (Sy - fHeight + rad) + (sin(degreesToRadians(i)) * rad); //centre point-Y + r*sin
        vertices[iVertCnt++]  = 0.0f;

        texcoord_RndRect [tex++]  = texCx +(cos(degreesToRadians(i))  * radbywidth);  
        texcoord_RndRect [tex++]  = texCy +(sin(degreesToRadians(i))  * radbyheight); 
    }

    GLfloat vert4[] =
    {
        (Sx + fWidth )      ,    (Sy - rad),  0.0f, // 47 
        (Sx + fWidth - rad) ,    (Sy -rad ),  0.0f, // 48 

    };

    for (i = 0; i < 6; i = i+3)
    {
        vertices[iVertCnt++]        =  vert4[i];
        vertices[iVertCnt++]        =  vert4[i+1];
        vertices[iVertCnt++]        =  vert4[i+2];
        texcoord_RndRect [tex++]    =  vert4[i]   * invWidth;
        texcoord_RndRect [tex++]    =  vert4[i+1] * invHeight;
    }

            // Display
    ///////////////////////////////////////
    GLushort indices_topright[] = 
    {   
        0,1,2,3,4,5,6,7,8,9,10,11
    };

    GLushort indices_topleft[] = 
    {   
        12,13,14,15,16,17,18,19,20,21,22,23
    };

    GLushort indices_bottomleft[] = 
    {   
        24,25,26,27,28,29,30,31,32,33,34,35
    };

    GLushort indices_bottomright[] = 
    {   
        36,37,38,39,40,41,42,43,44,45,46,47,48,11,23
    };
    glDrawElements(GL_TRIANGLE_FAN, (sizeof(indices_topright)/sizeof(indices_topright[0])), GL_UNSIGNED_SHORT, indices_topright);
    glDrawElements(GL_TRIANGLE_FAN, (sizeof(indices_topleft)/sizeof(indices_topleft[0])), GL_UNSIGNED_SHORT, indices_topleft);
    glDrawElements(GL_TRIANGLE_FAN, (sizeof(indices_bottomleft)/sizeof(indices_bottomleft[0])), GL_UNSIGNED_SHORT, indices_bottomleft);
    glDrawElements(GL_TRIANGLE_FAN, (sizeof(indices_bottomright)/sizeof(indices_bottomright[0])), GL_UNSIGNED_SHORT, indices_bottomright);
    ////////////////////////

此代码适用于我。