在openGL中绘制可变宽度的线(无glLineWidth)
不使用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()"调用,可以很容易地将上述过程转换为通用函数。