Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Geometry 射线与椭球体相交精度的提高_Geometry_Glsl_Shader_Floating Accuracy_Artifacts - Fatal编程技术网

Geometry 射线与椭球体相交精度的提高

Geometry 射线与椭球体相交精度的提高,geometry,glsl,shader,floating-accuracy,artifacts,Geometry,Glsl,Shader,Floating Accuracy,Artifacts,我需要提高我的一个函数的精度,该函数计算单个光线和轴对齐椭球体之间的交点 这是我的大气散射着色器的核心功能。旧的原始着色器处于浮动状态,对于正常的渲染效果很好,但在添加缩放后,我发现距离相对较小时,精度会降低。在浮标上,地球的可用距离仅为0.005 AU(天文单位)。因此,我尝试将关键函数移植到double,这很有帮助,因此现在可用距离约为1.0AU(带有小瑕疵) 这是片段着色器内部函数的double版本(旧式源代码使用不推荐的东西!!!) 在此之前: view_depth_l0=flo

我需要提高我的一个函数的精度,该函数计算单个光线和轴对齐椭球体之间的交点

这是我的大气散射着色器的核心功能。旧的原始着色器处于浮动状态,对于正常的渲染效果很好,但在添加缩放后,我发现距离相对较小时,精度会降低。在浮标上,地球的可用距离仅为0.005 AU(天文单位)。因此,我尝试将关键函数移植到
double
,这很有帮助,因此现在可用距离约为1.0AU(带有小瑕疵)

这是片段着色器内部函数的
double
版本(旧式源代码使用不推荐的东西!!!)

在此之前:

    view_depth_l0=float(l0);
    view_depth_l1=float(l1);
    return true;
    }
着色器的其余部分将句柄
l0、l1
作为相对值。结果如下:

对于距离达到10.0 AU的情况,现在可以了(只有在非常高的缩放范围内才能看到伪影),新的伪影最有可能在其他地方产生,因此当我有时间和意愿时,必须进一步研究

[edit2]将p0沿dp向(0,0,0)移动

实现需要相对昂贵的规格化函数和长度函数,并且不带范围移位的结果(edit1)比原始函数要好一些,但改进不太大。使用档位切换(edit1)时,结果与之前相同,因此不是这样。我的结论是,所有剩余的工件都不是由view-dept函数本身引起的

在整个过程中,我将尝试将着色器移植到
#version 400+fp64
,以检查输入数据是否被浮点舍入过多

[edit3]实际源代码

#extension GL_ARB_gpu_shader_fp64 : enable
double abs(double x) { if (x<0.0) x=-x; return x; }
// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2
float view_depth_ll= 0.0, // shift to boost accuracy
      view_depth_l0=-1.0, // view_depth_ll+view_depth_l0 first hit
      view_depth_l1=-1.0; // view_depth_ll+view_depth_l1 second hit
const double view_depth_max=100000000.0; // > max view depth
bool _view_depth(vec3 _p0,vec3 _dp,vec3 _r)
    {
    dvec3 p0,dp,r;
    double a,b,c,d,l0,l1;
    view_depth_ll= 0.0;
    view_depth_l0=-1.0;
    view_depth_l1=-1.0;
    // conversion to double
    p0=dvec3(_p0);
    dp=dvec3(_dp);
    r =dvec3(_r );
    // quadratic equation a.l.l+b.l+c=0; l0,l1=?;
    a=(dp.x*dp.x*r.x)
     +(dp.y*dp.y*r.y)
     +(dp.z*dp.z*r.z);
    b=(p0.x*dp.x*r.x)
     +(p0.y*dp.y*r.y)
     +(p0.z*dp.z*r.z); b*=2.0;
    c=(p0.x*p0.x*r.x)
     +(p0.y*p0.y*r.y)
     +(p0.z*p0.z*r.z)-1.0;
    // discriminant d=sqrt(b.b-4.a.c)
    d=((b*b)-(4.0*a*c));
    if (d<0.0) return false;
    d=sqrt(d);
    // standard solution l0,l1=(-b +/- d)/2.a
    a*=2.0;
    l0=(-b+d)/a;
    l1=(-b-d)/a;
    // alternative solution q=-0.5*(b+sign(b).d) l0=q/a; l1=c/q; (should be more accurate sometimes)
//  if (b<0.0) d=-d; d=-0.5*(b+d);
//  l0=d/a;
//  l1=c/d;
    // sort l0,l1 asc
    if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; }
    if (l0<0.0)          { a=l0; l0=l1; l1=a; }
    if (l0<0.0) return false;
    // relative shift to preserve accuracy after conversion back float
    if (l0>view_depth_max){ a=floor(l0/view_depth_max)*view_depth_max; a-=view_depth_max; view_depth_ll=float(a); if (l1>l0) l1-=a; l0-=a; }
    // conversion back float
    view_depth_l0=float(l0);
    view_depth_l1=float(l1);
    return true;
    }
