当我们点击它时,我们如何使用Javascript获取网格的像素颜色?

时间:2018-03-26 15:53:39

标签: javascript html html5 canvas three.js

目前在页面中我们有一个用TreeJS加载的网格并显示在画布中: enter image description here

我们怎样才能获得点击的点的颜色?

我已经尝试过这里建议:Getting the color value of a pixel on click of a mesh with three.js,使用webgl上下文创建一个带有2d上下文的画布。

问题在于,当我们将模型转换为PNG时,图像为白色:

我们的img 2d src:

enter image description here

如果我们点击它:

enter image description here

然后控制台记录颜色为:0 0 0 0

此外,我将展示生成webgl画布和2d画布的代码:

// this class handles the load and the canva for a nrrd
// Using programming based on prototype: https://javascript.info/class
// This class should be improved:
//   - Canvas Width and height

InitCanvas = function (IdDiv, Filename) {


    this.IdDiv = IdDiv;
    this.Filename = Filename
}

InitCanvas.prototype = {

    constructor: InitCanvas,

    init: function () {

        this.container = document.getElementById(this.IdDiv);

        // this should be changed.
        this.container.innerHeight = 600;
        this.container.innerWidth = 800;

        //These statenments should be changed to improve the image position
        this.camera = new THREE.PerspectiveCamera(60, this.container.innerWidth / this.container.innerHeight, 0.01, 1e10);
        this.camera.position.z = 300;

        let scene = new THREE.Scene();
        scene.add(this.camera);

        // light

        let dirLight = new THREE.DirectionalLight(0xffffff);
        dirLight.position.set(200, 200, 1000).normalize();

        this.camera.add(dirLight);
        this.camera.add(dirLight.target);


        // read file

        let loader = new THREE.NRRDLoader();
        loader.load(this.Filename, function (volume) {

            //z plane
            let sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));

            this.container.innerWidth = sliceZ.iLength;
            this.container.innerHeight = sliceZ.jLength;

            sliceZ.mesh.material.color.setRGB(0,1,1);


            console.log('Our slice is: ', sliceZ);

            scene.add(sliceZ.mesh);
        }.bind(this));


        this.scene = scene;



        var canvas2d = document.createElement('canvas');

        canvas2d.id = "canvas2D";
        canvas2d.style.width = `${this.container.innerWidth}px`;
        canvas2d.style.height = `${this.container.innerHeight}px`;
        canvas2d.style.zIndex = 8;




        this.container.appendChild(canvas2d);





        // renderer
        this.renderer = new THREE.WebGLRenderer({alpha: true});
        this.renderer.setPixelRatio(this.container.devicePixelRatio);
        this.renderer.setSize(this.container.innerWidth, this.container.innerHeight);

        // add canvas in container
        this.container.appendChild(this.renderer.domElement);





    },

    animate: function () {

        this.renderer.render(this.scene, this.camera);
    }

}

我们也在logic.js

中使用它
if (!Detector.webgl) Detector.addGetWebGLMessage();

// global variables for this scripts
let OriginalImg,
    SegmentImg,
    myFileReader;

var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var mousePressed = false;
var clickCount = 0;
var allText;


init();
animate();


// initilize the page
function init() {


    readTextFile("columna01-es-latin1.txt");

    let originalImgPath = getParameterByName('originalImgPath');
    let filename = originalImgPath || "models/nrrd/columna02.nrrd"; // change your nrrd file
    let idDiv = 'original';
    OriginalImg = new InitCanvas(idDiv, filename);
    OriginalImg.init();
    console.log(OriginalImg);

    let segmentedImgPath = getParameterByName('segmentedImgPath');

    filename = segmentedImgPath || "models/nrrd/columnasegmentado02.nrrd"; // change your nrrd file
    idDiv = 'segment';
    SegmentImg = new InitCanvas(idDiv, filename);
    SegmentImg.init();





















    let canvas2D = document.getElementById('canvas2D');
    let ctx2D = canvas2D.getContext('2d');

    var img2D = new Image();
    img2D.src = OriginalImg.renderer.domElement.toDataURL("img/png");
    console.log('Our img 2d source is:::: ',img2D.src);
    img2D.addEventListener("load", function () {
        ctx2D.clearRect(0, 0, canvas2D.width, canvas2D.height);
        ctx2D.drawImage(img2D, 0, 0);
        // from here, get your pixel data
        var imgData = ctx2D.getImageData(10, 10, 1, 1);
        red = imgData.data[0];
        green = imgData.data[1];
        blue = imgData.data[2];
        alpha = imgData.data[3];
        console.log(red + " " + green + " " + blue + " " + alpha);
    });
}

