Rol*_*iga 9 c# graphics xna bezier hlsl
几天前,我开始研究有效绘制bezier曲线,我遇到了Charles Loop和Jim Blinn开发的这种方法,看起来非常有趣.然而,经过大量的算法实验,我似乎无法让它能够渲染三次曲线.Quadratics很好,没问题.
我到目前为止找到的唯一资源如下:
为了快速启动和运行测试,我在XNA中这样做.基本上我将纹理坐标与我的顶点一起传递给GPU,应用透视变换并使用像素着色器中所有文章中提到的公式来渲染最终结果.然而,问题(我认为)在于如何计算纹理坐标.检查此代码:
public void Update()
{
float a1 = Vector3.Dot(p1, Vector3.Cross(p4, p3));
float a2 = Vector3.Dot(p2, Vector3.Cross(p1, p4));
float a3 = Vector3.Dot(p3, Vector3.Cross(p2, p2));
float d1 = a1 - 2 * a2 + 3 * a3;
float d2 = -a2 + 3 * a3;
float d3 = 3 * a3;
float discr = d1 * d1 * (3 * d2 * d2 - 4 * d1 * d3);
if (discr > 0)
{
Type = CurveTypes.Serpentine;
float ls = 3 * d2 - (float)Math.Sqrt(9 * d2 * d2 - 12 * d1 * d3);
float lt = 6 * d1;
float ms = 3 * d2 + (float)Math.Sqrt(9 * d2 * d2 - 12 * d1 * d3);
float mt = 6 * d1;
TexCoord1 = new Vector3(ls * ms, (float)Math.Pow(ls, 3), (float)Math.Pow(ms, 3));
TexCoord2 = new Vector3((3 * ls * ms - ls * mt - lt * ms) / 3, ls * ls * (ls - lt), ms * ms * (ms - mt));
TexCoord3 = new Vector3((lt * (mt - 2 * ms) + ls * (3 * ms - 2 * mt)) / 3, (float)Math.Pow(lt - ls, 2) * ls, (float)Math.Pow(mt - ms, 2) * ms);
TexCoord4 = new Vector3((lt - ls) * (mt - ms), -(float)Math.Pow(lt - ls, 3), -(float)Math.Pow(mt - ms, 3));
}
else if (discr == 0)
{
Type = CurveTypes.Cusp;
}
else if (discr < 0)
{
Type = CurveTypes.Loop;
}
}
Run Code Online (Sandbox Code Playgroud)
请原谅一塌糊涂,这只是一些测试代码.p1 ... p4是世界空间中的控制点,TexCoord1 ... TexCoord4是相应的纹理坐标.这是GPU Gems文章中所述内容的复制.
这里有一些问题,首先在计算a3时,我们对两个参数都使用p2,这当然总是得到一个(0,0,0)向量,并且取这个和p3的点积将总是给出0.那没用,所以为什么他们会在文章中提到这一点?
这当然会使判别错误,我们甚至无法确定它是什么类型的曲线.
在摆弄了一段时间之后,我决定尝试完成他们在Loop和Blinn论文中所做的工作.从那我得到这样的东西:
public void Update()
{
Matrix m1 = new Matrix(
p4.X, p4.Y, 1, 0,
p3.X, p3.Y, 1, 0,
p2.X, p2.Y, 1, 0,
0, 0, 0, 1);
Matrix m2 = new Matrix(
p4.X, p4.Y, 1, 0,
p3.X, p3.Y, 1, 0,
p1.X, p1.Y, 1, 0,
0, 0, 0, 1);
Matrix m3 = new Matrix(
p4.X, p4.Y, 1, 0,
p2.X, p2.Y, 1, 0,
p1.X, p1.Y, 1, 0,
0, 0, 0, 1);
Matrix m4 = new Matrix(
p3.X, p3.Y, 1, 0,
p2.X, p2.Y, 1, 0,
p1.X, p1.Y, 1, 0,
0, 0, 0, 1);
float det1 = m1.Determinant();
float det2 = -m2.Determinant();
float det3 = m3.Determinant();
float det4 = -m4.Determinant();
float tet1 = det1 * det3 - det2 * det2;
float tet2 = det2 * det3 - det1 * det4;
float tet3 = det2 * det4 - det3 * det3;
float discr = 4 * tet1 * tet3 - tet2 * tet2;
if (discr > 0)
{
Type = CurveTypes.Serpentine;
float ls = 2 * det2;
float lt = det3 + (float)((1 / Math.Sqrt(3)) * Math.Sqrt(3 * det3 * det3 - 4 * det2 * det4));
float ms = 2 * det2;
float mt = det3 - (float)((1 / Math.Sqrt(3)) * Math.Sqrt(3 * det3 * det3 - 4 * det2 * det4));
TexCoord1 = new Vector3(lt * mt, (float)Math.Pow(lt, 3), (float)Math.Pow(mt, 3));
TexCoord2 = new Vector3(-ms * lt - ls * mt, -3 * ls * lt * lt, -3 * ms * mt * mt);
TexCoord3 = new Vector3(ls * ms, 3 * ls * ls * lt, 3 * ms * ms * mt);
TexCoord4 = new Vector3(0, -ls * ls * ls, -ms * ms * ms);
}
else if (discr == 0)
{
Type = CurveTypes.Cusp;
}
else if (discr < 0)
{
Type = CurveTypes.Loop;
}
}
Run Code Online (Sandbox Code Playgroud)
猜猜看,那也不起作用.然而,歧视似乎现在至少更加正确.至少它具有正确的符号,并且当控制点被布置为形成尖点时它为零.我仍然得到相同的视觉效果,除了曲线随机消失一段时间(像素着色器公式总是大于零)并在我将控制点移回更多的方形后返回.这里是像素着色器代码:
PixelToFrame PixelShader(VertexToPixel PSIn)
{
PixelToFrame Output = (PixelToFrame)0;
if(pow(PSIn.TexCoords.x, 3) - PSIn.TexCoords.y * PSIn.TexCoords.z > 0)
{
Output.Color = float4(0,0,0,0.1);
}
else
{
Output.Color = float4(0,1,0,1);
}
return Output;
}
Run Code Online (Sandbox Code Playgroud)
这是我现在能想到的所有有用信息.有谁知道发生了什么事?因为我已经没用了.
小智 7
我正在查看纸张和你的代码,它接缝你错过了乘以M3矩阵.
在将p1,p2,p3和p4坐标用于计算行列式之前,应将其放置在矩阵中并乘以M3矩阵.例如.
Matrix M3 = Matrix(
1, 0, 0, 0,
-3, 3, 0, 0,
3, -6, 3, 0,
-1, 3, -3, 1);
Matrix B = Matrix(
p1.X, p1.Y, 0, 1,
p2.X, p2.Y, 0, 1,
p3.X, p3.Y, 0, 1,
p4.X, p4.Y, 0, 1);
Matrix C = M3*B;
Run Code Online (Sandbox Code Playgroud)
然后使用C矩阵的每一行作为代码中m1到m4矩阵的坐标.其中行的第一个和第二个值是x,y坐标,最后一个是w坐标.
最后,纹理坐标矩阵需要通过M3的逆矩阵进行多次处理.
Matrix invM3 = Matrix(
1, 0, 0, 0,
1, 0.3333333, 0, 0,
1, 0.6666667, 0.333333, 0,
1, 1, 1, 1);
Matrix F = Matrix(
TexCoord1,
TexCoord2,
TexCoord3,
TexCoord4);
Matrix result = invM3*F;
Run Code Online (Sandbox Code Playgroud)
结果矩阵的每一行对应着色器所需的纹理坐标.
我自己还没有实现它,所以不能保证它会解决你的问题.在阅读完论文后,我注意到你的实现中遗漏了这些内容.
我希望这有帮助,如果我错了请告诉我因为我很快会尝试这个.
| 归档时间: |
|
| 查看次数: |
2135 次 |
| 最近记录: |