Javascript webgl和opengles中带反射的三角形网格渲染问题
iam目前正在编写一个具有三角形交点的光线跟踪器。我将网格导出为.raw格式,只是为了获得每个顶点的坐标。 我注意到一件事,当我旋转相机时,它显示了一种被遮挡的网格 我在下面的片段着色器中发布了我的三角形相交函数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
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;
}