function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}

let originalCanvas = document.getElementById('original');
originalCanvas.addEventListener('mousedown', onDocumentMouseDown, false);
originalCanvas.addEventListener('mouseup', onDocumentMouseUp, false);


function onDocumentMouseDown(event) {
    mousePressed = true;

    clickCount++;

    let realClickedCanvasX = event.offsetX;
    let realClickedCanvasY = event.offsetY;

    mouse.x = ( ( event.clientX - OriginalImg.renderer.domElement.offsetLeft ) / OriginalImg.renderer.domElement.clientWidth ) * 2 - 1;
    mouse.y = -( ( event.clientY - OriginalImg.renderer.domElement.offsetTop ) / OriginalImg.renderer.domElement.clientHeight ) * 2 + 1


    console.log('Mouse x position is: ', realClickedCanvasX, 'the click number was: ', clickCount);
    console.log('Mouse x position is: ', realClickedCanvasY, 'the click number was: ', clickCount);

    //console.log('Mouse x position is: ', mouse.x, 'the click number was: ', clickCount);
    //console.log('Mouse Y position is: ', mouse.y);

    raycaster.setFromCamera(mouse.clone(), OriginalImg.camera);
    var objects = raycaster.intersectObjects(OriginalImg.scene.children);

    console.log(objects);
}

function onDocumentMouseUp(event) {
    mousePressed = false
}


function animate() {


    requestAnimationFrame(animate);
    OriginalImg.animate();
    SegmentImg.animate();


}

我也读过:

ThreeJS How to pick the intersection point color of an object

Get pixel color from an image

How to get a pixel's x,y coordinate color from an image?

getPixel from HTML Canvas?

https://johnresig.com/blog/ocr-and-neural-nets-in-javascript/

https://dev.opera.com/articles/html5-canvas-basics/#pixelbasedmanipulation

Get the mouse coordinates when clicking on canvas

HTML5 Dynamically create Canvas

Canvas width and height in HTML5

Set Canvas size using javascript

提前感谢您的帮助。

编辑:

感谢@ TheJim01的帮助。

我已尝试过您的建议,并使用以下代码:

进入OnDocumentMouseDown函数:

var target = OriginalImg.renderer.getRenderTarget();
    console.log('Our target which should be a WebGLRenderTarget is: ');
    console.log(target);

    var outputBuffer = new Uint8Array( OriginalImg.renderer.width * OriginalImg.renderer.height * 4 );

    OriginalImg.renderer.readRenderTargetPixels ( target, 0, 0, OriginalImg.renderer.width, OriginalImg.renderer.height, outputBuffer );

    var pixelIndex = ((realClickedCanvasX * OriginalImg.renderer.width) + realClickedCanvasY) * 4;

    var color = {
        r: outputBuffer[pixelIndex + 0],
        g: outputBuffer[pixelIndex + 1],
        b: outputBuffer[pixelIndex + 2],
        a: outputBuffer[pixelIndex + 3]
    };

    console.log('Color of clicked pixel is: ');
    console.log(color);

我们在网络控制台中看到:

Our target which sould be a WebGLRenderTarget is: 

null

THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.

Color of clicked pixel is: 

Object { r: undefined, g: undefined, b: undefined, a: undefined }

我试着了解发生的事情并解决了这个问题,我读到了:

Three.js render to texture

我添加了一个WebGlRenderTarget:

... more code...

    this.renderTarget = new THREE.WebGLRenderTarget(this.renderer.domElement.clientWidth, this.renderer.domElement.clientHeight);

        this.renderer.render(this.scene, this.camera, this.renderTarget);

... more code...

