In three.js, I am trying to create a texture whose image is the current scene as viewed from a Camera. Using a CubeCamera to create a similar effect is well-documented; and with CubeCamera I have created an example of a scene to illustrate my goal at:
http://stemkoski.github.com/Three.js/Camera-Texture-Almost.html
However, I would like to use a regular Camera (rather than a CubeCamera) as the texture. How could I do this?
Ideally this would work.
Init:
renderTarget = new THREE.WebGLRenderTarget( 512, 512, { format: THREE.RGBFormat } );
var planelikeGeometry = new THREE.CubeGeometry( 400, 200, 200 );
var plane = new THREE.Mesh( planelikeGeometry, new THREE.MeshBasicMaterial( { map: renderTarget } ) );
plane.position.set(0,100,-500);
scene.add(plane);
Render:
renderer.render( scene, topCamera, renderTarget, true );
renderer.render( scene, topCamera );
And it almost does, but we have some unfinished business with y-flipped textures that ruins the party here.
So the best solution at the moment is to use the intermediry quad for flipping the texture (also saves a render):
http://mrdoob.github.com/three.js/examples/webgl_rtt.html
Based on mrdoob's example and suggestions, I have created a working example with very detailed comments, available at:
http://stemkoski.github.com/Three.js/Camera-Texture.html
part of my series of tutorial-style Three.js series of examples at
http://stemkoski.github.com/Three.js/
Related
I'm trying to create a three.js cube with different textures on each face.
Basically a dice. This is in my sandbox environment, so should just product a rotating cube with dice images (1-6) on each side. Once done I intend to use this for a browser base game. This example I have only tested in Chrome, although contemplating changing it to a canvas renderer for additional browser support.
Had a look at a few questions here on SO and a substantial amount of other googling, and though I had the answer (seemed reasonably simple actually) but I simply cannot get it to work.
I am reasonably new to three.js, but not JavaScript.
Pages I used for reference are
SO - three.js cube with different texture on each face
SO - three.js cube with different texture faces
evanz - Test three.js cube
and enriquemorenotent.com - three.js building a cube with different materials on each face
My Code
var camera, scene, renderer, dice;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(110, 110, 250);
camera.lookAt(scene.position);
scene.add(camera);
var materials = [
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-1-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-2-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-3-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-4-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-5-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-6-hi.png')
})
];
dice = new THREE.Mesh(
new THREE.CubeGeometry(562, 562, 562, 1, 1, 1, materials),
new THREE.MeshFaceMaterial());
scene.add(dice);
}
function animate() {
requestAnimationFrame(animate);
dice.rotation.x += .05;
dice.rotation.y += .05;
dice.rotation.z += .05;
renderer.render(scene, camera);
}
The error I am getting is
Uncaught TypeError: Cannot read property 'map' of undefined
from three.js line 19546 (not the min version) WHichi is the bufferGuessUVType(material) function - material is undefined. Which leads me to believe something is not right in one/all of my material definitions.
Using three.js r58.
There is really no HTML or CSS, just the JS at this point
I can quite happily get a cube rotating with the same image on all six sides but not with different images. The images are just the images of a dice dots, 1 - 6.
Given a bit more time I could do a fiddle if required
EDIT: THREE.MultiMaterial has been deprecated. You can now pass the materials array directly into the constructor. Like so:
dice = new THREE.Mesh( new THREE.BoxGeometry( 562, 562, 562, 1, 1, 1 ), materials );
scene.add( dice );
Be careful of copying old examples from the net.
Always check the Migration Wiki for help upgrading to the current version.
three.js r.85
I'm trying to learn the capabilities of ThreeJS by making a small game. I have an animated sprite that is working great in my scene by using a PlaneGeometry and using a png texture in my MeshBasicMaterial but unfortunately even though my png has an alpha channel, the mesh is displaying the alpha channel as black when instead I'd prefer it to obviously be transparent. Is there a way to correct this?
//this is a customer function you can see at the top of my codepen
texture = new THREE.SpriteSheetTexture('assets/monster.png', 4, 1, 250, 4);
//loading the basic material here
var material = new THREE.MeshBasicMaterial({
map: texture
});
geometry = new THREE.PlaneGeometry(1, 1, 1, 1);
monster = new THREE.Mesh( geometry, material );
scene.add( monster );
You can view how I have the code laid out here, note though, I cannot get the png resource working on codepen:
https://codepen.io/GreedFeed/pen/yrqpQY
You've to set the .transparent property of the THRRE.Material which states the material transparent and activates the special treatment of transparent objects:
var material = new THREE.MeshBasicMaterial({
map: texture,
transparent: true
});
I'm rewriting this question since I understand more about the bug now. It looks like when using the JSONLoader in r74, the first named bone in an exported Maya scene gets a duplicate of all the geometry.
EDIT: Here's a JSFiddle
In this example I have 2 boxes. Each box is bound to a single bone, and each of those bones has keyframes that animate the position and rotation. There is another bone that has no geometry bound to it, and has keyframes that make no change to its position or rotation.
The stationary bone is called "joint1" in Maya. The bones that actually have geometry bound to them are called "joint2" and "joint3". If I were to rename the stationary bone "joint4" the result would be a duplicate of both boxes attached to the currently animating "joint2".
My guess is that either this is a bug, or I'm doing something wrong when loading the animations. Any tips would be appreciated. The only workaround I can figure out right now is to separate each animated object into a separate file, and that's really not feasible. Plus, that wouldn't solve the issue when I have a multi-bone skeleton. This example is just single bone rigs with no actual deformation.
Here's my current loader code.
//Load Scene, Materials, and Animation
var mixer, mesh;
var actions = {};
var sceneLoader = new THREE.JSONLoader();
sceneLoader.load( sceneFile, function( geometry,materials ) {
materials.forEach( function( material ){
material.skinning = true;
});
mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshFaceMaterial( materials ) );
mixer = new THREE.AnimationMixer( mesh );
actions.main = mixer.clipAction( geometry.animations[ 0 ]);
actions.main.setEffectiveWeight( 1 );
actions.main.play();
scene.add( mesh );
});
//Render
var render = function () {
requestAnimationFrame( render );
controls.update;
var delta = clock.getDelta();
var theta = clock.getElapsedTime();
if ( mixer ) { mixer.update( delta ); }
renderer.render(scene, camera)
}
render();
This is still an issue, but I've found an ok workaround.
Since the duplicated geometry always gets assigned the default lambert shader that is always included when using the Maya Exporter. As long as all the objects that are intended to be kept have a material other than the default in Maya, you can insert
mesh.material.materials[0].visible = false;
into the loader code which will make any material with the default lambert invisible.
Here's a fiddle
A current Three.js application I am developing requires a lot of independent lights and so would benefit from a deferred lighting renderer.
Resources I have so far read on this suggest using WebGLDeferredRenderer, however when I define a renderer object as they suggest:
var renderer = new THREE.WebGLDeferredRenderer({
width: window.innerWidth,
height: window.innerHeight,
scale: 1, antialias: true,
tonemapping: THREE.FilmicOperator, brightness: 2.5 });
and call the renderer as follows to draw the scene:
renderer.render( scene, camera );
I get a blank screen, whereas if I use the standard WebGL renderer my scene is correctly rendered.
renderer = new THREE.WebGLRenderer( { antialias: true } );
I can't seem to find a suitable example of implamenting deferred lighting in three.js. Am I missing a library? I only have three.js linked. perhaps this requires an additional library?
In my clone of three.js I can't find a copy of WebGLDeferredRenderer.js.
WebGLDeferredRenderer has been removed. See this post for more information, and follow the links to access the old code.
three.js r.73
I'm trying to create a three.js cube with different textures on each face.
Basically a dice. This is in my sandbox environment, so should just product a rotating cube with dice images (1-6) on each side. Once done I intend to use this for a browser base game. This example I have only tested in Chrome, although contemplating changing it to a canvas renderer for additional browser support.
Had a look at a few questions here on SO and a substantial amount of other googling, and though I had the answer (seemed reasonably simple actually) but I simply cannot get it to work.
I am reasonably new to three.js, but not JavaScript.
Pages I used for reference are
SO - three.js cube with different texture on each face
SO - three.js cube with different texture faces
evanz - Test three.js cube
and enriquemorenotent.com - three.js building a cube with different materials on each face
My Code
var camera, scene, renderer, dice;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(110, 110, 250);
camera.lookAt(scene.position);
scene.add(camera);
var materials = [
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-1-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-2-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-3-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-4-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-5-hi.png')
}),
new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('/Content/Images/dice-6-hi.png')
})
];
dice = new THREE.Mesh(
new THREE.CubeGeometry(562, 562, 562, 1, 1, 1, materials),
new THREE.MeshFaceMaterial());
scene.add(dice);
}
function animate() {
requestAnimationFrame(animate);
dice.rotation.x += .05;
dice.rotation.y += .05;
dice.rotation.z += .05;
renderer.render(scene, camera);
}
The error I am getting is
Uncaught TypeError: Cannot read property 'map' of undefined
from three.js line 19546 (not the min version) WHichi is the bufferGuessUVType(material) function - material is undefined. Which leads me to believe something is not right in one/all of my material definitions.
Using three.js r58.
There is really no HTML or CSS, just the JS at this point
I can quite happily get a cube rotating with the same image on all six sides but not with different images. The images are just the images of a dice dots, 1 - 6.
Given a bit more time I could do a fiddle if required
EDIT: THREE.MultiMaterial has been deprecated. You can now pass the materials array directly into the constructor. Like so:
dice = new THREE.Mesh( new THREE.BoxGeometry( 562, 562, 562, 1, 1, 1 ), materials );
scene.add( dice );
Be careful of copying old examples from the net.
Always check the Migration Wiki for help upgrading to the current version.
three.js r.85