Is it possible to Outline a view port in threejs? - three.js

I've created a scene with two cameras and one renderer. each camera is looking at the scene from a different angle and I have the first camera rendering on the entire screen then the second camera I have rendering in a small view port laying on top of the first render. I was wondering if there is a way to have that second view port outlined so that each look separate

Yes, you can outline an inset viewport by rendering a solid-colored rectangle slightly larger than the inset prior to rendering the inset.
// border
renderer.setScissorTest( true );
renderer.setScissor( x, y, width, height );
renderer.setClearColor( 0xffffff, 1 ); // border color
renderer.clearColor(); // clear color buffer
Then, render the inset. Just make sure the inset background is opaque.
three.js r.86

I guess you are using threejs viewport feature? As far as I know, by itself, it does not have such a feature.
But since it is rendered on to canvas... maybe you could draw an outline by yourself on canvas in desired coordinates, after each threejs render frame?
A basic example:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rect(20,20,150,100);
ctx.stroke();
(reference: https://www.w3schools.com/tags/canvas_rect.asp)

Related

Reference existing WebGL depth buffer when rendering a new ThreeJS scene

I have an existing WebGL canvas that is being rendered without using ThreeJS, and is for all intents and purposes a black box to me, apart from two facts: (1) I have access to the underlying webgl canvas DOM element and can position and resize it on the screen, and (2) I know the properties of the camera for the scene, and get updates on every render cycle for that camera.
The problem I need to solve can be simplified to the following: I need to have my own separate ThreeJS canvas that displays both the black box canvas data, and then elements that I draw, like a cube for a simple example. I can already easily overlay the two canvases, set the transparency on my canvas for everything but the cube, and then align the two with the camera events from the black box library. This works quite well.
The issue with this is that when I draw my objects, like a cube, they don't respect the depth buffer of the black box canvas. So I might have a cube that is properly aligned with the backing scene and movements of the scene, but then it isn't properly masked when something in the black box canvas is closer to the camera than the cube. My thought is that I need to solve this in one of two ways: (1) I can have my renderer write to the other canvas with autoClear = false and preserveDrawingBuffer = true, or (2) I can somehow copy the depth buffer from the black box canvas into my canvas, and then set up my renderer so that it respects the new depth buffer.
I haven't been successful with either approach yet, so I'm wondering if this is possible, and if so which of the above approaches, or what other approach, can solve this problem?
--Edit--
See https://jsfiddle.net/zdxyoajb/ for angular/typescript implementation of the above attempts. In the following animate loop, if I comment out the overlayRenderer lines, the below sphere will be red and offset from the center (as it should be), but if I don't comment the lines, I get the below image. I also get the following error:
WebGL: INVALID_OPERATION: uniformMatrix4fv: location is not from current program
animate() {
requestAnimationFrame(() => this.animate());
this.blackBoxCamera.copy(this.overlayCamera);
this.blackBoxRenderer.render(this.blackBoxScene, this.blackBoxCamera);
this.overlayRenderer.state.reset();
this.overlayRenderer.render(this.overlayScene, this.overlayCamera);
}

Scale that resizes with zoom (threejs + orthographic view)

I'd like to add a scale in my scene, then resize the scale on zoom.
I work with an orthographic camera and the trackball orthographic controller.
The scale lets the user know the dimensions of the image he is looking at - (see green scale on the left of the screenshots)
Before zoom:
After zoom:
Which would be the best approach with THREEJS?
- have a 'scale' object in the scene and resize it somehow?
- overlay a div on top of the renderer and also resize it somehow?
- overlay a new renderer?
Is there any example of such implementation somewhere already?
Best,

Three.js - transparent objects when rotated with TrackballControls don't behave like transparent

When I add to the scene two objects and set their transparency as true with some opacity and using TrackballControls I rotate the scene by mouse, the object which was initially further from camera loses its transparency.
I read that this is Z-buffer problem and further objects from camera will be displayed first. But when I rotate the scene using TrackballControls, camera changes its position, so transparent objects should be displayed correctly. But it is not like that.
Here in this picture - on the right is frontview, on the left is backview which is not displayed correctly:
http://www.foto-ondruskova.cz/Experiment/lenses.jpg
Please, any solutions?
I have come across this problem and setting alphaTest: 0.5 to the material as suggested here solved my problem. But it is hit and miss. Give it a try. Hopefully it works!

Is it possible in three.js to crop the viewport?

I have a scene with a sphere in the middle and a camera spinning around it. Now I was wondering if it is possible with Three.JS to make a crop of this viewport so that the sphere for example would appear on the left or right.
I'm not looking to moving the camera or looking at a point besides the sphere, since that would distort the perspective, but a clip or crop of the rendering.
Is this possible?
One potential solution is to position a second canvas over your Three.js canvas, then re-draw the three.js scene onto your second canvas by blitting:
overlayCanvas.getContext('2d').drawImage(threeCanvas, 40, 40, 960, 960, 0, 0, 1200, 1200);
You can read more about the parameters to drawImage() in the documentation, but what this does is crop a certain area of the three.js canvas and stretch it over a larger area of your second canvas. It should be much faster than rendering the scene a second time, and it will display at the size you want it (albeit with some stretching).
You can alleviate the stretching by drawing the original (three.js) scene at a larger size than it would normally be displayed such that the area you want to crop into view is the same size as your secondary canvas.

background occlusion

I'm trying to render 2 scenes. The first scene is just a 2D background plane. In the second scene i have set to objects. The first objects (a head) material-opacity is set to 1. I thought this was an easy and fast way to calculate the occlusion for the second object (sunglasses) in the scene. In fact that work exactly like I wanted, but now the head is also occluding the background even though he should be transparent. ( I cleared the depth buffer before rendering the second scene and set renderer.autoClear = false )
renderer.autoClear = false;
var headMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, opacity: 1 });
...
//Renderloop
renderer.clear();
renderer.render( background, camera );
renderer.clear(false,true,false);
renderer.render( scene, camera);
Is there a compelling reason for rendering two scenes, rather than just one scene that contains all objects? They share the same camera, no?
Try rendering the head and sunglasses first. Mask the sunglasses with a stencil. Then render the background with a stencil test (but not depth test). You'll render fewer background pixels, resulting in a bit faster overall render.
If by saying "background" you mean a scene with only plane that has some texture on in - why don't you set your background as html background? That was you won't have to calculate your plane's right position to fill all thre screen area.
Now, for transparency issue - here is some example for you: http://jsfiddle.net/ajJmx/1/
See how you've got your front cube side set to semi-transparent and you can see othe sides of cube. And if you turn cube 45deg - you'll see that even though there is some other object on the background - your solid cube sides stay solid.
What you basically want to do is to set transparent:true, opacity:0.6 to your sunglasses material. That's it! You could also play around with material blendings and try to set blending:THREE.AdditiveBlending depending on you sunglasses type.

Resources