Javascript webgl和opengles中带反射的三角形网格渲染问题

Javascript webgl和opengles中带反射的三角形网格渲染问题,javascript,opengl-es,glsl,rendering,webgl2,Javascript,Opengl Es,Glsl,Rendering,Webgl2,iam目前正在编写一个具有三角形交点的光线跟踪器。我将网格导出为.raw格式,只是为了获得每个顶点的坐标。 我注意到一件事,当我旋转相机时,它显示了一种被遮挡的网格 我在下面的片段着色器中发布了我的三角形相交函数 bool hitTriangle(vec3 orig,vec3 dir,vec3 a,vec3 b,vec3 c,out vec3 uvt,out vec3 triangleNormal){ float eps=1e-8; vec3 ab=b-a; vec3 ac=c

iam目前正在编写一个具有三角形交点的光线跟踪器。我将网格导出为.raw格式,只是为了获得每个顶点的坐标。 我注意到一件事,当我旋转相机时,它显示了一种被遮挡的网格

我在下面的片段着色器中发布了我的三角形相交函数

bool hitTriangle(vec3 orig,vec3 dir,vec3 a,vec3 b,vec3 c,out vec3 uvt,out vec3 triangleNormal){
   float eps=1e-8;
   vec3 ab=b-a;
   vec3 ac=c-a;

   triangleNormal = normalize(cross(ab,ac));
   vec3 n=cross(dir,ac);

   float det=dot(ab,n);
   // if the determinant is negative the triangle is backfacing
   // if the determinant is close to 0, the ray misses the triangl
   if(det<=eps){ return false;}
   
   vec3 ao=orig-a;
   float u=dot(ao,n)/det;
   if(u<0.0 || u>1.0){ return false;}
    
   vec3 e=cross(ao,ab);
   float v=dot(dir,e)/det;
   if(v<0.0||u+v>1.0){ return false;}

   float t= dot(ac,e)/det;
   uvt = vec3(u,v,t);
   return true;
}
bool-hittangle(vec3-orig、vec3-dir、vec3-a、vec3-b、vec3-c、out-vec3-uvt、out-vec3-triangleNormal){
浮球eps=1e-8;
vec3ab=b-a;
vec3ac=c-a;
三角形法线=规格化(交叉(ab,ac));
vec3 n=交叉(方向,ac);
浮点数=点(ab,n);
//如果行列式为负,则三角形为倒三角形
//如果行列式接近0,则光线将丢失三角形
如果(detmindist){
hitPos1=相交;
Minist=z;
Wehit某事=真实;
材料类型=金属;
材料反照率=vec3(.0.8.8);
法线=三角形法线;
hitPos=hitPos1;
}
}      
}      
归还某物;
}
下面是通过跟踪循环的跟踪函数