现在我们在网络控制台中看到了:

    Error: WebGL warning: clear: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0 has no width or height
    three.js:21370:4
    Error: WebGL warning: clear: Framebuffer must be complete.
    three.js:21370:4
    Error: WebGL warning: clear: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0 has no width or height
    three.js:21370:4
    Error: WebGL warning: clear: Framebuffer must be complete.
    three.js:21370:4
  ...

我试图寻找它,我在GitHub中看到了这个问题:

https://github.com/pixijs/pixi.js/issues/3767

但是我认为它不相关。

EDIT2:

谢谢@ TheJim01的帮助,我很感激!! 在您的帮助和代码下,Render Target问题看起来已经解决了。事实上,我在Web控制台中看到一个奇怪的警告:

Error: WebGL warning: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.

在搜索此警告后,我看到了这个很棒的主题:Error: WebGL: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one

关闭标签后,重新加载项目已经消失了。

此外,我们获得的颜色未定义,我将显示一个控制台日志:

Our OriginalImg where we want to get the color is: 

Object { IdDiv: "original", Filename: "models/nrrd/columna02.nrrd", container: div#original.column, camera: {…}, scene: {…}, renderer: {…} }

Error: WebGL warning: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.

Error: WebGL warning: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.

The target being used in this click is: 

Object { uuid: "8EAEFD8F-5C55-4973-84BC-471D43C006F8", width: undefined, height: undefined, scissor: {…}, scissorTest: false, viewport: {…}, texture: {…}, depthBuffer: true, stencilBuffer: true, depthTexture: null }

Our target which should be a WebGLRenderTarget is: 
onMouseDownLogic.js:23:5
Object { uuid: "8EAEFD8F-5C55-4973-84BC-471D43C006F8", width: 800, height: 600, scissor: {…}, scissorTest: false, viewport: {…}, texture: {…}, depthBuffer: true, stencilBuffer: true, depthTexture: null, … }
onMouseDownLogic.js:24:5
Color of clicked pixel is: 
onMouseDownLogic.js:39:5
{…}
​
a: undefined
​
b: undefined
​
g: undefined
​
r: undefined
​
__proto__: Object { … }

为了更好地理解我正在撰写的内容,我重构了代码以更好地解释和编写代码。

我们有logic.js,其目的是初始化画布并为它们制作动画:

if (!Detector.webgl) Detector.addGetWebGLMessage();

// global variables for this scripts
let OriginalImg,
    SegmentImg;

var mouse = new THREE.Vector2();
var raycaster = new THREE.Raycaster();
var allText;

init();
animate();

// initilize the page
function init() {

    readTextFile("columna01-es-latin1.txt");
    OriginalImg = initCanvasOfOriginalImg();
    initCanvasOfSegmentedImg();

}

let originalCanvas = document.getElementById('original');
originalCanvas.addEventListener('mousedown', onDocumentMouseDown, false);

// re-usable objects defined outside your mouse event
console.log('Our OriginalImg where we want to get the color is: ');
console.log(OriginalImg);

var size = OriginalImg.renderer.getSize();
var reusableTarget = new THREE.WebGLRenderTarget(OriginalImg.renderer.width, OriginalImg.renderer.height);

function onDocumentMouseDown(event) {

    let {realClickedCanvasX, realClickedCanvasY} = calculateClickedPointWindowCoordinates(event);
    let OriginalImgRenderer = calculateNormalizedClickedPointCoordinates(event);


    var target = OriginalImgRenderer.getRenderTarget() || reusableTarget;
    console.log('The target being used in this click is: ');
    console.log(target);

    size = OriginalImgRenderer.getSize();
    target.setSize(size.width, size.height);

    OriginalImgRenderer.render( OriginalImg.scene, OriginalImg.camera, target );

    calculateClickedPointColor(OriginalImgRenderer, realClickedCanvasX, realClickedCanvasY);
    projectRayAndGetIntersectedObject();
}

function animate() {


    requestAnimationFrame(animate);
    OriginalImg.animate();
    SegmentImg.animate();


}

然后我们有InitCanvas.js,它是连接div的Prototype,画布和正在加载的模型:

// this class handles the load and the canva for a nrrd
// Using programming based on prototype: https://javascript.info/class
// This class should be improved:
//   - Canvas Width and height

InitCanvas = function (IdDiv, Filename) {


    this.IdDiv = IdDiv;
    this.Filename = Filename
}

InitCanvas.prototype = {

    constructor: InitCanvas,

    init: function () {

        this.container = document.getElementById(this.IdDiv);

        // this should be changed.
        this.container.innerHeight = 600;
        this.container.innerWidth = 800;

        //These statenments should be changed to improve the image position
        this.camera = new THREE.PerspectiveCamera(60, this.container.innerWidth / this.container.innerHeight, 0.01, 1e10);
        this.camera.position.z = 300;

        let scene = new THREE.Scene();
        scene.add(this.camera);

        // light

        let dirLight = new THREE.DirectionalLight(0xffffff);
        dirLight.position.set(200, 200, 1000).normalize();

        this.camera.add(dirLight);
        this.camera.add(dirLight.target);


        // read file

        let loader = new THREE.NRRDLoader();
        loader.load(this.Filename, function (volume) {

            //z plane
            let sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));

            this.container.innerWidth = sliceZ.iLength;
            this.container.innerHeight = sliceZ.jLength;

            sliceZ.mesh.material.color.setRGB(0, 1, 1);


           // console.log('Our slice is: ', sliceZ);

            scene.add(sliceZ.mesh);
        }.bind(this));


        this.scene = scene;


        // renderer
        this.renderer = new THREE.WebGLRenderer({alpha: true});
        this.renderer.setPixelRatio(this.container.devicePixelRatio);
        this.renderer.setSize(this.container.innerWidth, this.container.innerHeight);

        // add canvas in container
        this.container.appendChild(this.renderer.domElement);


    },

    animate: function () {

        this.renderer.render(this.scene, this.camera);
    }

}

