我的任务是通过Stage3d(Adobe Flash)技术渲染二次贝塞尔曲线(路径),该技术没有开箱即用的任何扩展(而OpenGl拥有它,据我所知)。是的,有一个Starling-Extension-Graphics,但是它使用简单的方法将曲线段划分为许多直线,这为我的长曲线路径生成了很多三角形。
所以......有一种完美的方法可以渲染Loop和Blinn的分辨率独立形状。我读过GPUGems3文章(gpugems3_ch25.html) 并将该片段着色器移植到AGAL2:
二次曲线像素着色器
float4 QuadraticPS(float2 p : TEXCOORD0,
float4 color : COLOR0) : COLOR
{
// Gradients
float2 px = ddx(p);
float2 py = ddy(p);
// Chain rule
float fx = (2*p.x)*px.x - px.y;
float fy = (2*p.x)*py.x - py.y;
// Signed distance
float sd = (p.x*p.x - p.y)/sqrt(fx*fx + fy*fy);
// Linear alpha
float alpha = thickness - abs(sd);
if (alpha > 1) // Inside
color.a = 1;
else if (alpha < 0) // Outside
clip(-1);
else
// Near boundary
color.a = alpha;
return color;
}
有效。但是有两个基本问题:
我不明白那个算法:(。我读过有关签名的距离场,衍生物和其他...我想了很多时间再读一遍 - 但没有结果!我的问题是:是否有人帮助我并解释该着色器中发生的事情(如果可能的话,逐行(!))?
第二个问题是曲线在三角形的角落被剪裁并且厚度可变。请看图片: https://monosnap.com/file/84EBOuQ1czNM5lprQ5VlnRUKP2mKmW 因此,如果我绘制路径,它看起来像这样:https://monosnap.com/file/54Zs5Xui6s3BL6lNdZRCx9ibcV2bCF
我喜欢这种方法,每个曲线段使用一个三角形,因为不需要任何几何体。而且我不需要非常粗的曲线(1-2 px非常好),但是厚度可变是一个问题。有人能帮助我吗?
(抱歉我的英文。这不是我的母语。)
[Spektre编辑1] 刚刚从评论和无效答案中移出
我计划每个曲线段使用一个三角形,类似于图片
答案 0 :(得分:7)
对于3个控制点贝塞尔曲线,我会:
放大控制点以包括曲线周围的区域以避免伪影
这种方式很快,从A',B',C'
计算A,B,C
没有问题,反之亦然。如果比例是常数(例如scale=1.25
),那么最大可用曲线thickness<=2.0*min(|control_point-M|)*(scale-1.0)
。
为了更安全地放大,您可以计算所需的精确比例(例如在几何着色器中)并将其传递给顶点和片段......以上所有都可以通过几何着色器完成。您应该使用透明度将曲线正确连接在一起。平均中间点应保持不变M=A+B+C=A'+B'+C'
如果透明度不是选项
然后你需要改变方法,以便在纹理内传递控制点和位置。
使用控制点创建一个2D float
纹理
float pnt[9][N]
pnt[0,1,2][]
是控制点A(x,y,z)
pnt[3,4,5][]
是控制点B(x,y,z)
pnt[6,7,8][]
是控制点C(x,y,z)
还可以创建一维颜色纹理
rgba col[N]
x
轴分辨率= N
是贝塞尔曲线的数量现在绘制单个Quad覆盖整个屏幕
在片段着色器中检查像素是否在任何曲线内。如果是,则输出其颜色......
对于高贝塞尔曲线计数N
[edit1]几乎共线的控制点
对于那些我会使用Quads
的人
D,E
是A,B
C
D=C+C-A
E=C+C-B
C
是中间点M = (A+B+D+E)/4 = C = (A'+B'+C'+D')/4
A',B',C',D'
是放大的A,B,D,E
控制点A'=C+(A -C)*scale
B'=C+(B -C)*scale
A =C+(A'-C)/scale
B =C+(B'-C)/scale
这可以用于任何Bezier,而不仅仅是几乎共线,但它使用更大的多边形,因此性能会更慢(然后真正需要更多碎片)