THREE.js 1渲染器2视口:摄像机反转无法正常工作

时间:2015-10-05 19:36:37

标签: javascript camera three.js

请参阅jsfiddle

我有一个场景和两个摄像头。 每个摄影机都映射到一个视口,两个视口并排放置在同一个渲染器对象上。

我希望第二台摄像机显示场景的镜像表示。

这是渲染代码。

function render() { 

//... clear entire renderer
renderer.setViewport
    (0             , 0, 
     renderer_width, renderer_height);
renderer.clear();

//... 1st viewport (left)
renderer.setViewport
    (0                   , 0, 
     renderer_width * 0.5, renderer_height);   
renderer.render(scene, camera1);

renderer.clearDepth(); //... seems to have no effect in this case (no VP overlap)

//... 2nd viewport (right)
renderer.setViewport
   (renderer_width * 0.5, 0, 
    renderer_width * 0.5, renderer_height);
renderer.render(scene, camera2);

}

我希望将第二个摄像头的视图反转为看起来像第一个摄像头的视图的镜像反射。我使用以下代码: -

camera2.projectionMatrix.scale(new THREE.Vector3(-1, 1, 1));
camera2.updateProjectionMatrix();

...但是当jsfiddle显示时(当你点击“Invert Camera2(VP2)”按钮时),静态立方体就像从内部看到一样。

N.B。两个视口必须位于同一个渲染器上。 (使用多个渲染器的另一种解决方案是/ u / stdob的答案 - /这里: - (Simulate an optically-inverted (mirror-image) camera in Three.js

编辑20160622

我已经用jsfiddle发布了一个答案。它结合了Lee Stemkoski和West Langley描述的渲染方法。

1 个答案:

答案 0 :(得分:0)

根据/ u / Vito Gentile /的要求,这里的代码适用于当前R78版本的THREE.js

我已将其放入a jsfiddle

HTML

<!--- Using latest THREE.js (r70+) -->
<!-- script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>

<h1 id="title_A">1 camera, 2 displays (1  mirrored)</h1>


<!-- NB In jsfiddle Frameworks & Extensions select No wrap - in <body> -->

CSS

body {
    background-color: #eeeeee;
    margin: 0px;
    overflow: hidden;
}

JAVASCRIPT

//... Copies methods presented by Lee Stemkoski and West Langley.

//... Global variables.
var camera1, camera2, scene, renderer, geometry, material, mybox, mybox2;
var renderer_width, renderer_height;
//

init();
animate();

//-------------------------------------------------------------
function init() {

    scene222 = new THREE.Scene();

    camera1 = new THREE.PerspectiveCamera
                (50, window.innerWidth / window.innerHeight, 1, 10000);

    camera1.position.set(0,350,2500);

    //...no effect these two commands
    camera1.projectionMatrix.scale(new THREE.Vector3(1, 1, 1));
    camera1.updateProjectionMatrix();

    scene222.add(camera1);

    //---------------------------------------------------------

    // 2 BOXES

    var myboxGeometry = new THREE.CubeGeometry(100, 100, 100);
    var myboxMaterial = new THREE.MeshLambertMaterial({
        color: 0x00aaff,
        side: THREE.DoubleSide
    });


    var mybox2Geometry = new THREE.CubeGeometry(150, 150, 150);
    var mybox2Material = new THREE.MeshNormalMaterial();

    mybox = new THREE.Mesh(myboxGeometry, myboxMaterial);
    mybox.position.set(0, 0, 0);
    scene222.add(mybox);

    mybox2 = new THREE.Mesh(mybox2Geometry, mybox2Material);
    scene222.add(mybox2);
    mybox2.position.set(0, -100, 0);

    // LIGHT
    var light = new THREE.PointLight(0xffffff);
    light.position.set(0, 200, 400);

    //var light = new THREE.AmbientLight(0xffffff);
    scene222.add(light);

    //RENDERER
    //renderer = new THREE.CanvasRenderer();
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });

    renderer_width = window.innerWidth;
    renderer_height = window.innerHeight;
    renderer.setSize(renderer_width, renderer_height);
    renderer.setClearColor(0x444444, 1);
    renderer.autoClear = false;
    document.body.appendChild(renderer.domElement);

    //... Need OrbitControls.js.
    camera1.lookAt(0, 0, 0); //R70
    controls1 = new THREE.OrbitControls(camera1, renderer.domElement);
    //...without a controls1 command, no graphics are seen in viewport2.

    //------------------------------------------------------------------

    xxx = F_Init_Scene222_Eyeballs()
}

//-------------------------------------------------------------

function animate() {

    requestAnimationFrame(animate);

    render();

    update();

}

//-------------------------------------------------------------
function update() {

    //mybox.rotation.x += 0.01;
    mybox.rotation.y += 0.015;

}

//-------------------------------------------------------------
function render() 
{

    renderer.clear();

  xxx = F_Render_Eyeball_Stuff();

    renderer.render( scene222, camera1 );

    //xxx = F_Render_Eyeball_Stuff();

}


function F_Render_Eyeball_Stuff()
{

        renderer.clearDepth();

        // put the result of EyeBall_textureCamera into the moby_Buffer which will feed the texture of moby_quad object.

        renderer.render( scene222, EyeBall_textureCamera, moby_Buffer, true );

        renderer.render( moby_Scene, moby_Camera, final_Buffer1, true );

        renderer.render( moby_Scene, moby_Camera, final_Buffer2, true );
}