另外,当我们单击Mouse,进入OnDocumentMouseDown()时,我们会使用这些函数:

let projectRayAndGetIntersectedObject = function () {
    raycaster.setFromCamera(mouse.clone(), OriginalImg.camera);
    var objects = raycaster.intersectObjects(OriginalImg.scene.children);

    console.log(objects);
};

let calculateClickedPointWindowCoordinates = function (event) {
    let realClickedCanvasX = event.offsetX;
    let realClickedCanvasY = event.offsetY;
    return {realClickedCanvasX, realClickedCanvasY};
};

let calculateNormalizedClickedPointCoordinates = function (event) {
    let OriginalImgRenderer = OriginalImg.renderer;
    mouse.x = ( ( event.clientX - OriginalImgRenderer.domElement.offsetLeft ) / OriginalImgRenderer.domElement.clientWidth ) * 2 - 1;
    mouse.y = -( ( event.clientY - OriginalImgRenderer.domElement.offsetTop ) / OriginalImgRenderer.domElement.clientHeight ) * 2 + 1
    return OriginalImgRenderer;
};

let calculateClickedPointColor = function (OriginalImgRenderer, realClickedCanvasX, realClickedCanvasY) {
    var target = OriginalImgRenderer.getRenderTarget();
    console.log('Our target which should be a WebGLRenderTarget is: ');
    console.log(target);

    var outputBuffer = new Uint8Array(OriginalImgRenderer.width * OriginalImgRenderer.height * 4);

    OriginalImgRenderer.readRenderTargetPixels(target, 0, 0, OriginalImgRenderer.width, OriginalImgRenderer.height, outputBuffer);

    var pixelIndex = ((realClickedCanvasX * OriginalImgRenderer.width) + realClickedCanvasY) * 4;

    var color = {
        r: outputBuffer[pixelIndex + 0],
        g: outputBuffer[pixelIndex + 1],
        b: outputBuffer[pixelIndex + 2],
        a: outputBuffer[pixelIndex + 3]
    };

    console.log('Color of clicked pixel is: ');
    console.log(color);
};

我不清楚我们如何解决这个问题。

编辑:3

谢谢@TheJim01您的示例代码解决了问题,在这里我展示了我正在使用的那个:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="chrome=1,IE=edge">
    <title>TEST</title>

    <script src="https://threejs.org/build/three.js"></script>
    <script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
    <script src="js/NRRDLoader.js"></script>
    <script src="js/Volume.js"></script>
    <script src="js/VolumeSlice.js"></script>

</head>

<body>

<canvas id="view" width="500" height="500" style="border: 1px black solid;"></canvas>


