使用Three.js中的自定义顶点着色器对点云进行光线跟踪

使用Three.js中的自定义顶点着色器对点云进行光线跟踪,three.js,webgl,Three.js,Webgl,如何使用three.js中的自定义顶点着色器对点云进行光线跟踪 这是我的顶点着色器 void main() { vUvP = vec2( position.x / (width*2.0), position.y / (height*2.0)+0.5 ); colorP = vec2( position.x / (width*2.0)+0.5 , position.y / (height*2.0) ); vec4 pos = vec4(0.0,0.0,0.0,0.0); dept

如何使用three.js中的自定义顶点着色器对点云进行光线跟踪

这是我的顶点着色器

void main() {
  vUvP = vec2( position.x / (width*2.0), position.y / (height*2.0)+0.5 );
  colorP = vec2( position.x / (width*2.0)+0.5 , position.y / (height*2.0)  );
  vec4 pos = vec4(0.0,0.0,0.0,0.0);
  depthVariance = 0.0;
  if ( (vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>0.0)) {
     vec2 smp = decodeDepth(vec2(position.x, position.y));
     float depth = smp.x;
     depthVariance = smp.y; 
     float z = -depth;
     pos = vec4(( position.x / width - 0.5 ) * z * (1000.0/focallength) * -1.0,( position.y / height - 0.5 ) * z * (1000.0/focallength),(- z + zOffset / 1000.0) * 2.0,1.0);
     vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0)  );
     vec4 maskColor = texture2D( map, maskP );
     maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;
  }
  gl_PointSize = pointSize;
  gl_Position = projectionMatrix * modelViewMatrix * pos;
}
void main(){
vUvP=vec2(位置x/(宽度*2.0),位置y/(高度*2.0)+0.5);
colorP=vec2(位置x/(宽度*2.0)+0.5,位置y/(高度*2.0));
vec4位置=vec4(0.0,0.0,0.0,0.0);
深度方差=0.0;
如果((vUvP.x0.5)| |(vUvP.y0.0)){
vec2 smp=解码深度(vec2(位置x,位置y));
浮动深度=smp.x;
深度方差=smp.y;
浮动z=深度;
pos=vec4((位置x/宽度-0.5)*z*(1000.0/焦距)*-1.0,(位置y/高度-0.5)*z*(1000.0/焦距),(-z+zOffset/1000.0)*2.0,1.0);
vec2 maskP=vec2(位置x/(宽度*2.0),位置y/(高度*2.0));
vec4 maskColor=纹理2d(贴图,maskP);
maskVal=(maskColor.r+maskColor.g+maskColor.b)/3.0;
}
gl_PointSize=PointSize;
gl_位置=投影矩阵*模型视图矩阵*位置;
}
在Points类中,光线跟踪的实现方式如下:

function testPoint( point, index ) {
    var rayPointDistanceSq = ray.distanceSqToPoint( point );
    if ( rayPointDistanceSq < localThresholdSq ) {
      var intersectPoint = ray.closestPointToPoint( point );
      intersectPoint.applyMatrix4( matrixWorld );
      var distance = raycaster.ray.origin.distanceTo( intersectPoint );
      if ( distance < raycaster.near || distance > raycaster.far ) return;
      intersects.push( {
          distance: distance,
          distanceToRay: Math.sqrt( rayPointDistanceSq ),
          point: intersectPoint.clone(),
          index: index,
          face: null,
          object: object
       } );
    }
 }

var vertices = geometry.vertices;
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
       testPoint( vertices[ i ], i );
}
功能测试点(点、索引){
var rayPointDistanceSq=光线距离SQTOPOINT(点);
if(光线点距离SQraycaster.far)返回;
相交。推({
距离:距离,,
distanceToRay:Math.sqrt(光线点距离SQ),
点:intersectPoint.clone(),
索引:索引,,
面:空,
对象:对象
} );
}
}
var顶点=geometry.vertices;
对于(var i=0,l=vertices.length;i
但是,由于我使用的是顶点着色器,因此geometry.vertex与屏幕上的顶点不匹配,这会阻止光线跟踪工作


我们可以从顶点着色器中获取点吗?

我没有深入了解顶点着色器的实际功能,我认为在着色器中执行此操作有很好的理由,因此在执行光线投射时,可能无法使用javascript重做计算

一种方法是对点的位置进行某种估计,将这些点用于预选,并对最接近光线的点进行更复杂的计算

如果这不起作用,最好的办法是渲染场景的查找贴图,其中颜色值是在坐标处渲染的点的id(这也称为GPU拾取、示例,甚至是一些库,尽管这并不能真正满足您的需要)

为此,需要渲染场景两次:在第一次过程中创建查找贴图,并在第二次过程中定期渲染。查找贴图将存储在那里渲染的每个像素的粒子

要获取该信息,您需要设置一个
THREE.RenderTarget
(这可能会缩小到宽度/高度的一半以获得更好的性能)和不同的材质。顶点着色器保持原样,但片段着色器将只为每个粒子(或可用于识别它们的任何对象)输出一个唯一的颜色值。然后将场景(或更好:仅应为光线投射目标的部分)渲染到渲染目标中:

var size = renderer.getSize();
var renderTarget = new THREE.WebGLRenderTarget(size.width / 2, size.height / 2);
renderer.render(pickingScene, camera, renderTarget);
渲染后,可以使用-方法获取此查找纹理的内容:

(此处pixelData的布局与常规画布的布局相同
imageData.data


一旦你有了它,光线投射器将只需要查找一个坐标,读取并解释颜色值作为对象id,并对其进行处理。

谢谢!!我只想为将来尝试这样做的任何人添加。在“顶点”着色器中,可以设置一个可变的顶点,然后可以在片段着色器中使用它,在该着色器中可以设置顶点的颜色
var pixelData = new Uint8Array(width * height * 4);
renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, pixelData);