Rendering to texture within a-frame - three.js

I'm trying to implement something very similar to this...
https://stemkoski.github.io/Three.js/Camera-Texture.html
... as an a-frame component. However, I'm getting merely a blank white on the quad which is supposed to be "monitoring" this extra camera. It changes to black when entering VR mode.
Here is my code:
AFRAME.registerComponent('viewfinder', {
schema:{
//
},
init:function(){
this.renderer = new THREE.WebGLRenderer({antialias:true});
this.renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(this.renderer.domElement);
this.dronecamera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
this.dronecamera.position.z=5;
this.monitorbuffercam = new THREE.OrthographicCamera(window.innerWidth/-2, window.innerWidth/2, window.innerHeight/2, window.innerHeight/-2, -10000, 10000);
this.monitorbuffercam.position.z=1;
this.buffertexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { format: THREE.RGBFormat });
this.monitortexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { format: THREE.RGBFormat });
this.bufferscene = new THREE.Scene();
var ambientlight = new THREE.AmbientLight(0xffffff);
this.bufferscene.add(ambientlight);
var bufferplaneG = new THREE.PlaneGeometry( window.innerWidth, window.innerHeight);
var bufferplaneM = new THREE.MeshBasicMaterial({map:this.buffertexture});
this.bufferplane = new THREE.Mesh(bufferplaneG, bufferplaneM);
this.bufferscene.add(this.bufferplane);
this.bufferscene.add(this.monitorbuffercam);
this.el.sceneEl.object3D.add(this.dronecamera);
this.monitorplaneG = new THREE.PlaneGeometry(10, 10);
this.monitorplaneM = new THREE.MeshBasicMaterial({map:this.monitortexture});
this.monitor = new THREE.Mesh(this.monitorplaneG, this.monitorplaneM);
this.el.setObject3D('monitor', this.monitor);
},
tick:function(){
var r = this.renderer;
var s = this.el.sceneEl.object3D;
var bs = this.bufferscene;
var dc = this.dronecamera;
var bt = this.buffertexturee;
var mbc = this.monitorbuffercam;
var mt = this.monitortexture;
requestAnimationFrame(draw);
function draw(){
r.render(s, dc, bt, true);
r.render(bs, mbc, mt, true);
}
}
});
Any help is greatly appreciated. I'm attempting to follow the model from the three.js example, rendering from a camera in the main scene to a quad texture map in a separate off-screen scene, then pointing an orthographic camera at it, and rendering that camera's view to a texture map back in the main scene. I have a hunch that there is merely some boilerplate code I'm forgetting or I'm doing wrong.
Thanks in advance!

I'm not sure if this what you're looking for, but maybe this answer to AFrame: How to render a camera to a texture could be of some help. In short, it shows how to use a component that creates a renderer for a secondary camera, that can be referenced as material for an object.

Related

Manually specifying camera matrices in ThreeJS

I'm working on a project where I will draw 3D graphics on a video that is filmed with a real camera. I get provided a static projection and view matrix and my task is to draw the actual graphics on top. I've got it working in pure WebGL and know I'm trying to do it in ThreeJS. The problem is that I can't find a way to manually set the projection and view matrix for the camera in ThreeJS.
I've tried to set camera.matrixAutoUpdate = false and calling camera.projectionMatrix.set(matrix) and camera.matrixWorldInverse.set(matrix), but it doesn't seam to work. It is like the actual variable isn't passed to the shader.
Does anyone know how this can be done?
This is what I've got so far:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.matrixAutoUpdate = false;
camera.projectionMatrix.set(...)
camera.matrixWorldInverse.set(...)
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BoxGeometry();
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();

three.js: Image in panorama viewer is rippled

Currently I'm making myself familiar with three.js and created a simple panorama viewer:
http://webentwicklung.ulrichbangert.de/threejs-image-on-sphere-inside.html
Unfortunately the vertical edges of the pillars are rippled.
When using the panorama viewer of Panorama Studio everything is fine:
http://ulrichbangert.de/heimat/Halberstadt/2018-06-10_Halberstadt_Dom_Panorama.html
var width = window.innerWidth,
height = window.innerHeight;
var scene = new THREE.Scene();
scene.add(new THREE.AmbientLight(0x333333));
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(5, 3, 5);
scene.add(light);
var camera = new THREE.PerspectiveCamera(45, width / height, 0.01, 1000);
camera.position.z = 1;
camera.fov = Math.max(100, Math.min(200, camera.fov));
camera.updateProjectionMatrix();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var loader = new THREE.TextureLoader();
loader.load('images/panorama.jpg', function (texture) {
texture.anisotropy = renderer.getMaxAnisotropy();
var material = new THREE.MeshBasicMaterial({
map: texture
});
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(20, 32, 32),
material
);
sphere.scale.x = -1;
sphere.rotation.x = -0.5;
scene.add(sphere);
var animate = function () {
requestAnimationFrame(animate);
sphere.rotation.y += 0.002;
renderer.render(scene, camera);
};
animate();
});
What's going wrong here?
Try adding more subdivisions to your SphereGeometry. Right now you have 32 lat & long subdivisions, which creates some unsightly straight-line deformations to your texture. If you do something like new THREE.SphereGeometry(20, 100, 100), you'll get better fidelity when texture mapping.