<script type="text/javascript">
    /**********************/
    /*   Initialization   */
    /**********************/

    let realClickedCanvasX, realClickedCanvasY, clickCount=0;

    var pixelBuffer = new Uint8Array(500 * 500 * 4);

    function testPixelBuffer() {
        var x, y, r, g, b, a, i1, i2;
        i1 = realClickedCanvasX * size.width;
        i2 = i1 + realClickedCanvasY;
        i2 *= 4;
        r = pixelBuffer[i2 + 0];
        g = pixelBuffer[i2 + 1];
        b = pixelBuffer[i2 + 2];
        a = pixelBuffer[i2 + 3];
            console.log(i2, r, g, b, a);


    }

    document.getElementById('view').addEventListener('mousedown', onDocumentMouseDown, false);

    function onDocumentMouseDown(event) {
        clickCount++;
        realClickedCanvasX = event.offsetX;
        realClickedCanvasY = event.offsetY;
        console.log('You have clicked on: ' + realClickedCanvasY
            + ' , ' + realClickedCanvasY +
            ' it is the click number: ' +
            clickCount);
        testPixelBuffer();
    }

    var renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById("view"),
        antialias: true,
        alpha: true
    });

    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera(28, 1, 1, 1000);
    camera.position.z = 50;

    camera.add(new THREE.PointLight(0xffffff, 1, Infinity));

    scene.add(camera);

    var controls = new THREE.TrackballControls(camera, renderer.domElement);
    controls.addEventListener("change", render);

    /**********************/
    /* Populate the Scene */
    /**********************/

    let loader = new THREE.NRRDLoader();
    loader.load('models/nrrd/columnasegmentado01.nrrd', function (volume) {
        //z plane
        let sliceZ = volume.extractSlice('z', Math.floor(volume.RASDimensions[2] / 4));
        scene.add(sliceZ.mesh);
    });

    /**********************/
    /*   Render Function  */
    /**********************/

    var externalTarget = new THREE.WebGLRenderTarget();
    var size = renderer.getSize();
    externalTarget.setSize(size.width, size.height);

    function render() {
        renderer.render(scene, camera);
        renderer.render(scene, camera, externalTarget);
    }

    render();

    /**********************/
    /*   Animation Loop   */
    /**********************/

    function animate() {
        requestAnimationFrame(animate);
        renderer.readRenderTargetPixels(externalTarget, 0, 0, size.width, size.height, pixelBuffer);
        controls.update();
    }

    animate();

</script>
</body>

</html>

我点击了以下区域:

enter image description here

结果是:

You have clicked on: 81 , 81 it is the click number: 1
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 194324 0 0 0 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 94 , 94 it is the click number: 2
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 440376 23 23 23 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 150 , 150 it is the click number: 3
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 246600 23 23 23 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 195 , 195 it is the click number: 4
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 122780 0 0 0 0
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 210 , 210 it is the click number: 5
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 12840 0 0 0 0
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 310 , 310 it is the click number: 6
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 69240 0 0 0 0
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 271 , 271 it is the click number: 7
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 255084 255 255 255 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 360 , 360 it is the click number: 8
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 495440 23 23 23 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 318 , 318 it is the click number: 9
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 511272 23 23 23 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 291 , 291 it is the click number: 10
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 685164 92 92 92 255
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 283 , 283 it is the click number: 11
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 963132 0 0 0 0
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 180 , 180 it is the click number: 12
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 960720 0 0 0 0
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 174 , 174 it is the click number: 13
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 864696 0 0 0 0
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:51 You have clicked on: 216 , 216 it is the click number: 14
index.html?_ijt=uvc1m089ec37ho5kobp4qir885:40 510864 46 46 46 255

我想知道为什么区域2,3被记录为具有相同的颜色!

我也想知道为什么区域4,5,6会被记录,因为它们颜色相同!

我不完全理解您示例中的以下代码:

