Scene-wide envmap for HDR lighting in three.js - three.js

I want to try and use an HDR image for my lighting.
I have tried doing
var envmap = new THREE.TextureLoader().load( "./assets/wooden_lounge_1k.hdr" );
scene.environment = envmap;
but all the objects in my scene are black in color.
I have seen some demos but they usually set the envmap property in the material for a single object, but I want to have the HDR lighting to be applied on all objects in the scene.
How would I do this?
thanks!

I found a JSFIDDLE website that had some code that would help me. It used the RGBELoader, but it had some extra stuff.
What I did:
function setLighting(){
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setPath( 'https://threejs.org/examples/textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
var envMap = pmremGenerator.fromEquirectangular( texture ).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
})
var pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
}

var envmap = new THREE.TextureLoader().load( "./assets/wooden_lounge_1k.hdr" );
You have to load HDR textures with THREE.RGBELoader (and not with THREE.TextureLoader). I suggest you study the following official example for more information:
https://threejs.org/examples/webgl_loader_texture_hdr

Enter THREE.RGBELoader
Instead of THREE.TextureLoader
I think you should paste this:
var envmap = new THREE.RGBELoader().load( "./assets/wooden_lounge_1k.hdr" );
scene.environment = envmap;
I hope it works

Related

Ready Player Me Avatar texture/lightning rendering in ThreeJS and Matterport

I try to import a Ready Player Me GLB avatar into a Matterport scene (in ThreeJS).
It works but the avatar is very flat (left picture) compared to the rendering into RPM (right picture) or basic GLTF Viewer. I don't understand what I missed ? Pseudo code :
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('https://api.readyplayer.me/v1/avatars/63580183b445da7aa57b9ce3.glb',
(gltf) => {
this.mesh = gltf.scene;
const light = new THREE.AmbientLight( 0xFFFFFF, 1 );
light.castShadow = true
this.mesh.add( light );
...
}, undefined);
On the WebGL part I have access to Matterport renderer :
(renderer, THREE, effectComposer) => {
renderer.outputEncoding = THREE.sRGBEncoding
renderer.toneMapping = THREE.ACESFilmicToneMapping
}
Is it related to Antialias ? Or a paramter or lighting that flatten hair and hands ? Or is it related to texture ?
Thanks !
EDIT 11/12/2022:
Thanks to #Mugen87, I find how to use the EquirectangularShader from GLTFLoader sample. This code works with Matterport context.
let pmremGenerator = new THREE.PMREMGenerator( this.context.renderer );
pmremGenerator.compileEquirectangularShader();
let envMap = pmremGenerator.fromScene( new THREE.RoomEnvironment() ).texture;
this.context.scene.environment = envMap;
Instead of using a single instance of AmbientLight, apply a more advanced type of environmental lighting to your scene. Especially if you already enabled tone mapping, consider to use a HDR environment map. The basic GLTFLoader example of three.js is a good code template. The most important part is:
new RGBELoader()
.load( 'textures/equirectangular/royal_esplanade_1k.hdr', function ( texture ) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = texture;
// more scene setup
} );
Applying an environment map to Scene.environment ensures all PBR materials in the scene are going to use it.

THREE.JS : Change material color behind PNG texture ? Assign 2 materials to a mesh imported from GLTF model?