//-------------------------------------------
function F_Init_Scene222_Eyeballs()
{


    //... EyeBall_textureCamera

    var VIEW_ANGLE = 60;//45, 
  ASPECT = 1;//window.innerWidth / window.innerHeight, 
  NEAR = 0.1, FAR = 50000; 
    EyeBall_textureCamera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
    EyeBall_textureCamera.name ="EyeBall_textureCamera"


    scene222.add(EyeBall_textureCamera);

    EyeBall_textureCamera.position.set( 0,100,200); 

    moby_Scene = new THREE.Scene();

    moby_Camera = new THREE.OrthographicCamera(
    512 / -2, 512  /  2, 
    512 /  2, 512  / -2, 
    /*
        window.innerWidth  / -2, window.innerWidth  /  2, 
        window.innerHeight /  2, window.innerHeight / -2, 
    */
    -10000, 10000 );

    moby_Camera.position.set = (-2200, 0,-1000);
    moby_Scene.add( moby_Camera );


    moby_Buffer = new THREE.WebGLRenderTarget( 512, 512, { format: THREE.RGBFormat } ); 
    var moby_Material = new THREE.MeshBasicMaterial( { map: moby_Buffer } );

    var moby_Geometry = new THREE.PlaneGeometry( 
      512,512
      //window.innerWidth, window.innerHeight 
      );
    var moby_quad = new THREE.Mesh( moby_Geometry, moby_Material );
    // moby_quad.rotation.x = Math.PI / 2;
    moby_Scene.add( moby_quad );


    // final version of camera texture, used in scene. 

    final_Buffer1 = new THREE.WebGLRenderTarget( 512, 512, { format: THREE.RGBFormat } );
    final_Buffer2 = new THREE.WebGLRenderTarget( 512, 512, { format: THREE.RGBFormat } );


    var plane1Material = new THREE.MeshBasicMaterial( { map: final_Buffer1 } );
    var plane2Material = new THREE.MeshBasicMaterial( { map: final_Buffer2 } );

    var planeGeometry = new THREE.CubeGeometry( 512,512,1,1);//(800, 400, 1, 1 );

    var p1x = -350, p1y = 200, p1z = -400;
    var p2x =  350, p2y = 200, p2z = -400;

    //... Plane 1
    var plane1 = new THREE.Mesh( planeGeometry, plane1Material );
    plane1.position.set( p1x, p1y, p1z);
    plane1.rotation.y = Math.PI;    
    scene222.add(plane1);

    //... Plane 2 ( = Plane1 picture but Mirrored in the YZ plane )
    var plane2 = new THREE.Mesh( planeGeometry, plane2Material );
    plane2.position.set( p2x, p2y, p2z );
    plane2.rotation.y = Math.PI;
    //plane2.scale.x = -1; // xxxxx THREE.js doesn't support negative scale factors.

    //... Mirror, reverse the orientation of picture along the x axis.
    //... from West Langley's answer at http://stackoverflow.com/questions/29974578/how-to-flip-a-three-js-texture-horizontally
    plane2.material.map.texture.wrapS = THREE.RepeatWrapping;
    plane2.material.map.texture.repeat.x = -1; 

    scene222.add(plane2);

    EyeBall_textureCamera.lookAt( mybox.position );

    //... Border Planes
    var p1Bx = p1x, p1By = p1y,  p1Bz = p1z-2;
    var p2Bx = p2x, p2By = p2y,  p2Bz = p2z-2;

    var plane1BGeometry = new THREE.CubeGeometry( 540, 540, 1, 1 );
    var plane1BMaterial = new THREE.MeshBasicMaterial( { color: 0xaa2222 } );
    var plane1B = new THREE.Mesh( plane1BGeometry, plane1BMaterial );
    plane1B.position.set( p1Bx, p1By,  p1Bz );
    scene222.add( plane1B );

    var plane2BGeometry = new THREE.CubeGeometry( 540, 540, 1, 1 );
    var plane2BMaterial = new THREE.MeshBasicMaterial( { color: 0x22aa22 } );
    var plane2B = new THREE.Mesh( plane2BGeometry, plane2BMaterial );
    plane2B.position.set( p2Bx, p2By,  p2Bz );
    scene222.add( plane2B );

    //...Eyeball Object, just for checking where the camera is in the scene.

        // Eyeball_Sphere //
        var parameterlist = 
        {   radius: 40, 
            segmentsAlongWidth: 32, 
            segmentsAlongHeight: 16,
            materialType: "Lambert",
            materialColor: 0xffff00,
            objectName: "ob_sphere999",
            posX: 0,
            posY: 0,
            posZ: 0 
        };

        //...make and attach a sphere to visually indicate the camera's position in scene.
        ob_EBsphere1 = SOW_F_grob_Make_New_Sphere ( parameterlist );        

        EyeBall_textureCamera.add ( ob_EBsphere1 ); //... sphere is at camera position

}
//... EOF F_Init_Scene222_Eyeballs()

//==================================================

function SOW_F_grob_Make_New_Sphere( param_list)

{
            sphere_Geometry 
            = new THREE.SphereGeometry( 
                param_list.radius, 
                param_list.segmentsAlongWidth,
                param_list.segmentsAlongHeight);

            if (param_list.materialType == "Lambert")
            {
                sphere_Material 
                = new THREE.MeshLambertMaterial
                ( {color: param_list.materialColor} ); 
            }
            else if (param_list.materialType == "Normal")
            {
                sphere_Material 
                = new THREE.MeshNormalMaterial
                ( { overdraw: 0.2 } ); 
            }
            else if (param_list.materialType == "Basic")
            {
                sphere_Material 
                = new THREE.MeshBasicMaterial
                ( {color: param_list.materialColor} );
            }

            ipObject = new THREE.Mesh(sphere_Geometry, sphere_Material);

            ipObject.position.set(param_list.posX,param_list.posY,param_list.posZ);

            return ipObject;

} //... E O Function  SOW_F_grob_Make_New_Sphere