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

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.

Related

Black sphere within skybox sphere forms when I try using a giant sphere to create a skybox in threejs

I'm trying to make a spherical skybox since I think that would best fit the space scene I'm making. I'm running across two issues:
I can get the skybox to work, but for some reason a sphere within my giant sphere I've made appears. I don't think its a real Object3D sphere, I have the feeling its a graphical glitch of some sort.
If I make the sphere too big (Like 1800 for the radius) it just disappears and stops working. If I set it's side to THREE.DoubleSide, I can zoom out of the scene and still see its outer side of the sphere, but inside, regardless of DoubleSide or BackSide, its invisible when 1800 or bigger
let skyboxGeom = new SphereGeometry(900, 128, 128)
let skyboxMat = new THREE.MeshPhongMaterial({map: spaceTexture});
skyboxMat.side = THREE.BackSide
let skybox = new THREE.Mesh(skyboxGeom, skyboxMat);
skybox.position.set(0,0,0)
mainScene.add(skybox)
Here is a picture of what it looks like:
The colorful ball is correct, the inner black sphere is what appears incorrectly. If I zoom in enough to the scene, the black ball shrinks and gets smaller and smaller until it disappears entirely, but I would have to zoom way too far into my scene that none of my things would show if I tried to do this to make the black ball go away
If it helps, I am using a PerspectiveCamera, and am exploring the scene using OrbitControls

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);
}

Is it possible to Outline a view port in threejs?

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)

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,

Modify shapes using javascript in HTML Canvas

I have started learning CANVAS. After i started drawing some basic shapes, i wanted to make some modifications to them. For example, I am confused of how to modify length and width of rectangle. Should i have to clear the canvas and redraw or can i capture the object of that rectangle like the objects in java script.
The canvas is a raster graphics surface. modifying length and width of a rectangle is a vector action. It is possible to scale a raster, but losses in quality can/will occur. You can use vector graphics in the form of SVG. But if it is only a rectangle, use a div with a border overlay-ed on your canvas.

Resources