I am trying to change the color of my 3D model "behind" the png texture I set (which includes transparency).
I have done a lot of researches, and i finally found an example with a cube which actually works, but I can't understand how to make that with my gltf 3D model (not a BoxGeometry).
METHOD :
Define an array of two materials,
first one is my png texture with transparency = true;
second one is a basic material with its plain color (the color i will be able to change later...)
var materialBack = new THREE.MeshBasicMaterial({color: 0xfadce6});
var materialTxt = new THREE.MeshBasicMaterial({map: mytexture,transparent: true});
var materials = [materialBack, materialTxt];
It works perfect with a cube :
var geometry = new THREE.BoxBufferGeometry();
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
var cube = new THREE.Mesh( geometry, materials );
Problem : I can't figure out how to do the same when my model is actually an imported GLTF, and not a "BoxBufferGeometry". It looks like we can't assign an array to o.material :
var loader = new THREE.GLTFLoader();
loader.load(mymodel.glb, function(gltf) {
gltf.scene.traverse((o) => {
if (o.isMesh) {
o.material = materials;
}
scene.add(gltf.scene);
});
I also tried to extract geometry from gltf, then create a new mesh, but without success :
var loader = new THREE.GLTFLoader();
loader.load(mymodel.glb, function(gltf) {
var geometry = gltf.scene.getObjectByName("name").geometry;
mymesh = new THREE.Mesh(geometry,materials);
scene.add(mymesh);
});
Can someone please help ?

THREE.JSONLoader - Double sided texture - PNG

I´m new in Three.js and I need advice. After exporting model from Blender (version 2.71) and loading to scene I see one side textured on my three.....but second side is without texture..... I must enable double side texture, however I don´t know how. I try some examples, but nothing works. I using .PNG texture format with alpha-chanel.. I also try in Blender activated double side, but nothing happends.
Here is my loading code:
var three1;
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('3D/three1.js', addthree1ToScene);
function addthree1ToScene( geometry, materials )
{
var materiall = new THREE.MeshFaceMaterial( materials );
three1 = new THREE.Mesh( geometry, materiall );
three1.scale.set( 0.8, 0.8, 0.8 );
three1.position.set(50,15.5,0);
scene.add( three1 );
}
Thanks for any advice! (Sorry for my english :) )
UPDATE:
..Something like this?..
var three1;
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('3D/three1.js', addthree1ToScene);
function addthree1ToScene( geometry, materials )
{
var materiall = new THREE.MeshFaceMaterial( materials );
for ( var i = 0; i < materials.length; i ++ )
{
var material = materials[i];
material.side = THREE.DoubleSide;
}
three1 = new THREE.Mesh( geometry, materiall );
three1.scale.set( 0.8, 0.8, 0.8 );
three1.position.set(50,15.5,0);
scene.add( three1 );
}
It´s working, BTW :)
For each material in your materials array, set
material.side = THREE.DoubleSide;
three.js r.68

Loading textures in three.js

I am new to three.js and what I done so far is: model a geometry in Blender, export it to JSON, and put it into my three.js scene.
It works fine with the basic three.js materials. Now I want to load a color, specular and normal map to my geometry. But everytime I try to add just a single texture, the geometry disappears in the browser.
Here is my code:
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "models/schuh.js", addModelToScene );
var texture = new THREE.ImageUtils.loadTexture("images/test_COL.jpg");
var ambientLight = new THREE.AmbientLight(0x111111);
scene.add(ambientLight);
}
function addModelToScene( geometry, materials )
{
var material = new THREE.MeshBasicMaterial(map:texture});
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set(50,50,50);
scene.add( mesh );
}
what did I do wrong?
It looks like you are loading the texture after calling the addModelToScene function.
Try to change your code like this:
function someFunction() {
var texture = new THREE.ImageUtils.loadTexture("images/test_COL.jpg");
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('models/schuh.js', addModelToScene);
var ambientLight = new THREE.AmbientLight(0x111111);
scene.add(ambientLight);
}
function addModelToScene( geometry, materials )
{
var material = new THREE.MeshBasicMaterial({map:texture});
mesh = new THREE.Mesh( geometry, material );
mesh.scale.set(50,50,50);
scene.add( mesh );
}

How to repeat the texture map like GL_REPEAT?

I have a house model in my game, and I have some materials for the house geometry. There is a material for the wall of the house, and I have a texture-map-image to show the bricks.
var mat = new THREE.MeshPhongMaterial( {
ambient: 0x969696,
map: THREE.ImageUtils.loadTexture( 'textures/G/G0.jpg' ),
overdraw: true,combine: THREE.MultiplyOperation
} );
In this way above, the texture map appears like GL_CLAMP I want it to show like GL_REPEAT.
What should I do?
If you can not see the images check this.
I have posted a full working example at:
http://stemkoski.github.com/Three.js/Texture-Repeat.html
The relevant part of the code example is:
// for example, texture repeated twice in each direction
var lavaTexture = THREE.ImageUtils.loadTexture( 'images/lava.jpg' );
lavaTexture.wrapS = lavaTexture.wrapT = THREE.RepeatWrapping;
lavaTexture.repeat.set( 2, 2 );
var lavaMaterial = new THREE.MeshBasicMaterial( { map: lavaTexture } );
var lavaBall = new THREE.Mesh( THREE.GeometryUtils.clone(sphereGeom), lavaMaterial );
scene.add( lavaBall );
It's called THREE.RepeatWrapping there. The loadTexture defaults to THREE.ClampToEdgeWrapping (see ctor function from previous link). Don't know if you can use the callback (because this in JS is a bit weird (looks like it points to the created Image, not the created Texture)). Signature:
loadTexture: function ( path, mapping, callback ) {
Better you just name the texture locally and set the wrap modes manually:
var t = THREE.ImageUtils.loadTexture( 'textures/G/G0.jpg' );
t.wrapS = t.wrapT = THREE.RepeatWrapping;
Looks like you're not going far with threejs without looking at the actual code...
Image must be 8x8, 16x16, 32x32, 128x128, 256x256, 512x512 etc.
And all be working.
=)

Resources