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

在openGL中绘制可变宽度线(无glLineWidth),opengl,Opengl,不使用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 ang

不使用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_四边形或两个GL_三角形)的声音听起来像是你的最佳选择,我不确定我能想出任何其他方法。

假设你的原始点是(x1,y1)->(x2,y2)。使用以下点(x1宽度/2,y1),(x1+宽度/2,y1),(x2宽度/2,y2),(x2+宽度/2,y2)构造矩形,然后使用四边形/三边形绘制它。这是一种简单天真的方式。请注意,对于大线宽,您将获得奇怪的端点行为。然后你真正想做的是使用向量数学进行一些智能的平行线计算(应该不会那么糟糕)。出于某种原因,我想到了点/叉积和向量投影。

好的,这个怎么样:(Ozgar)


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

另一种方法是,如果您碰巧编写了软件光栅化器,是在像素着色阶段使用重心坐标,并在其中一个重心坐标接近0时为像素着色。你的津贴越多,线就越粗。

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

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

  • glTranslatef(…)
    将其移动到所需的
    (x1,y1)
    位置
  • glScalef(…)
    将其向右缩放
    长度
    和所需的
    宽度
    :使用
    length=sqrt((x2-x1)^2+(y2-y1)^2)
    或任何其他低复杂度近似值
  • glRotatef(…)
    angle
    将其向右旋转:使用
    angle=atan2(y2-y1,x2-x1)
  • 单位正方形是由两个三角形条
    GL\u triangle\u strip
    创建的,经过上述变换后,它会变成实线


    这里的负担主要放在OpenGL(和图形硬件)上,而不是应用程序代码上。通过围绕
    glPushMatrix()
    glPopMatrix()
    调用,上述过程很容易变成一个通用函数。

    对于那些正在寻找解决方案的人来说,这段代码是使用LWJGL编写的,但可以很容易地适应OpenGL的任何实现

    import java.awt.Color;
    import org.lwjgl.opengl.GL11;
    import org.lwjgl.util.vector.Vector2f;
    public static void DrawThickLine(int startScreenX, int startScreenY, int endScreenX, int endScreenY, Color color, float alpha, float width) {
    
        Vector2f start = new Vector2f(startScreenX, startScreenY);
        Vector2f end = new Vector2f(endScreenX, endScreenY);
    
        float dx = startScreenX - endScreenX;
        float dy = startScreenY - endScreenY;
    
        Vector2f rightSide = new Vector2f(dy, -dx);
        if (rightSide.length() > 0) {
            rightSide.normalise();
            rightSide.scale(width / 2);
        }
        Vector2f leftSide = new Vector2f(-dy, dx);
        if (leftSide.length() > 0) {
            leftSide.normalise();
            leftSide.scale(width / 2);
        }
    
        Vector2f one = new Vector2f();
        Vector2f.add(leftSide, start, one);
    
        Vector2f two = new Vector2f();
        Vector2f.add(rightSide, start, two);
    
        Vector2f three = new Vector2f();
        Vector2f.add(rightSide, end, three);
    
        Vector2f four = new Vector2f();
        Vector2f.add(leftSide, end, four);
    
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), alpha);
        GL11.glVertex3f(one.x, one.y, 0);
        GL11.glVertex3f(two.x, two.y, 0);
        GL11.glVertex3f(three.x, three.y, 0);
        GL11.glVertex3f(four.x, four.y, 0);
        GL11.glColor4f(1, 1, 1, 1);
        GL11.glEnd();
    }
    

    这太复杂了!太多不需要的三角函数。结果证明这不是OP想要的(见下面他的答案)。但如果你愿意分享的话,我希望看到一个更简单的算法。我在这里添加了一个无trig的版本now@Ozgur”“我的回答好多了。考虑添加你正在谈论的向量数学。这对水平线也不起作用(当x1==x2)
    // 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 )
    
    import java.awt.Color;
    import org.lwjgl.opengl.GL11;
    import org.lwjgl.util.vector.Vector2f;
    public static void DrawThickLine(int startScreenX, int startScreenY, int endScreenX, int endScreenY, Color color, float alpha, float width) {
    
        Vector2f start = new Vector2f(startScreenX, startScreenY);
        Vector2f end = new Vector2f(endScreenX, endScreenY);
    
        float dx = startScreenX - endScreenX;
        float dy = startScreenY - endScreenY;
    
        Vector2f rightSide = new Vector2f(dy, -dx);
        if (rightSide.length() > 0) {
            rightSide.normalise();
            rightSide.scale(width / 2);
        }
        Vector2f leftSide = new Vector2f(-dy, dx);
        if (leftSide.length() > 0) {
            leftSide.normalise();
            leftSide.scale(width / 2);
        }
    
        Vector2f one = new Vector2f();
        Vector2f.add(leftSide, start, one);
    
        Vector2f two = new Vector2f();
        Vector2f.add(rightSide, start, two);
    
        Vector2f three = new Vector2f();
        Vector2f.add(rightSide, end, three);
    
        Vector2f four = new Vector2f();
        Vector2f.add(leftSide, end, four);
    
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glColor4f(color.getRed(), color.getGreen(), color.getBlue(), alpha);
        GL11.glVertex3f(one.x, one.y, 0);
        GL11.glVertex3f(two.x, two.y, 0);
        GL11.glVertex3f(three.x, three.y, 0);
        GL11.glVertex3f(four.x, four.y, 0);
        GL11.glColor4f(1, 1, 1, 1);
        GL11.glEnd();
    }