我一直在尝试在OpenGL中创建一个圆,但我不能使用三角形扇形,因为我已经知道它们在DirectX中不再可用,而我也将进行DirectX调用。
我真的不太理解三角形条带是如何工作的。我所有的实现都有洞或奇怪的问题,有人能帮我吗?如何以最佳方式实现它?
此外,在10个包含1000个三角形的圆中,使用三角形条带和单独的三角形是否真的有性能差异?这会产生很大的差别吗?
我一直在尝试在OpenGL中创建一个圆,但我不能使用三角形扇形,因为我已经知道它们在DirectX中不再可用,而我也将进行DirectX调用。
我真的不太理解三角形条带是如何工作的。我所有的实现都有洞或奇怪的问题,有人能帮我吗?如何以最佳方式实现它?
此外,在10个包含1000个三角形的圆中,使用三角形条带和单独的三角形是否真的有性能差异?这会产生很大的差别吗?
使用三角形带(triangle strip)来指定圆形的一种方法如下:
for each step
add next position on circle
add circle center
add left most vertex
for each phi in (-PI/2, Pi/2) //ommit the first and last one
x = r * sin(phi)
y = r * cos(phi)
add (x, y)
add (x, -y)
add right most vertex
根据您的背面剔除设置,您可能需要调整循环。
不同拓扑结构需要不同数量的顶点。对于三角形列表,10个包含1000个三角形的圆需要30000个顶点。而对于三角形带,每个圆需要1002个顶点,因此总共需要10020个顶点。这几乎是三倍小,传输到CPU时应该会更快。如果这反映在FPS上取决于几个因素。
cos()
和一个sin()
调用。// Number of points used for half circle.
const unsigned HALF_PREC = 10;
const float angInc = M_PI / static_cast<float>(HALF_PREC);
const float cosInc = cos(angInc);
const float sinInc = sin(angInc);
GLfloat* coordA = new GLfloat[2 * HALF_PREC * 2];
unsigned coordIdx = 0;
coordA[coordIdx++] = 1.0f;
coordA[coordIdx++] = 0.0f;
float xc = 1.0f;
float yc = 0.0f;
for (unsigned iAng = 1; iAng < HALF_PREC; ++iAng) {
float xcNew = cosInc * xc - sinInc * yc;
yc = sinInc * xc + cosInc * yc;
xc = xcNew;
coordA[coordIdx++] = xc;
coordA[coordIdx++] = yc;
coordA[coordIdx++] = xc;
coordA[coordIdx++] = -yc;
}
coordA[coordIdx++] = -1.0f;
coordA[coordIdx++] = 0.0f;
GLuint vaoId = 0;
glGenVertexArrays(1, &vaoId);
glBindVertexArray(vaoId);
GLuint vboId = 0;
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, 2 * HALF_PREC * 2 * sizeof(GLfloat),
coordA, GL_STATIC_DRAW);
delete[] coordA;
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
绘制:
glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 2 * HALF_PREC);
glBindVertexArray(0);
for each phi in (-PI, Pi) //ommit the first and last one
x1 = r * sin(phi)
y1 = r * cos(phi)
x2 = r * sin(phi + Pi)
y2 = r * cos(phi + Pi)
add (x1, y1)
add (x2, y2)
与上述伪代码所示的在圆形的一侧来回移动不同,这个算法会在圆心来回移动,从而得到更完整的圆形。
sin(x + Pi)
与-sin(x)
相同。余弦也是如此。因此,您可以消除对x2和y2的正弦和余弦调用。 - Jack G