通过Three.js中的getImageData像素颜色数据循环生成多个立方体

Making Multiple Cubes from Looping Through getImageData pixel color data in Three.js

本文关键字:循环 立方体 数据 颜色 js Three 中的 getImageData 像素 通过      更新时间:2023-09-26

我使用一个简单的3x3.png文件从中检索颜色/不透明度数据。(9个像素中的每一个都是不同的颜色/不透明度)。

.png被加载并应该在屏幕外单独的画布中,然后9个立方体应该以3x3的形式绘制。

我认为这真的很接近效果,但显然出了问题。

<!DOCTYPE html>
<head>
<title>a png made into cubes per pixel</title>
<style>body {margin: 0px;background-color: #99F;overflow: hidden;}</style>
<script src="js/three.min.js"></script>
</head>
<body>
<!-- the 3x3 png image pre-loading -->
<img id='image1' src='3x3.png' onload="javascript:loaded();">
<canvas id='canvas'></canvas>

<script>
    function loaded(){
    var img = new Image();
    img.src = document.getElementById("image1").src;
    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.drawImage(img, 0, 0);
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    camera.position.z = 5;
    var geometry = new THREE.BoxGeometry( 1, 1, 1 );
    for (ix = 0; ix < img.width; ix++) { 
        for (iy = 0; iy < img.height; iy++) { 
            // get next pixel data
            var data = ctx.getImageData( ix, iy, 1, 1 ).data;
            var floats = data.slice( 0, 4 ).map( function( val ) { return val / 255; });
            var computedcolor = THREE.Color( floats[0], floats[1], floats[2] );
            var computedopacity = floats[4];
            var material = new THREE.MeshBasicMaterial( { color: computedcolor, opacity: computedopacity, side: THREE.DoubleSide } );
            var cube = new THREE.Mesh( geometry, material );
            scene.add( cube );
            cube.position.x = ix; //move the cube positions to rebuild the image using cubes instead of pixels
            cube.position.y = iy;
        }
    }
    var render = function () {
        requestAnimationFrame( render );
        camera.position.z = camera.position.z + .01;
        renderer.render(scene, camera);
    }
    render();
    }
</script>
</body>
</html>

var computedopacity = floats[4]应改为var computedopacity = floats[3]

然而,我不知道这是否能解决问题。我没有试图找到问题所在,而是从头开始编码了你想要做的事情:

function boxelizeImage( image ) {
    // 2D
    var canvas = document.createElement( 'canvas' );
    canvas.width = image.width;
    canvas.height = image.height;
    var context = canvas.getContext( '2d' );
    context.drawImage( image, 0, 0 );
    var data = context.getImageData( 0, 0, canvas.width, canvas.height ).data;
    // 3D
    var group = new THREE.Group();
    var geometry = new THREE.BoxGeometry( 1, 1, 1 );
    for ( var i = 0, j = 0; i < data.length; i += 4, j ++ ) {
        var color = new THREE.Color();
        color.fromArray( data, i );
        color.multiplyScalar( 1 / 255 );
        if ( color.getHex() === 0 ) continue;
        var material = new THREE.MeshBasicMaterial( {
            color: color,
            wireframe: true,
        } );
        var mesh = new THREE.Mesh( geometry, material );
        mesh.position.x = j % canvas.width;
        mesh.position.y = - Math.floor( j / canvas.width );
        group.add( mesh );
    }
    return group;
}
//
var camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 500 );
camera.position.x = 15;
camera.position.y = -10;
camera.position.z = 80;
var scene = new THREE.Scene();
var image = new Image();
image.addEventListener( 'load', function () {
    var group = boxelizeImage( image );
    scene.add( group );
    renderer.render( scene, camera );
} );
image.src = '../img/logo.png';
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

http://jsfiddle.net/44mj229c/