OpenGL:使用 TriangleList 绘制非常细的三角形变成点
OpenGL: Drawing very thin triangles with TriangleList turn into points
我正在使用 TriangleList 输出我的图元。大多数时候我都需要画矩形、三角形、圆形。有时我需要绘制非常细的三角形(例如 width=2px)。我认为它应该看起来像一条线(几乎是一条线)但它看起来像分开的点:)
下图显示了我在说什么:
左边的第一张图显示了如何绘制一个矩形(逆时针,从右上角开始)。然后你可以看到我称之为 "dx".
的矩形的 "width"
如何避免这种行为?我希望它看起来像一条直线(几乎是直线),而不是点:)
这是普遍的瘦三角问题。例如,在自适应细分中,当你有细小的 T 形接头时,它总是会发生。一种解决方案是绘制具有抗锯齿效果的边缘(您可以使用 GL_LINE_STRIP) 您可以:
Gl.glShadeModel(Gl.GL_SMOOTH);
Gl.glEnable(Gl.GL_LINE_SMOOTH);
Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_DONT_CARE);
在画线之前,这样当你的三角形很小的时候你就能得到线...
当几何形状小于单个像素时,这称为子像素特征。如果对非常细的三角形进行动画处理,您会看到像素突然进出。
尝试打开多重采样。大多数 GL 窗口库支持多重采样后台缓冲区。您也可以在图形驱动程序设置中强制启用它。
正如@BrettHale 所提到的,这是一个别名问题。例如,
没有super/multisampling,三角形只覆盖右下角像素的中心,只有它会接收颜色。真实像素有面积,在完美的情况下,会接收到与覆盖面积相等的一部分颜色。 "Antialiasing" 技术可减少 aliasing 因未跨像素集成颜色而造成的影响。
让它看起来正确而又不会非常慢是很难的。 OpenGL 提供 GL_POLYGON_SMOOTH
, which conservatively rasterizes triangles and draws the correct percentages of colour to each pixel using blending. This works well until you have overlapping triangles and you hit the problem of transparency sorting where order-independent transparency is needed. A simple and more brute force solution is to render to a much bigger texture and then downsample. This is essentially what supersampling does, except the samples can be "anisotropic" (irregular) which gives a nicer result. Multisampling techniques are adaptive and a bit more efficient, e.g. supersample pixels only at triangle edges. It is fairly straightforward to set this up with OpenGL.
然而,随着三角形面积接近零,该面积也会接近零,并且即使使用抗锯齿它仍然会完全消失(尽管会淡出而不是像素化)。虽然在物理上不正确,但您可能会在最小 1 像素宽度的三角形之后,这样即使它是一个非常细的三角形,您也可以获得您想要的线条。这就是您自己 conservative rasterization 可能感兴趣的地方。
如果三角形是由geometry shader生成的,那么可以让三角形区域动态化。
例如,您可以使三角形宽度始终大于 1px。
// ndc coord is range from -1.0 to 1.0 and the screen width is 1920.
float pixel_unit = 2.0 / 1920.0;
vec2 center = 0.5 * (triangle[0].xy + triangle[1].xy );
// Remember to divide the w component.
float triangle_width = (triangle[0].xy - center)/triangle[0].w;
float scale_ratio = pixel_unit / triangle_width;
if (scale_ratio > 1.0){
triagle[0].xy = (triangle[0].xy - center) * scale_ratio + center;
triagle[1].xy = (triangle[1].xy - center) * scale_ratio + center;
}
我正在使用 TriangleList 输出我的图元。大多数时候我都需要画矩形、三角形、圆形。有时我需要绘制非常细的三角形(例如 width=2px)。我认为它应该看起来像一条线(几乎是一条线)但它看起来像分开的点:)
下图显示了我在说什么:
左边的第一张图显示了如何绘制一个矩形(逆时针,从右上角开始)。然后你可以看到我称之为 "dx".
的矩形的 "width"如何避免这种行为?我希望它看起来像一条直线(几乎是直线),而不是点:)
这是普遍的瘦三角问题。例如,在自适应细分中,当你有细小的 T 形接头时,它总是会发生。一种解决方案是绘制具有抗锯齿效果的边缘(您可以使用 GL_LINE_STRIP) 您可以:
Gl.glShadeModel(Gl.GL_SMOOTH);
Gl.glEnable(Gl.GL_LINE_SMOOTH);
Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_DONT_CARE);
在画线之前,这样当你的三角形很小的时候你就能得到线...
当几何形状小于单个像素时,这称为子像素特征。如果对非常细的三角形进行动画处理,您会看到像素突然进出。
尝试打开多重采样。大多数 GL 窗口库支持多重采样后台缓冲区。您也可以在图形驱动程序设置中强制启用它。
正如@BrettHale 所提到的,这是一个别名问题。例如,
没有super/multisampling,三角形只覆盖右下角像素的中心,只有它会接收颜色。真实像素有面积,在完美的情况下,会接收到与覆盖面积相等的一部分颜色。 "Antialiasing" 技术可减少 aliasing 因未跨像素集成颜色而造成的影响。
让它看起来正确而又不会非常慢是很难的。 OpenGL 提供 GL_POLYGON_SMOOTH
, which conservatively rasterizes triangles and draws the correct percentages of colour to each pixel using blending. This works well until you have overlapping triangles and you hit the problem of transparency sorting where order-independent transparency is needed. A simple and more brute force solution is to render to a much bigger texture and then downsample. This is essentially what supersampling does, except the samples can be "anisotropic" (irregular) which gives a nicer result. Multisampling techniques are adaptive and a bit more efficient, e.g. supersample pixels only at triangle edges. It is fairly straightforward to set this up with OpenGL.
然而,随着三角形面积接近零,该面积也会接近零,并且即使使用抗锯齿它仍然会完全消失(尽管会淡出而不是像素化)。虽然在物理上不正确,但您可能会在最小 1 像素宽度的三角形之后,这样即使它是一个非常细的三角形,您也可以获得您想要的线条。这就是您自己 conservative rasterization 可能感兴趣的地方。
如果三角形是由geometry shader生成的,那么可以让三角形区域动态化。
例如,您可以使三角形宽度始终大于 1px。
// ndc coord is range from -1.0 to 1.0 and the screen width is 1920.
float pixel_unit = 2.0 / 1920.0;
vec2 center = 0.5 * (triangle[0].xy + triangle[1].xy );
// Remember to divide the w component.
float triangle_width = (triangle[0].xy - center)/triangle[0].w;
float scale_ratio = pixel_unit / triangle_width;
if (scale_ratio > 1.0){
triagle[0].xy = (triangle[0].xy - center) * scale_ratio + center;
triagle[1].xy = (triangle[1].xy - center) * scale_ratio + center;
}