three.js - Model showing with blank (black) texture despite material loaded

I have a 3D model file 3dbaotang.obj and a material file 3dbaotang.mtl. I've loaded both of them using three.js OBJLoader and MTLLoader. The model has shown up, but not the material, as it's solely covered with black. Can anyone help?
Here is my code:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth /
window.innerHeight, 0.1, 10000);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var keyLight = new THREE.DirectionalLight('hsl(30, 100%, 75%)', 1.0);
var fillLight = new THREE.DirectionalLight('hsl(240, 100%, 75%)', 0.75);
var backLight = new THREE.DirectionalLight(0xffffff, 1.0);
backLight.position.set(100, 0, -100).normalize();
keyLight.position.set(-100, 0, 100);
fillLight.position.set(100, 0, 100);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
controls.update();
renderer.setSize(window.innerWidth, window.innerHeight, false);
renderer.setClearColor(new THREE.Color(0xf2f2f2), 1);
document.body.appendChild(renderer.domElement);
// LOAD MODEL
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setResourcePath('/models/');
mtlLoader.setPath('/models/');
mtlLoader.load('/3dbaotang.mtl', (materials) => {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('/models/');
objLoader.load('3dbaotang.obj', (object) => {
scene.add(object);
});
});
camera.position.z = 200;
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
Result:
Adding to Brother Eye's answer, I'm brand new and and spent quite a lot of time in the dark but this got me on to the solution so I thought I'd elaborate for anyone in the same position.
Adding a light can be some simply as follows;
//Add light
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
The reference docs are located at https://threejs.org/docs/#api/en/lights/AmbientLight
It was the lack of light that caused this problem, not the material. After adding ambient light to the scene, the object can be seen normally

Three.js not rendering cube with custom texture

I'm trying to render a three.js box that has custom textures which I'm loading using THREE.TextureLoader().
While I see THREE.WebGLRenderer 87 in my console, there doesn't seem to be any cube being rendered.
I've created a fiddle to show how I'm attempting to do it: http://jsfiddle.net/hfj7gm6t/4786/
Note that I'm just using one url for all 6 side's textures for simplicity's sake.
Can anybody please help me understand why my beloved cube isn't showing?
First you need a render loop, you cannot just call renderer.render once. Then you need to position your camera correctly and make sure it is actually looking at your cube:
let textureUrls = [
'https://i.imgur.com/wLNDvZV.png', 'https://i.imgur.com/wLNDvZV.png', 'https://i.imgur.com/wLNDvZV.png',
'https://i.imgur.com/wLNDvZV.png', 'https://i.imgur.com/wLNDvZV.png', 'https://i.imgur.com/wLNDvZV.png'
];
let renderer = null
let camera = null
let scene = null
function renderMap(urls) {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
60, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.x = 500;
camera.position.y = 500;
camera.position.z = -500;
camera.lookAt(new THREE.Vector3(0, 0, 0))
let textureLoader = new THREE.TextureLoader();
let materials =
urls.map((url) => {
return textureLoader.load(url);
}).map((texture) => {
return new THREE.MeshBasicMaterial({map: texture})
});
let mesh = new THREE.Mesh(new THREE.BoxGeometry(200, 200, 200), materials);
scene.add(mesh);
}
function init() {
renderMap(textureUrls);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
render();
}
function render() {
requestAnimationFrame(render)
renderer.render(scene, camera)
}
init()

Texture in three.js no console errors still not working

I'm new to three.js and need to make a project for school. For this project I need a texture on my cube. But the screen stays black.. and there are no console errors! I did everything I can so this is kinda my last change haha.
My code:
<script src="js/three.min.js"></script>
<script>
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 );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
// +
var material = new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('images/crate2.jpg')
})
// =
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.1;
cube.rotation.y += 0.05;
renderer.render(scene, camera);
};
render();
</script>
You do not have a light in your scene.
Adding one like below should work
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0xffffff); // white light
scene.add(light);
I would add a link to a js fiddle but it seems they have changed and I can not longer find where to get the link.
Anyway, just ad some sort of light.
Perhaps adding a light would help? That or try using THREE.MeshBasicMaterial

Resources