问题是您所使用的设备的devicePixelRatio!= 1.0和three.js大小差不多。
因为你打电话 renderer.setPixelRatio
现在魔术在幕后发生。您画布的大小不是您要求的大小,而是根据three.js代码中隐藏的某些公式得出的其他大小。
所以,会发生什么。您的画布是一种尺寸,但是渲染目标是另一种尺寸。您的着色器使用gl_PointSize
绘制其点。该尺寸以设备像素为单位。由于渲染目标的大小不同,因此渲染目标中点的大小与屏幕上的点不同。
删除对的呼叫render.setPixelRatio
,它将开始工作。
IMO解决此问题的正确方法是使用devicePixelRatio
自己,因为这样您可以100%看到所有发生的事情。幕后没有发生任何魔术。
所以,
摆脱容器并直接使用画布
设置画布以100vw
用于宽度,100vh
高度和主体margin: 0;
canvas { width: 100vw; height: 100vh; display: block; } body { margin: 0; }
这将使您的画布自动拉伸以填充窗口。
使用浏览器拉伸画布的大小选择其drawingBuffer应为的大小并乘以devicePixelRatio
。假设您实际上要支持设备像素比率。无需重复执行两次,因此在DRY之后,只需在onWindowResize中进行即可。
canvas = document.getElementById("c"); renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, canvas: canvas, }); pickingTexture = new THREE.WebGLRenderTarget(1, 1, options); onWindowResize(); ... function onWindowResize() { var width = canvas.clientWidth * window.devicePixelRatio; var height = canvas.clientHeight * window.devicePixelRatio; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height, false); // YOU MUST PASS FALSE HERE otherwise three.js will muck with the CSS pickingTexture.setSize(width, height); }
将鼠标坐标转换为设备坐标
renderer.readRenderTargetPixels( pickingTexture, mouse.x * window.devicePixelRatio, pickingTexture.height - mouse.y * window.devicePixelRatio, 1, 1, pixelBuffer);
这是解决方案
canvas { width: 100vw; height: 100vh; display: block; } body { margin: 0; }
canvas = document.getElementById("c"); renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, canvas: canvas, }); pickingTexture = new THREE.WebGLRenderTarget(1, 1, options); onWindowResize(); ... function onWindowResize() { var width = canvas.clientWidth * window.devicePixelRatio; var height = canvas.clientHeight * window.devicePixelRatio; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height, false); // YOU MUST PASS FALSE HERE otherwise three.js will muck with the CSS pickingTexture.setSize(width, height); }