1

I have a Three.js scene containing various objects and some text. It is viewed by a single camera, camera_A whose output goes to a viewport_A in one part of my browser webpage.

Now I want a second camera (camera_B) to view the same scene and pass its output to a second viewport (viewport_B) on another part of the same webpage. Camera_B is the same as Camera_A in every respect except that the image it produces (in the second viewport_B) should be a mirror image of the image in (viewport_A).

I know how to set up different viewports on the same page and and create two identical cameras and send their outputs to the two viewports in a single renderer object (with two render operations).

But what is the best way to produce a mirror image in one of the viewports?


I have tried using the following command:-

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

But when I apply this command the resulting perspective of objects look wrong, see this jsfiddle example: http://jsfiddle.net/steveow/510h3nwv/2/


EDIT:

The answer by stdob does the job OK but requires using a second renderer

(My bad, I did not make clear the wish for a single renderer in original question).

Ideally I would just use one renderer and mirror the image in viewport_B.

steveOw
  • 879
  • 12
  • 41

1 Answers1

1

You can use post processing and custom shader:

THREE.MirrorShader = {

    uniforms: {
        "tDiffuse": { type: "t", value: null }
    },

    vertexShader: [
        "varying vec2 vUv;",
        "void main() {",
            "vUv = uv;",
            "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
        "}"
    ].join("\n"),

    fragmentShader: [
        "uniform sampler2D tDiffuse;",
        "varying vec2 vUv;",
        "void main() {",
            "vec2 mvUv = vec2(1.-vUv.x, 1.-vUv.y);", // Mirror
            "vec4 color = texture2D( tDiffuse, mvUv );",
            "gl_FragColor = color;",
        "}"
    ].join("\n")
};

http://jsfiddle.net/4jmaphjw/

stdob--
  • 28,222
  • 5
  • 58
  • 73
  • 1. The disadvantage with this approach is you lose antialiasing if it is specified in the renderer constructor: `renderer = new THREE.WebGLRenderer( { antialias: true } );` 2. Are you sure you want to flip vUv.y also? – WestLangley Sep 06 '15 at 04:06
  • Thanks but when I flip the objects go from bottom left corner to top right (see this fork of your jsfiddle: http://jsfiddle.net/steveow/5Lu28okb/1/ To flip, in the render function uncomment the line "//do_flip = true;" ) i.e. a rotation?.......Whereas what I want is a single mirror operation, for example the objects would go from bottom left to bottom right. – steveOw Sep 06 '15 at 06:26
  • @steveOw See my comment (2.) above. – WestLangley Sep 06 '15 at 15:12
  • @WestLangley Thanks, I changed the line in fragmentShader to <<< "vec2 mvUv = vec2(1.-vUv.x, +vUv.y);", // Mirror >>> and it works OK but see my next comment. – steveOw Sep 06 '15 at 17:42
  • @stdob With WestLangley's hint I made change as per my above comment and it works good. Thanks. However, ideally I would like to use two viewports on a single renderer. I forgot say this in my original question, sorry. – steveOw Sep 06 '15 at 17:45