In ThreeJS (JavaScript/ WebGL) how can I create a static background image that is part of the scene but resizes to fit the full inner browser window exactly? It works when I use CSS but then the background image won't show when making a "screenshot" via renderer.domElement.toDataURL('image/png'), which I want to. Thanks!
You can use a separate background scene to render the background image.
var bg = new THREE.Mesh(
new THREE.PlaneGeometry(2, 2, 0),
new THREE.MeshBasicMaterial({map: backgroundTexture})
);
// The bg plane shouldn't care about the z-buffer.
bg.material.depthTest = false;
bg.material.depthWrite = false;
var bgScene = new THREE.Scene();
var bgCam = new THREE.Camera();
bgScene.add(bgCam);
bgScene.add(bg);
Then in your render loop, draw bgScene before your real scene.
renderer.autoClear = false;
renderer.clear();
renderer.render(bgScene, bgCam);
renderer.render(scene, cam);
It wasn't clear for me if you are trying to make a panorama viewer or something like that...
If that was your goal, here's an answer I gave to solve the problem of inserting an equirectangular image to the rendered sphere (which can be controlled by mouse and/or deviceOrientation[accelerometer in smartphones]):
https://stackoverflow.com/a/37129356/1920145
Related
//textures
let loader=new THREE.TextureLoader()
let stars = loader.load("./../static/textures/stars3.jpg");
//BACKGROUND
scene.background = new THREE.CubeTextureLoader()
.load([
"./../static/textures/stars2.jpg",
"./../static/textures/stars3.jpg",
"./../static/textures/stars2.jpg",
"./../static/textures/stars3.jpg",
"./../static/textures/stars2.jpg",
"./../static/textures/stars3.jpg",
]);
// scene.background = loader.load(
// "./../static/textures/stars3.jpg"
// );
the stars image are not showing as 3d background. When I use simple textureloader to load just one static image it works as the background but not cubetextureloader.
I don't get any errors just 3 warnings
"GL_INVALID_VALUE: Each cubemap face must have equal width and height.",
"GL_INVALID_OPERATION: Level of detail outside of range.", * 6
"GL_INVALID_OPERATION: Texture format does not support mipmap generation."
All I get is a black background.
I have a model, a background sky and a ground surface. Texturing the surface results in no surface.
I've tried the basic approach and come to the conclusion that it is probably that the scene is being rendered before the texture has finished loading. Having searched and found various possible solutions, I have tried several of them, without really understanding how they are supposed to work. None of them has worked. One problem is that it is an old problem and most of the suggestions involve outdated versions of the three.js library.
// Ground
// create a textured Ground based on an answer in Stackoverflow.
var loader = new THREE.TextureLoader();
loader.load('Textures/Ground128.jpg',
function (texture) {
var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({map: texture});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true; //Illumination addition
ground.rotation.x = -0.5 * Math.PI; // rotate into the horizontal.
scene.add(ground);
}
);
// This variation does not work either
http://lhodges.users37.interdns.co.uk/me/downloads/Aphaia/Temple.htm
http://lhodges.users37.interdns.co.uk/me/downloads/Aphaia/Temple7jsV0.15b.htm
The first of the above is the complete page in which the ground is a plain billiard table green. The second is the page containing the above code.
There appear to be no error (Last time I tried.)
By the time your texture loads and you add the ground, your scene has already rendered (and there is no other render call).
You need to call renderer.render(scene, camera); after adding the ground to the scene.
// Ground
// create a textured Ground based on an answer in Stackoverflow.
var loader = new THREE.TextureLoader();
loader.load('Textures/Ground128.jpg',
function (texture) {
var groundGeometry = new THREE.PlaneBufferGeometry(2000, 2000, 100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({map: texture});
var ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true; //Illumination addition
ground.rotation.x = -0.5 * Math.PI; // rotate into the horizontal.
scene.add(ground);
renderer.render(scene, camera); // <--- add this line
}
);
I'm just getting started with webgl and was trying to make an animation based on a spritesheet. I've found an example and changed the spritesheet to my own. However even though I removed the white background, saved it as a transparant png, the animation still shows up with a white background.
This is the example I used:
http://stemkoski.github.io/Three.js/Texture-Animation.html
Is there any way how I can get rid off the white background?
Thanks in advance.
EDIT:
var runnerTexture = new THREE.ImageUtils.loadTexture( 'images/run.png' );
annie = new TextureAnimator( runnerTexture, 10, 1, 10, 75 ); // texture, #horiz, #vert, #total, duration.
var runnerMaterial = new THREE.MeshBasicMaterial( { map: runnerTexture, side:THREE.DoubleSide } );
var runnerGeometry = new THREE.PlaneGeometry(50, 50, 1, 1);
var runner = new THREE.Mesh(runnerGeometry, runnerMaterial);
runner.position.set(-150,25,0);
scene.add(runner);
To support PNGs with an alpha-channel, you have to modify the MeshBasicMaterial accordingly: There is an attribute 'transparent' which you could set to 'true'.
Try using the following line instead:
var runnerMaterial = new THREE.MeshBasicMaterial( { map: runnerTexture, side:THREE.DoubleSide, transparent: true } );
See also the reference from Material:
.transparent
Defines whether this material is transparent. This has an effect on
rendering as transparent objects need special treatment and are
rendered after non-transparent objects. For a working example of this
behaviour, check the WebGLRenderer code. When set to true, the extent
to which the material is transparent is controlled by setting opacity.
This is my code:
var sprite = new THREE.Sprite(material);
sprite.renderDepth = 10;
The above renderDepth setting is invalid, it does not work for sprites.
How to solve this problem?
You want one sprite to always be on top.
Since SpriteMaterial does not support a user-specified renderDepth, you have to implement a work-around.
Sprites are rendered last when using WebGLRenderer.
The easiest way to do what you want is to have two scenes and two render passes, with one sprite in the second scene like so:
renderer.autoClear = false;
scene2.add( sprite2 );
then in the render loop
renderer.render( scene, camera );
renderer.clearDepth();
renderer.render( scene2, camera );
three.js r.64
I'm trying the second approach to use Text in three.js, drawing on a canvas and using the result as a texture. It basically works, except for the following problem -don't know if it's a bug:
I create two texts, with transparent background, and overlap then. They show ok, but when I rotate one of them, the transparency is messed up.
I create the text objects with following (excerpt) function
function createText(text, ...){
var textHolder = document.createElement( 'canvas' );
var ctext = textHolder.getContext('2d');
...
var tex = new THREE.Texture(textHolder);
var mat = new THREE.MeshBasicMaterial( { map: tex, overdraw: true});
mat.transparent = true;
mat.map.needsUpdate = true;
var textBoard = new THREE.Mesh(new THREE.PlaneGeometry(textHolder.width, textHolder.height),mat);
textBoard.dynamic = true;
textBoard.doubleSided = true;
return textBoard;
}
and add them to the scene.
See demonstration with full code in jsfiddle
Transparency is tricky in webGL.
The best solution in your case is to do the following for your transparent text material:
mat.depthTest = false;
updated fiddle: http://jsfiddle.net/SXA8n/4/
three.js r.55