https://www.worldlink.com.cn/osdir/gpu-js.html
<script src="gpu-browser.js"></script>
<script>
function mul(a,b){
var l1=a.length
var l2=a[0].length
var l3=b.length
var l4=b[0].length
if(l2!=l3)return false
var f= new GPU().createKernel(function(a, b,l2) {
let sum = 0;
for (let i = 0; i <l2; i++)
sum += a[this.thread.y][i] * b[i][this.thread.x];
return sum;
}).setOutput([l4, l1]);
return f(a, b,l2)
}
var a=[
[1,0],
[1,0],
[0,2]]
var b=[
[2,0],
[0,1]]
var c = mul(a, b);
console.log("a",a)
console.log("b",b)
console.log("c",c)
</script>
用GPU实现视锥剔除
class Culling{
X,Y,Z,R,//包围球
camera,
models,
sizeGPU,
constructor (opt){
this.camera=opt.camera
this.models=opt.models
this.#init_GPU_culling()
}
#init_GPU_culling(){
var b=this.models.length
this.sizeGPU=Math.ceil(Math.pow(n,0.5));
//#GPU_culling是利用GPU进行视锥遮挡计算的方法
this.GPU_culling= new GPU().createKernel(function (p0,p1,p2,p3,p4,p5,X,Y,Z,R,sizeGPU) {
//p0,p1,p2,p3,p4,p5 视锥体的6个平面 //每个平面包含四个参数信息
//X,Y,Z,R 包围球 sizeGPU
var k=this.thread.y*sizeGPU+this.thread.x;
return intersectsSphere(p0,p1,p2,p3,p4,p5,X[k],Y[k],Z[k],R[k])
function intersectsSphere(p0,p1,p2,p3,p4,p5,x,y,z,r) {
function distanceToPoint(plane,point) {
return plane[0]* point[0] + plane[1]* point[1] + plane[2]* point[2] + plane[3];
}
if ( distanceToPoint(p0, [x,y,z] ) < -1*r ) return 0;//不相交
if ( distanceToPoint(p1, [x,y,z] ) < -1*r ) return 0;//不相交
if ( distanceToPoint(p2, [x,y,z] ) < -1*r ) return 0;//不相交
if ( distanceToPoint(p3, [x,y,z] ) < -1*r ) return 0;//不相交
if ( distanceToPoint(p4, [x,y,z] ) < -1*r ) return 0;//不相交
if ( distanceToPoint(p5, [x,y,z] ) < -1*r ) return 0;//不相交
return 1;
}
}).setOutput([this.sizeGPU, this.sizeGPU])
var X=[],Y=[],Z=[],R=[];
var k=0;
for(var i=0;i<this.sizeGPU;i++)
for(var j=0;j<this.sizeGPU;j++){
if(k<this.models.length){
X.push(this.models[k].boundingSphere.x);
Y.push(this.models[k].boundingSphere.y);
Z.push(this.models[k].boundingSphere.z);
R.push(this.models[k].boundingSphere.r);
k++;
}else{
X.push(0);
Y.push(0);
Z.push(0);
R.push(0);
}
}
this.X=X;this.Y=Y;this.Z=Z;this.R=R;
}
update=function(){//判断哪些资源在视锥内
var frustum=scope.#getFrustum();
var out=scope.GPU_culling(
frustum[0], frustum[1], frustum[2], frustum[3], frustum[4], frustum[5],//视锥体
scope.X,scope.Y,scope.Z,scope.R,//包围球
scope.sizeGPU
)
var kk=0;
for(var i=0;i<scope.sizeGPU;i++)
for(var j=0;j<scope.sizeGPU;j++)
if(kk<scope.models.length)
scope.models[kk++].visible=(out[i][j]===1);
}
#getFrustum=function () {
var frustum=new THREE.Frustum();
frustum.setFromProjectionMatrix(
new THREE.Matrix4().multiplyMatrices(
this.camera.projectionMatrix,
this.camera.matrixWorldInverse
)
);
const planes = frustum.planes;
var plane0=planes[0];
var plane1=planes[1];
var plane2=planes[2];
var plane3=planes[3];
var plane4=planes[4];
var plane5=planes[5];
return [
[plane0.normal.x,plane0.normal.y,plane0.normal.z,plane0.constant],
[plane1.normal.x,plane1.normal.y,plane1.normal.z,plane1.constant],
[plane2.normal.x,plane2.normal.y,plane2.normal.z,plane2.constant],
[plane3.normal.x,plane3.normal.y,plane3.normal.z,plane3.constant],
[plane4.normal.x,plane4.normal.y,plane4.normal.z,plane4.constant],
[plane5.normal.x,plane5.normal.y,plane5.normal.z,plane5.constant],
];
}
}