圆形带三角形条纹

3

我一直在尝试在OpenGL中创建一个圆,但我不能使用三角形扇形,因为我已经知道它们在DirectX中不再可用,而我也将进行DirectX调用。

我真的不太理解三角形条带是如何工作的。我所有的实现都有洞或奇怪的问题,有人能帮我吗?如何以最佳方式实现它?

此外,在10个包含1000个三角形的圆中,使用三角形条带和单独的三角形是否真的有性能差异?这会产生很大的差别吗?


你应该指定你要针对哪个版本的Direct3D。 - Sion Sheevok
@sion sheevok,我想问如何使用三角带在OpenGL中绘制填充圆形。 - Etherealone
你还有一个DirectX标签,你只针对OpenGL吗?如果是这样,请移除DirectX标签。 - Sion Sheevok
3个回答

6

使用三角形带(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上取决于几个因素。


不错。第二种方法比三角形扇形少一个顶点。 :-) - yoyo

3
这里是使用VAO/VBO的代码,所需点数最少。与目前为止发布的其他答案不同,它只需要一个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);

2
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接