Recreating Sketchfab's "ambient environment" with threejs - multiple CubeMaps? - three.js

I am trying to recreate Sketchfab's "ambient environment" feature in threejs.
see sketchfab background settings
I want my model in threejs to show a traditional environment map (360 picture of a location), but I want the scene to show a blurred, ambient image as the environement.
I tried loading two cubetextures and applying one to the envMap of the model, and the other to the scene.background:
var loader = new THREE.TextureLoader();
loader.load( "../../image/download/img1.jpg", function ( texture ) {
texture.encoding = THREE.sRGBEncoding;
texture.anisotropy = maxAnisotropy;
var cubemapGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: 512 } );
var cubeMapTexture = cubemapGenerator.update( renderer );
var pmremGenerator = new THREE.PMREMGenerator( cubeMapTexture );
pmremGenerator.update( renderer );
var pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
pmremCubeUVPacker.update( renderer );
envMapCubeRenderTarget = pmremCubeUVPacker.CubeUVRenderTarget;
var envMap = envMapCubeRenderTarget ? envMapCubeRenderTarget.texture : null;
texture.dispose();
pmremGenerator.dispose();
pmremCubeUVPacker.dispose();
object.material.envMap = envMap
var loader2 = new THREE.TextureLoader();
loader2.load( "../../image/download/img2.jpg", function ( texture ) {
texture.encoding = THREE.sRGBEncoding;
texture.anisotropy = maxAnisotropy;
var cubemapGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: 512 } );
envMapBackground = cubemapGenerator.renderTarget;
scene.background = envMapBackground; //old = texture
scene.background.anisotropy = maxAnisotropy;
});
});
When I try to use two cubemaps, my scene just renders a blank background...

Related

How to attach an image to loaded object in Three.js

I'm trying to attach a custom image to an object (.obj)
What I want is
But the result is
I want the image to be located in the center of the object for only one time. But the image is repeated to fill the entire material.
I googled a lot and read some articles about uv mapping but I could not figure out how to apply to a custom object.
Following is my code. Thanks in advance.
var mtlLoader = new MTLLoader();
mtlLoader.load("~~~.mtl", function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(
"~~.obj",
function (geometry) {
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load("~~.jpg");
var material = new THREE.MeshLambertMaterial({
transparent: true,
map: texture, // <- ??
});
texture.minFilter = THREE.LinearFilter;
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
geometry.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material = material;
}
});
scene.add(geometry);
}

Update texture with three.js