function testPixelBuffer() {
        var x, y, r, g, b, a, i1, i2;
        i1 = realClickedCanvasX * size.width;
        i2 = i1 + realClickedCanvasY;
        i2 *= 4;

你能帮我吗?

提前谢谢!

1 个答案:

答案 0 :(得分:2)

WebGLRenderer.readRenderTargetPixels

这使您可以访问渲染目标的缓冲区,就像直接从2D画布的ImageData缓冲区读取数据一样。

// re-usable objects defined outside your mouse event
var size = renderer.getSize();
var reusableTarget = new THREE.WebGLRenderTarget(renderer.width, renderer.height);

// inside your mouse event...
var target = renderer.getRenderTarget() || reusableTarget;

size = renderer.getSize();
target.setSize(size.width, size.height);

renderer.render( scene, camera, target );

var outputBuffer = new Uint8Array( width * height * 4 );

renderer.readRenderTargetPixels( target, 0, 0, width, height, outputBuffer );

var pixelIndex = ((mousePosition.y * width) + mousePosition.x) * 4;

var color = {
  r: outputBuffer[pixelIndex + 0],
  g: outputBuffer[pixelIndex + 1],
  b: outputBuffer[pixelIndex + 2],
  a: outputBuffer[pixelIndex + 3]
};

修改

你是对的,你必须渲染到外部渲染目标。我已经编辑了上面的代码。

如果您在尝试渲染到外部渲染目标时遇到错误,我认为值得创建一个单独的问题(它超出了&#34的范围;如何获得x,y&#34;)处的像素颜色。请参考/链接到这个问题,以便读者了解整个故事。

解决渲染目标问题后,此问题可能会在此过程中得到解决。

添加基于代码段的测试:

老实说,我不确定你为什么会得到你得到的结果。您可以在下面找到一个实现readRenderTargetPixels并成功的简单代码段。

(在浏览器中打开开发者控制台以查看结果。)

&#13;
&#13;
/**********************/
/*   Initialization   */
/**********************/

var pixelBuffer = new Uint8Array( 500 * 500 * 4 );
function testPixelBuffer () {
	var x, y, r, g, b, a, i1, i2;
	for ( x = 0; x < size.width; ++x ) {
		i1 = x * size.width;
		for ( y = 0; y < size.height; ++y ) {
			i2 = i1 + y;
			i2 *= 4;
			r = pixelBuffer[ i2 + 0 ];
			g = pixelBuffer[ i2 + 1 ];
			b = pixelBuffer[ i2 + 2 ];
			a = pixelBuffer[ i2 + 3 ];
			if ( a > 0 ) {
				console.log( i2, r, g, b, a );
        console.count("Colored pixels count:");
			}
		}
	}
}
document.getElementById("test").addEventListener("click", testPixelBuffer);

var renderer = new THREE.WebGLRenderer( {
	canvas: document.getElementById( "view" ),
	antialias: true,
	alpha: true
} );

var scene = new THREE.Scene();

var camera = new THREE.PerspectiveCamera( 28, 1, 1, 1000 );
camera.position.z = 50;

camera.add( new THREE.PointLight( 0xffffff, 1, Infinity ) );

scene.add( camera );

var controls = new THREE.TrackballControls( camera, renderer.domElement );
controls.addEventListener( "change", render );

/**********************/
/* Populate the Scene */
/**********************/

var geo = new THREE.BoxBufferGeometry( 5, 5, 5 );

var mat = new THREE.MeshPhongMaterial( {
	color: "red"
} );

var mesh = new THREE.Mesh( geo, mat );

scene.add( mesh );

/**********************/
/*   Render Function  */
/**********************/

var externalTarget = new THREE.WebGLRenderTarget();
var size = renderer.getSize();
externalTarget.setSize( size.width, size.height );

function render () {
	renderer.render( scene, camera );
	renderer.render( scene, camera, externalTarget );
}
render();

/**********************/
/*   Animation Loop   */
/**********************/

function animate () {
	requestAnimationFrame( animate );
	renderer.readRenderTargetPixels( externalTarget, 0, 0, size.width, size.height, pixelBuffer );
	controls.update();
}
animate();
&#13;
<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="chrome=1,IE=edge">
	<title>TEST</title>

	<script src="https://threejs.org/build/three.js"></script>
	<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>

</head>

<body>

	<input id="test" value="Test Pixel Buffer" type="button" /><br />

	<canvas id="view" width="500" height="500" style="border: 1px black solid;"></canvas>

</body>

</html>
&#13;
&#13;
&#13;