Я хочу нарисовать прямоугольник с закругленными углами в OpenGLES, с помощью одного вызова glDraw.
Я также попробовал это. и поделился этим в ответе.
Надеюсь, это будет полезно.
Я попытался нарисовать прямоугольник с закругленными углами в OpenGLES с помощью одного вызова glDraw.
Ниже приведен фрагмент кода:
// -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 вершины для каждого закругленного угла.
Но можно увеличить его, чтобы получить больше плавности.
Но соответствующие изменения должны быть сделаны в массиве «индексы»
Много оптимизаций может быть сделано в этом коде.
Я изменил код, чтобы получить входные данные (TopLeft Corner Position, width и height) и динамически генерировать 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);
////////////////////////
Этот код работает для меня.