Getting the color value of a pixel on click of a mesh with three.js

人盡茶涼 提交于 2019-12-06 09:09:24

问题


I'm working with the last version of three.js and I got a scene with a 2D mesh, with gradient color. The color depends of a value assigned to each vertex. I would like to get the value of every point of my gradient by clicking on it with the mouse (by getting the color, and make some math for my value)

I tried to use a system like this one, since it works here : http://jsbin.com/wepuca/2/edit?html,js,output

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

function echoColor(e){
    var imgData = ctx.getImageData(e.pageX, e.pageX, 1, 1);
    red = imgData.data[0];
    green = imgData.data[1];
    blue = imgData.data[2];
    alpha = imgData.data[3];
    console.log(red + " " + green + " " + blue + " " + alpha);  
}

My problem is that this technique is used to get data from the canvas, when an image is displayed, and not a mesh. When I tried to use it on my mesh, I have that error :

"TypeError: ctx is null" or "imageData is not a function" (depending on how I declared my canvas and his context).

Since I didn't find if this method can be used with mesh, I'm here asking if it's possible or not, more than how to do it.

Thanks in advance


回答1:


First, you cannot get a 2D context from a canvas which is already using a WebGL context. This is why you're getting the ctx is null error.

To get the pixel color, you have two options.

1. Transfer the WebGL canvas image onto a canvas with a 2D context.

To do this, create a new canvas and size it to be the same size as your THREE.js canvas, and get a 2D context from it. You can then draw the rendered image from the THREE.js canvas onto your new canvas as an image, using the 2D context:

var img2D = new Image();
twoDeeCanvasImage.addEventListener("load", function () {
    ctx2D.clearRect(0, 0, canvas2D.width, canvas2D.height);
    ctx2D.drawImage(img2D, 0, 0);
    // from here, get your pixel data
});
img2D.src = renderer.domElement.toDataURL("img/png");

From there you can use getImageData, like you did before.

One caveat of this method is that you may see image degradation due to compression introduced when exporting the image via toDataURL. You can circumvent this in some cases:

if(ctx2D.imageSmoothingEnabled !== undefined){
    ctx2D.imageSmoothingEnabled  = false;
}
else if(ctx2D.mozImageSmoothingEnabled  !== undefined){
    ctx2D.mozImageSmoothingEnabled   = false;
}
else if(ctx2D.webkitImageSmoothingEnabled  !== undefined){
    ctx2D.webkitImageSmoothingEnabled   = false;
}
else{
    console.warn("Browser does not support disabling canvas antialiasing. Results image may be blurry.");
}

2. You can also get a pixel value directly from the renderer, but it will cost you an extra render pass.

See this THREE.js example: https://threejs.org/examples/?q=instanc#webgl_interactive_instances_gpu

This example uses readRenderTargetPixels in the THREE.WebGLRenderer. https://threejs.org/docs/#api/renderers/WebGLRenderer

I don't have any personal experience using this method, so hopefullysomeone else can fill in some of the blanks.



来源:https://stackoverflow.com/questions/43583012/getting-the-color-value-of-a-pixel-on-click-of-a-mesh-with-three-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!