//Trace is the main function of the max bounces
vec3 Trace(out Ray ray, Sphere lightSource){

    vec3 hitPos, normal;
    bool isShpere;
    Material material;
    vec3 color = vec3(1.);
    vec3 attenuation = vec3(1.);
    vec3 light = vec3(1.,1.,1.), shadow = vec3(1.,1.,1.);

    //this if for every ray to bounce 4 times.(hopefully)
    for(int i=0; i< MAX_BOUNCES; i++){
        
        // we check if we hit something
        if(hitScene(ray, hitPos, normal, material, lightSource)){
  
            //we calculate the new direction
            vec3 direction = normalize(reflect(ray.dir, normal));
                
            ray = Ray(hitPos, direction); 
             
            color *= material.albedo * attenuation*hitPos;
            attenuation *= material.albedo;    
        }

        else{
            color = attenuation;
        }
    }

    return color;
}
//跟踪是最大反弹的主要功能
vec3跟踪(外光线、球体光源){
vec3-hitPos,正常;
布尔·伊什佩尔;
材料;
vec3颜色=vec3(1.);
vec3衰减=vec3(1.);
vec3灯光=vec3(1,1,1.),阴影=vec3(1,1,1.);
//如果每一条光线反弹4次(希望如此)
对于(int i=0;i
在那之后,我得到了这样的东西: 正如你所看到的,我得到了反射,但我也看到了球体内部的立方体。这是否意味着我无法通过光线三角形相交测试?或者最小距离不正确


问题的根源是什么?

这并不能解决你所有的问题,但它是答案的一部分

在你的代码中有一个基本的误解。重心坐标不是坐标,但它们是[0,1]范围内的3个值。想象一个重心坐标为3个权重,权重为三角形的3个角点

重心坐标的3个刻度之和为1:

b.x+b.x+b.z==1
如果三角形由三个点定义,
a
B
C
,则三角形上由重心坐标定义的点
X
,可通过以下公式计算:

X=A*b.X+b*b.y+C*b.z
这意味着在HITSENCE
中,交叉口距离的计算必须进行如下调整:

vec3 intersect=a.xyz*uvt.x+b.xyz*uvt.y+c.xyz*uvt.z;
到射线原点的距离是从原点到射线方向交点的向量长度。
一般来说,我会这样计算:

float z=dot(intersect-R_.orig,normalize(R_.dir));

此外,计算重心坐标的算法看起来很奇怪。我非常确定它必须是
uvt=vec3(t,u,v)
而不是
uvt=vec3(u,v,t)。但这需要进一步调查

三角形和光线的交点可以按如下方式计算:

射线由点
R0
和方向
D
定义
该平面由一个三角形定义,三角形有三个点
PA
PB
PC

平面的法向量可通过三角形的两条边的叉积计算:

N=标准化(交叉(PC-PA,PB-PA)
R0
到平面的正常距离
n

n=| R0-PA |*cos(alpha)=点(PA-R0,n)
因此,交点
X
到射线R0原点的距离
d
为:

d=n/cos(β)=n/dot(d,n)
交点
X
为:

X=R0+D*D=R0+D*dot(PA-R0,N)/dot(D,N)
将应用于代码时,我建议使用以下函数
hittangle

  • 如果光线在光线原点(
    orig
    )后沿光线的正方向(
    dir
    )与三角形基本体相交,则返回值为
    true
  • 输出
    N
    是由三角形定义的平面的法向量
  • 输出
    uvt
    是三角形的最大值
  • 输出
    x
    是三角形上的交点
  • 输出
    dist
    是从光线原点(
    orig
    )到交点
    x
    的距离
注意,光线方向(
dir
)必须标准化。只有当函数返回
true
时,输出值才有意义

bool-hittangle(
vec3-orig,vec3-dir,vec3-a,vec3-b,vec3-c,
输出向量3 uvt、输出向量3 N、输出向量3 x、输出浮点距离){
浮球eps=1e-8;
vec3ab=b-a;
vec3ac=c-a;
N=标准化(交叉(ab,ac));
距离=点(a-原点,N)/点(方向,N);
x=原点+方向*距离;
vec3ax=x-a;
浮点数d00=点(ab,ab);
浮点数d01=点(ab,ac);
浮动d11=点(ac,ac);
浮点数d20=do
//Trace is the main function of the max bounces
vec3 Trace(out Ray ray, Sphere lightSource){

    vec3 hitPos, normal;
    bool isShpere;
    Material material;
    vec3 color = vec3(1.);
    vec3 attenuation = vec3(1.);
    vec3 light = vec3(1.,1.,1.), shadow = vec3(1.,1.,1.);

    //this if for every ray to bounce 4 times.(hopefully)
    for(int i=0; i< MAX_BOUNCES; i++){
        
        // we check if we hit something
        if(hitScene(ray, hitPos, normal, material, lightSource)){
  
            //we calculate the new direction
            vec3 direction = normalize(reflect(ray.dir, normal));
                
            ray = Ray(hitPos, direction); 
             
            color *= material.albedo * attenuation*hitPos;
            attenuation *= material.albedo;    
        }

        else{
            color = attenuation;
        }
    }

    return color;
}