#扩展GL_ARB_gpu_着色器_fp64:启用
双abs(double x){if(x)view_depth_l0,1
//其中r.x是elipsoid rx^-2,r.y=ry^-2,r.z=rz^-2
浮动视图\u深度\u ll=0.0,//移动以提高精度
view\u depth\u l0=-1.0,//view\u depth\u ll+view\u depth\u l0首次命中
view\u depth\u l1=-1.0;//view\u depth\u ll+view\u depth\u l1第二次命中
常量双视图深度最大值=100000000.0;/>最大视图深度
bool\u view\u depth(vec3\u p0,vec3\u dp,vec3\u r)
{
dvec3 p0,dp,r;
双a,b,c,d,l0,l1;
视图深度=0.0;
视图深度=1.0;
视图深度l1=-1.0;
//转双
p0=dvec3(p0);
dp=dvec3(_-dp);
r=dvec3(_r);
//二次方程a.l.l+b.l+c=0;l0,l1=?;
a=(dp.x*dp.x*r.x)
+(dp.y*dp.y*r.y)
+(dp.z*dp.z*r.z);
b=(p0.x*dp.x*r.x)
+(p0.y*dp.y*r.y)
+(p0.z*dp.z*r.z);b*=2.0;
c=(p0.x*p0.x*r.x)
+(p0.y*p0.y*r.y)
+(p0.z*p0.z*r.z)-1.0;
//判别式d=sqrt(b.b-4.a.c)
d=((b*b)-(4.0*a*c));

if(d)二次方程的标准公式没有很好的数值稳定性。请参阅以获得更好的计算根的方法。@Sneftel(+1)不知道这一点。但实施后,结果看起来是一样的。因此问题在别处…(可能是三点积)我认为移动点p0更接近椭球体(只有在过于粗糙的情况下)才能做到这一点,稍后将进行调查
    view_depth_l0=float(l0);
    view_depth_l1=float(l1);
    return true;
    }
#extension GL_ARB_gpu_shader_fp64 : enable
double abs(double x) { if (x<0.0) x=-x; return x; }
// compute length of ray(p0,dp) to intersection with ellipsoid((0,0,0),r) -> view_depth_l0,1
// where r.x is elipsoid rx^-2, r.y = ry^-2 and r.z=rz^-2
float view_depth_ll= 0.0, // shift to boost accuracy
      view_depth_l0=-1.0, // view_depth_ll+view_depth_l0 first hit
      view_depth_l1=-1.0; // view_depth_ll+view_depth_l1 second hit
const double view_depth_max=100000000.0; // > max view depth
bool _view_depth(vec3 _p0,vec3 _dp,vec3 _r)
    {
    dvec3 p0,dp,r;
    double a,b,c,d,l0,l1;
    view_depth_ll= 0.0;
    view_depth_l0=-1.0;
    view_depth_l1=-1.0;
    // conversion to double
    p0=dvec3(_p0);
    dp=dvec3(_dp);
    r =dvec3(_r );
    // quadratic equation a.l.l+b.l+c=0; l0,l1=?;
    a=(dp.x*dp.x*r.x)
     +(dp.y*dp.y*r.y)
     +(dp.z*dp.z*r.z);
    b=(p0.x*dp.x*r.x)
     +(p0.y*dp.y*r.y)
     +(p0.z*dp.z*r.z); b*=2.0;
    c=(p0.x*p0.x*r.x)
     +(p0.y*p0.y*r.y)
     +(p0.z*p0.z*r.z)-1.0;
    // discriminant d=sqrt(b.b-4.a.c)
    d=((b*b)-(4.0*a*c));
    if (d<0.0) return false;
    d=sqrt(d);
    // standard solution l0,l1=(-b +/- d)/2.a
    a*=2.0;
    l0=(-b+d)/a;
    l1=(-b-d)/a;
    // alternative solution q=-0.5*(b+sign(b).d) l0=q/a; l1=c/q; (should be more accurate sometimes)
//  if (b<0.0) d=-d; d=-0.5*(b+d);
//  l0=d/a;
//  l1=c/d;
    // sort l0,l1 asc
    if (abs(l0)>abs(l1)) { a=l0; l0=l1; l1=a; }
    if (l0<0.0)          { a=l0; l0=l1; l1=a; }
    if (l0<0.0) return false;
    // relative shift to preserve accuracy after conversion back float
    if (l0>view_depth_max){ a=floor(l0/view_depth_max)*view_depth_max; a-=view_depth_max; view_depth_ll=float(a); if (l1>l0) l1-=a; l0-=a; }
    // conversion back float
    view_depth_l0=float(l0);
    view_depth_l1=float(l1);
    return true;
    }