如何在Blinn / Loop的分辨率独立曲线渲染中解决渲染神器? [英] How to Solve Rendering Artifact in Blinn/Loop's Resolution Independent Curve Rendering?

查看:173
本文介绍了如何在Blinn / Loop的分辨率独立曲线渲染中解决渲染神器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在实现Blinn / Loop的曲线渲染算法时,我意识到在循环曲线类型上有一个特殊情况。正如他们的论文(第4.4小节,第6-7),他们说曲线应该分成两部分,但我真的很困惑如何获得交点。

这是我的渲染结果:



如果 td / sd te / se 位于值[0,1]之间,则会出现此伪像。



我的源代码:

  ... 

case CURVE_TYPE_LOOP:

td = d2 + sqrt(4.0 * d1 * d3 - 3.0 * d2 * d2);
sd = 2.0 * d1;

te = d2 - sqrt(4.0 * d1 * d3 - 3.0 * d2 * d2);
se = 2.0 * d1; ((td / sd> 0.0& td / sd< 1.0)||(te / se> 0.0& te / se< 1.0))

b $ b std :: cout<< error\\\
;

// F矩阵将与逆M3相乘以获得tex坐标(我使用Eigen库btw ...)
F<< td * te,td * td * te,td * te * te,1,
(-se * td) - (se * te),(-se * td * td) - (2.0 * sd * te * td),( - sd * te * te) - (2.0 * se * td * te),0,
sd * se,te * sd * sd + 2.0 * se * td * sd,td * se * se + 2 * sd * te * se,0,
0,-sd * sd * se,-sd * se * se,0;

break;

...


解决方案

解决它,

我应该得到分裂值t,



这是我的代码:

  //得到t 
double splitLoop = -1.0;

switch(curve_type)
{

case CURVE_TYPE_UNKNOWN:
break;

case CURVE_TYPE_SERPENTINE:

tl = d2 +((1.0 / sqrt(3.0))* sqrt(3.0 * d2 * d2 - 4.0 * d1 * d3));
sl = 2.0 * d1; ((1.0 / sqrt(3.0))* sqrt(3.0 * d2 * d2-4.0 * d1 * d3));
sm = 2.0 * d1;

F<< (t * tm),tl * tl * tl,tm * tm * tm,1,
- sm * tm * tm),0,
sl * sm,3.0 * sl * sl * tl,3.0 * sm * sm * tm,0,
0, - (sl * sl * sl), - (sm * sm * sm),0;

break;

case CURVE_TYPE_LOOP:

td = d2 + sqrt(4.0 * d1 * d3 - 3.0 * d2 * d2);
sd = 2.0 * d1;

te = d2 - sqrt(4.0 * d1 * d3 - 3.0 * d2 * d2);
se = 2.0 * d1; ((td / sd)> 0.0&&(td / sd)< 1.0)
{
splitLoop(

//获得分割t
) = td / sd; ((te / se)> 0.0&&(te / se)< 1.0)
{
splitLoop = te / se;
}
}

F<< td * te,td * td * te,td * te * te,1,
(-se * td) - (se * te),(-se * td * td) - (2.0 * sd * te * td),( - sd * te * te) - (2.0 * se * td * te),0,
sd * se,te * sd * sd + 2.0 * se * td * sd,td * se * se + 2 * sd * te * se,0,
0,-sd * sd * se,-sd * se * se,0;

break;

案例CURVE_TYPE_QUADRATIC:
break;

case CURVE_TYPE_LINE:
break;


$ b if(splitLoop> 0.0& split&Loop< 1.0)
{
// SPLIT
double x01 =(x1-x0)* splitLoop + x0;
double y01 =(y1 - y0)* splitLoop + y0;

double x12 =(x2 - x1)* splitLoop + x1;
double y12 =(y2 - y1)* splitLoop + y1;

double x23 =(x3 - x2)* splitLoop + x2;
double y23 =(y3 - y2)* splitLoop + y2;

double x012 =(x12 - x01)* splitLoop + x01;
double y012 =(y12 - y01)* splitLoop + y01;

double x123 =(x23 - x12)* splitLoop + x12;
double y123 =(y23 - y12)* splitLoop + y12;

double x0123 =(x123 - x012)* splitLoop + x012;
double y0123 =(y123 - y012)* splitLoop + y012;

// CURVE A(递归)
DrawCubic(x0,y0,x01,y01,x012,y012,x0123,y0123);

// CURVE B(递归)
DrawCubic(x0123,y0123,x123,y123,x23,y23,x3,y3);
}
else
{
//和平照...

}

==编辑==



在我再次尝试一段时间之后,我的程序出现数字错误当子曲线上的 td / sd te / se 的值再次位于[0,1 ] ,因为我的程序使用递归调用 DrawCubic(),它会导致递归堆错误。 在此期间,我使用'hack'解决方案,我不会在递归调用中调用 DrawCurve() (确保递归只被调用一次)。到目前为止,结果非常令人满意,我没有看到任何神器。



任何反馈都非常受欢迎,因为我不擅长数值计算: p>