I've got a textured model in three.js and I want to be able to swap out the texture defined in the .gltf file when the page loads. I've looked here for inspiration.
"images": [
{
"uri": "flat_baseColor.png"
},
// etc
So to update the texture I do
var images = [
"./textures/01.jpg",
// "./textures/01.jpg",
];
var texture = new THREE.TextureLoader().load( images[0] );
var my_material = new THREE.MeshBasicMaterial({map: texture});
// load the model
var loader = new GLTFLoader().setPath( 'models/gltf/' ); // trex
loader.load( 'creature_posed.gltf', function ( gltf )
{
gltf.scene.traverse( function ( child )
{
if ( child.isMesh )
{
// The textures go for a double flip, I have no idea why
// Texture compensation
texture.flipX = false;
texture.flipY = false;
child.material = my_material;
texture.needsUpdate = true;
}
} );
var model = gltf.scene;
Only the texture is considerably pale. :(
I've tested it against itself, so it's not the texture). What have a missed out?
When loading textures you'll need to pay attention to colorspace: if the texture has color data (like .map or .emissiveMap) it's probably sRGB.
texture.encoding = THREE.sRGBEncoding;
See GLTFLoader docs and color management in three.js. This assumes that renderer.outputEncoding = THREE.sRGBEncoding as well.
three.js r113

Three.js LegacyGLTFLoader.js shadows missing

I have a GLTF version 1.0 model that I am importing into Three.js using LegacyGLTFLoader.js. When I do so, everything looks good, except that the model does not receive shadows. I am guessing that this is because the imported model's material is THREE.RawShaderMaterial, which does not support receiving shadows (I think). How can I fix this so that my imported model can receive shadows?
Here is sample code:
// Construct scene.
var scene = new THREE.Scene();
// Get window dimensions.
var width = window.innerWidth;
var height = window.innerHeight;
// Construct camera.
var camera = new THREE.PerspectiveCamera(75, width/height);
camera.position.set(20, 20, 20);
camera.lookAt(scene.position);
// Construct renderer.
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.shadowMapEnabled = true;
document.body.appendChild(renderer.domElement);
// Construct cube.
var cubeGeometry = new THREE.BoxGeometry(10, 1, 10);
var cubeMaterial = new THREE.MeshPhongMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.translateY(15);
scene.add(cube);
// Construct floor.
var floorGeometry = new THREE.BoxGeometry(20, 1, 20);
var floorMaterial = new THREE.MeshPhongMaterial({color: 0x00ffff});
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.receiveShadow = true;
scene.add(floor);
// Construct light.
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 0);
light.castShadow = true;
scene.add(light);
// Construct light helper.
var lightHelper = new THREE.DirectionalLightHelper(light);
scene.add(lightHelper);
// Construct orbit controls.
new THREE.OrbitControls(camera, renderer.domElement);
// Construct GLTF loader.
var loader = new THREE.LegacyGLTFLoader();
// Load GLTF model.
loader.load(
"https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb",
function(event) {
var model = event.scene.children[0];
var mesh = model.children[0];
mesh.receiveShadow = true;
scene.add(model);
},
null,
function(event) {
alert("Loading model failed.");
}
);
// Animates the scene.
var animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
// Animate the scene.
animate();
Here are my resources:
https://dl.dropboxusercontent.com/s/y2r8bsrppv0oqp4/three.js
https://dl.dropboxusercontent.com/s/5wh92lnsxz2ge1e/LegacyGLTFLoader.js
https://dl.dropboxusercontent.com/s/1jygy1eavetnp0d/OrbitControls.js
https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb
Here is a JSFiddle:
https://jsfiddle.net/rmilbert/8tqc3yx4/26/
One way to fix the problem is to replace the instance of RawShaderMaterial with MeshStandardMaterial. To get the intended effect, you have to apply the existing texture to the new material like so:
var newMaterial = new THREE.MeshStandardMaterial( { roughness: 1, metalness: 0 } );
newMaterial.map = child.material.uniforms.u_tex.value;
You also have to compute normal data for the respective geometry so lighting can be computed correctly. If you need no shadows, the unlint MeshBasicMaterial is actually the better choice.
Updated fiddle: https://jsfiddle.net/e67hbj1q/2/

Three JS texture is not showing up

I am trying to apply a texture to my 3D model with Three JS.
I tried a lot of ways from the Three JS Examples but for any reasons nothing is working.
Here is how I apply the texture to my model:
//LOADING TEXTURE
var textureLoader = new THREE.TextureLoader();
var diffuse = textureLoader.load( "models/Carbon.png" );
diffuse.encoding = THREE.sRGBEncoding;
diffuse.wrapS = THREE.RepeatWrapping;
diffuse.wrapT = THREE.RepeatWrapping;
diffuse.repeat.x = 1;
diffuse.repeat.y = 1;
var normalMap = textureLoader.load( "models/Carbon_Normal.png" );
normalMap.wrapS = THREE.RepeatWrapping;
normalMap.wrapT = THREE.RepeatWrapping;
var material = new THREE.MeshPhysicalMaterial({
roughness: 0.5,
clearcoat: 1.0,
clearcoatRoughness: 0.1,
map: diffuse,
normalMap: normalMap
});
// LOADING MODEL
var loader = new THREE.GLTFLoader();
loader.load("models/stairs.gltf", function(gltf){
model = gltf.scene
model.traverse((newModel) => {
if (newModel.isMesh){
newModel.material = material;
newModel.castShadow = true;
newModel.receiveShadow = true;
}
});
scene.add(model);
});
I appreciate any help!
When loading a texture for a glTF model, you have to set Texture.flipY to false to satisfy the uv convention of glTF.
diffuse.flipY = false;
normalMap.flipY = false;
Besides, you always have to ensure that your model has texture coordinates. You can do this by checking if the geometries of your meshes have an uv attribute. If this attribute is missing, I suggest you generate texture coordinates in a DCC tool like Blender.
three.js R112

How can i set materials to collada child in THREE.js

i created a scene in blender it contains some meshs with out materials then i exported it to collada, i load it to three.js scene with colladaloader everything is ok but when i put some materials to children using the following code :
loader.load( "../models/islands/"+islandselected.getAttribute("data-model")+".dae", function(object){
scene.remove("island");
plane=object.scene;
plane.name=islandselected.innerHTML;
plane.traverse(function(child){
if(child.children[0]){
if(child.children[0].geometry){
console.log(child)
var t = new THREE.ImageUtils.loadTexture( '../models/islands/'+child.name+'.jpg' );
t.wrapS = t.wrapT = THREE.RepeatWrapping;
t.repeat.set( 50, 50 );
var ma= new THREE.MeshBasicMaterial( {map:t} );
child.children[0].material=ma
}
}
});
plane.scale.set(100,100,100);
scene.add(plane);
});
i get errors in console :
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1
empcreator.jsp:1 WebGL: too many errors, no more errors will be reported to the console for this context.
var model,mat;
var loader = new THREE.ColladaLoader();
var lastTimestamp = 0;
var progress = 0;
loader.load( 'obj/mymodel.dae', function ( collada ) {
model = collada.scene;
model.children[3].children[0].material = new THREE.MeshPhongMaterial({map:THREE.ImageUtils.loadTexture('obj/images/myimage.jpg')});
console.log(model.material);
model.scale.x = model.scale.y = model.scale.z = 0.10;
model.rotation.y = 0.80;
scene.add( model );
}
//you will need to modify a little to work it, i took it from my old project

Resources