Javascript ThreeJS-如何测量x/y/z中给定点的光强度/像素值?

Javascript ThreeJS-如何测量x/y/z中给定点的光强度/像素值?,javascript,3d,three.js,Javascript,3d,Three.js,我想知道如何获得场景中给定点的光强度和/或像素值rgba 例如,我有一个场景,移动的灯光照射在立方体上,我想测量立方体上某些点的亮度: //我们的Javascript将放在这里。 var场景=新的三个场景; var摄像机=新的三透视摄像机75,window.innerWidth/window.innerHeight,0.11000; var renderer=new THREE.WebGLRenderer{preserveDrawingBuffer:true}; renderer.setSiz

我想知道如何获得场景中给定点的光强度和/或像素值rgba

例如,我有一个场景,移动的灯光照射在立方体上,我想测量立方体上某些点的亮度:

//我们的Javascript将放在这里。 var场景=新的三个场景; var摄像机=新的三透视摄像机75,window.innerWidth/window.innerHeight,0.11000; var renderer=new THREE.WebGLRenderer{preserveDrawingBuffer:true}; renderer.setSize window.innerWidth、window.innerHeight; document.body.appendChild.doElement; var geometry=新的3.BoxGeometry 1,1,1; var material=新的3.0网格LambertMaterial; var cube=新的三个。网格几何体,材质; 立方体.旋转.x+=0.4; 立方体旋转y+=0.4; scene.addcube; var plane_geo=新的三个平面几何2,2,2; var平面=新的三个网格平面,材料; 平面旋转x=-1; 平面位置y=-0.5; 场景.添加平面; var灯光=新的三个聚光灯0xff0000,1100; //var灯=新的三点灯0xff0000,1100; light.position.set 3、2、2; 场景。添加灯光; var sphereSize=0.1; var pointLightHelper=new THREE.pointLightHelper-light,sphereSize; scene.addpointlighthelper; var-lightX=0.5; var-lightY=0.5; 摄像机位置z=5; 使有生气 document.addEventListenermousemove,mousemove\u处理器; 函数动画{ 请求动画帧动画; 光。位置。设置光x,光,1; 渲染器。渲染场景,摄影机; } 函数mousemove\u handlerevent { //获取映射到三维向量的鼠标坐标 var vector=新的3.Vector3; 向量集 event.clientX/window.innerWidth*2-1, -event.clientY/window.innerHeight*2+1, 0.5; 矢量相机; var dir=vector.subcmera.position.normalize; var distance=-camera.position.z/dir.z; var pos=camera.position.clone.adddir.multiplyScalardistance; lightX=位置x; 轻盈=位置y; } 正文{页边距:0;} 画布{宽度:100%;高度:100%} 我的前三个.js应用程序 正文{页边距:0;} 画布{宽度:100%;高度:100%}
这里有太多的事情要考虑。 从显而易见的事情开始:

现实生活中的光线计算取决于干涉、坎德拉、波长等。我不建议使用webGL灯光进行科学计算,比如太阳能性能

进一步:

3d中的灯光使用着色器过程。这意味着照明是对场景的传递。根据场景中的半透明对象(如窗口)的不同,您需要将摄影机直接移动到相关点上,从而尽可能清晰地渲染该点。重要的是,我们只能测量一个面向摄像机的点。但是,如果你的场景很简单,除非你有一个积极的雾设置,否则这不是什么大问题

获取特定像素上的光强度如下所示:

获取要了解的曲面的点。 获取该像素的屏幕位置。 获取画布上下文。 获取上下文像素位置 获取像素的RGBA值 将RGBA值转换为灰度。 但还是有一个陷阱:

转换为灰度并不像看上去那么直接。回想一下photoshop如何为您提供转换为灰度的不同方法。你有平均值、光度、强度、亮度等

这里有一把小提琴,你可以用一下。这些值表示为0-1浮点值。0是黑色的

工作小提琴:

在接下来的过程中:


为了获得一个特定的点来筛选像素而不是鼠标位置,请参阅这个StaskExoal:

这里有很多事情要考虑。 从显而易见的事情开始:

现实生活中的光线计算取决于干涉、坎德拉、波长等。我不建议使用webGL灯光进行科学计算,比如太阳能性能

进一步:

3d中的灯光使用着色器过程。这意味着照明是对场景的传递。根据场景中的半透明对象(如窗口)的不同,您需要将摄影机直接移动到相关点上,从而尽可能清晰地渲染该点。重要的是,我们只能测量一个面向摄像机的点。但是,如果你的场景很简单,除非你有一个积极的雾设置,否则这不是什么大问题

获取特定像素上的光强度如下所示:

获取要了解的曲面的点。 获取该像素的屏幕位置。 获取画布上下文。 获取上下文像素位置 获取像素的RGBA值 将RGBA值转换为灰度。 但还是有一个陷阱:

转换为灰度并不像看上去那么直接。回想一下photoshop如何为您提供转换为灰度的不同方法。你有平均值、光度、强度、亮度等

这是一把小提琴,你可以看到它 ck。这些值表示为0-1浮点值。0是黑色的

工作小提琴:

在接下来的过程中:


要获得屏幕像素中的特定点而不是鼠标位置,请参阅此stackoverflow:

body{margin:0}可能有助于提高鼠标单击的准确性。将立方体颜色设置为0xffffff可能会提供更直观的结果。是的,我将其设置为红色以显示转换为灰度的情况,从而获得更真实的发光体。但是是的。我认为OP会遵循3d位置到屏幕位置的链接,使得保证金没有意义。但总的来说,是的,答案显示了这个概念,需要调整语境。谢谢。这帮了大忙!我想有一件事我在你的代码中不太明白:你注释了.setPixelRatio。如果我取消对此的注释,我将不再获得正确的值。为什么?你正在改变缓冲区像素大小与物理像素大小的关系。示例代码需要1对1关系,因为它使用鼠标物理像素位置来查找画布像素。如果您在视网膜显示器上,并且将像素比率设置为每个物理像素2个缓冲像素,则鼠标将以相同的数量级关闭。您需要乘以鼠标像素位置,以获得绘制到传统画布的正确绘图缓冲区位置。在某些情况下,在ultra dpi设备上应用该比率是为了提高输出。body{margin:0}可能有助于提高鼠标单击的准确性。将立方体颜色设置为0xffffff可能会提供更直观的结果。是的,我将其设置为红色以显示转换为灰度的情况,从而获得更真实的发光体。但是是的。我认为OP会遵循3d位置到屏幕位置的链接,使得保证金没有意义。但总的来说,是的,答案显示了这个概念,需要调整语境。谢谢。这帮了大忙!我想有一件事我在你的代码中不太明白:你注释了.setPixelRatio。如果我取消对此的注释,我将不再获得正确的值。为什么?你正在改变缓冲区像素大小与物理像素大小的关系。示例代码需要1对1关系,因为它使用鼠标物理像素位置来查找画布像素。如果您在视网膜显示器上,并且将像素比率设置为每个物理像素2个缓冲像素,则鼠标将以相同的数量级关闭。您需要乘以鼠标像素位置,以获得绘制到传统画布的正确绘图缓冲区位置。在某些情况下,在ultra dpi设备上应用该比率是为了提高输出。使用r71可能不是一个好主意。为了指出这一点,最好升级到r87 thx。完成。使用r71可能不是一个好主意。为了指出这一点,最好升级到r87 thx。完成。
//assumes wegbGL renderer
renderer.domElement.addEventListener("click",function(event){

    var mousePos = getMousePos(this, event);
    var y = mousePos.y;
    var x = mousePos.x;

    var offscreenCanvas = document.createElement("canvas");
    offscreenCanvas.width = this.width;
    offscreenCanvas.height = this.height;
    var ctx = offscreenCanvas.getContext("2d");

    ctx.drawImage(this,0,0);
    var imageData = ctx.getImageData(x,y, 1, 1);
    var c = imageData.data;
    c = [c[0], c[1],c[2]];
    var lightness = ((Math.max.apply(null, c) + Math.min.apply(null, c)) / 2)/255;
    var intensity = (65536 * c[0] + 256 * c[1] + c[2])/16777216;
    var average = ((c[0]+c[1]+c[2]) / 3)/255;
    var luminosity = ((0.21 * c[0]) + (0.72 * c[1]) + (0.07 * c[2]))/255;
    console.log(lightness, intensity, average, luminosity);

},false);