In implementing Blinn/Loop's algorithm on curve rendering, I realize there is a special case on Loop Curve Type. As described in their paper (subsection 4.4, page 6-7), they said the curve should be divided into two but I'm really confused how to obtain the intersection point.

Here's my rendering result:

As stated in the paper, this artifact occurs when either td/sd or te/se lie in between value [0, 1].

My source code:

    ...

case CURVE_TYPE_LOOP:

    td = d2 + sqrt(4.0 * d1 * d3 - 3.0 * d2 *d2);
    sd = 2.0 * d1;

    te = d2 - sqrt(4.0 * d1 * d3 - 3.0 * d2 * d2);
    se = 2.0 * d1;

    if((td / sd > 0.0 && td/ sd < 1.0) || (te / se > 0.0 && te/ se < 1.0))
        std::cout << "error\n";

    // F matrix will be multiplied with inverse M3 to obtain tex coords (I use Eigen library btw...)
    F << td * te,                   td * td * te,                               td * te * te,                           1,      
         (-se * td) - (se * te),    (-se * td * td) - (2.0 * sd * te * td),     (-sd * te * te) - (2.0 * se * td * te), 0,
         sd * se,                   te * sd * sd + 2.0 * se * td* sd,           td * se * se + 2 * sd * te * se,        0,
         0,                         -sd * sd * se,                              -sd * se * se,                          0;

    break;

...

解决方案

Solved it,

I should get the splitting value t,

here's my code:

// get t
double splitLoop = -1.0;

switch (curve_type)
{

case CURVE_TYPE_UNKNOWN:
    break;

case CURVE_TYPE_SERPENTINE:

    tl = d2 + ((1.0 / sqrt(3.0)) * sqrt(3.0 * d2 * d2 - 4.0 * d1 * d3));
    sl = 2.0 * d1;

    tm = d2 - ((1.0 / sqrt(3.0)) * sqrt(3.0 * d2 * d2 - 4.0 * d1 * d3));
    sm = 2.0 * d1;

    F << tl * tm,                   tl * tl * tl,           tm * tm * tm,           1,
        -(sm * tl) -(sl * tm),      -(3.0 * sl * tl * tl),  -(3.0 * sm * tm * tm),  0,
        sl * sm,                    3.0 * sl * sl * tl,     3.0 * sm * sm *  tm,    0,
        0,                          -(sl * sl * sl),        -(sm * sm * sm),        0;  

    break;

case CURVE_TYPE_LOOP:

    td = d2 + sqrt(4.0 * d1 * d3 - 3.0 * d2 *d2);
    sd = 2.0 * d1;

    te = d2 - sqrt(4.0 * d1 * d3 - 3.0 * d2 * d2);
    se = 2.0 * d1;

    // Get splitting t
    if((td / sd) > 0.0 && (td / sd) < 1.0)
    {
        splitLoop = td / sd;
    }
    else if((te / se) > 0.0 && (te/ se) < 1.0)
    {
        splitLoop = te / se;
    }

    F << td * te,                   td * td * te,                               td * te * te,                           1,      
            (-se * td) - (se * te), (-se * td * td) - (2.0 * sd * te * td),     (-sd * te * te) - (2.0 * se * td * te), 0,
            sd * se,                te * sd * sd + 2.0 * se * td* sd,           td * se * se + 2 * sd * te * se,        0,
            0,                      -sd * sd * se,                              -sd * se * se,                          0;

    break;

case CURVE_TYPE_QUADRATIC:
    break;

case CURVE_TYPE_LINE:
    break;

}

if(splitLoop > 0.0 && splitLoop < 1.0)
{
    // SPLIT
    double x01 = (x1 - x0) * splitLoop + x0;
    double y01 = (y1 - y0) * splitLoop + y0;

    double x12 = (x2 - x1) * splitLoop + x1;
    double y12 = (y2 - y1) * splitLoop + y1;

    double x23 = (x3 - x2) * splitLoop + x2;
    double y23 = (y3 - y2) * splitLoop + y2;

    double x012 = (x12 - x01) * splitLoop + x01;
    double y012 = (y12 - y01) * splitLoop + y01;

    double x123 = (x23 - x12) * splitLoop + x12;
    double y123 = (y23 - y12) * splitLoop + y12;

    double x0123 = (x123 - x012) * splitLoop + x012;
    double y0123 = (y123 - y012) * splitLoop + y012;

    // CURVE A (recursive)
    DrawCubic(x0, y0, x01, y01, x012, y012, x0123, y0123);

    // CURVE B (recursive)
    DrawCubic(x0123,  y0123, x123, y123, x23, y23, x3, y3);
}
else
{
    // Draw as usual...

}

== EDIT ==

After i experimented again for a while, There's a numerical error on my program when the values of td/sd or te/se on subcurves lie again in between [0, 1], since my program use recursive by calling DrawCubic(), it causes recursive heap error.

In the meantime, I use 'hack' solution where I will not call DrawCurve() inside the recursive call (making sure the recursive is called only once). So far the result is quite satisfying and I don't see any artifact.

Any feedback is really welcomed since I'm not really good in numerical calculation :)

这篇关于如何在Blinn / Loop的分辨率独立曲线渲染中解决渲染神器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