在openGL中绘制可变宽度的线(无glLineWidth)

时间:2020-03-06 14:25:51  来源:igfitidea点击:

不使用glLineWidth绘制可变宽度线的最佳方法是什么?
只是画一个矩形?
各种平行线?
以上都不是?

解决方案

我们可以绘制两个三角形:

// Draws a line between (x1,y1) - (x2,y2) with a start thickness of t1 and
// end thickness t2.
void DrawLine(float x1, float y1, float x2, float y2, float t1, float t2)
{
    float angle = atan2(y2 - y1, x2 - x1);
    float t2sina1 = t1 / 2 * sin(angle);
    float t2cosa1 = t1 / 2 * cos(angle);
    float t2sina2 = t2 / 2 * sin(angle);
    float t2cosa2 = t2 / 2 * cos(angle);

    glBegin(GL_TRIANGLES);
    glVertex2f(x1 + t2sina1, y1 - t2cosa1);
    glVertex2f(x2 + t2sina2, y2 - t2cosa2);
    glVertex2f(x2 - t2sina2, y2 + t2cosa2);
    glVertex2f(x2 - t2sina2, y2 + t2cosa2);
    glVertex2f(x1 - t2sina1, y1 + t2cosa1);
    glVertex2f(x1 + t2sina1, y1 - t2cosa1);
    glEnd();
}

矩形(即GL_QUAD或者两个GL_TRIANGLES)听起来像是我们最好的选择,但不确定我能想到其他方法。

假设原始点是(x1,y1)->(x2,y2)。使用以下点(x1-width / 2,y1),(x1 + width / 2,y1),(x2-width / 2,y2),(x2 + width / 2,y2)构造一个矩形然后使用四边形/三边形来绘制它。这是简单的天真方式。请注意,对于较大的线宽,我们将获得奇怪的端点行为。然后,我们真正想做的就是使用矢量数学进行一些智能的平行线计算(应该没那么糟)。由于某种原因,点/叉积和矢量投影浮现在脑海。

好的,这是怎么回事:(Ozgar)

A
      / \
     /      \
    . p1        \
   /                \
  /                    D
 B -                 .p2
      -   -    -    C

所以AB是width1,CD是width2

然后,

// find line between p1 and p2
Vector p1p2 = p2 - p1 ;

// find a perpendicular
Vector perp = p1p2.perpendicular().normalize()

// Walk from p1 to A
Vector A = p1 + perp*(width1/2)
Vector B = p1 - perp*(width1/2)

Vector C = p2 - perp*(width2/2)
Vector D = p2 - perp*(width2/2)

// wind triangles
Triangle( A, B, D )
Triangle( B, D, C )

请注意,此算法可能存在CW / CCW绕组问题-如果在上图中将perp计算为(-y,x),则它将是CCW绕组,如果(y,-x)则将是CW绕组。

这样做的另一种方法是,如果我们偶然编写软件光栅化程序,则是在像素着色阶段使用重心坐标,并在其中一个重心坐标接近0时对像素进行着色。线会。

我今天早些时候不得不做同样的事情。

要创建跨越给定width的((x1,y1)->(x2,y2)的线,一种非常简单的方法是变换一个简单的单位大小的正方形,跨度为((0.,-0.5)- >(1.,0.5)使用:

  • glTranslatef(...)将其移动到所需的(x1,y1)位置;
  • glScalef(...)将其缩放到正确的长度和所需的宽度:使用length = sqrt((x2-x1)^ 2 +(y2-y1)^ 2)或者其他任意低-复杂度近似;
  • 将glRotatef(...)调整为正确的角度:使用角度= atan2(y2-y1,x2-x1)。

单位平方非常简单地由两个三角形的条形GL_TRIANGLE_STRIP创建,经过上述转换后变成实线。

这里的负担主要放在OpenGL(和图形硬件)上,而不是应用程序代码上。通过围绕" glPushMatrix()"和" glPopMatrix()"调用,可以很容易地将上述过程转换为通用函数。