how to change Environment map texture dynamically on reflection material - three.js

in threejs i want to change the skybox textures dynamically, am added 2 scenes here so i attached one scene to my skybox, so i decided to remove the skybox before switch from on texture to another, and the skybox textures are reflecting Environmentmap on the object, if i change the textures by select from the given list, am checking textures with the switch case and adding the texture , the reflection on the object is working, but if i switch skyBoxMaterial to selected texture Enviromentmap changed successfully but the reflection on the object is not changed to current Enviromentmap
Following is my code:
function envmap(envmap)
{
switch(envmap)
{
case 'canary':
var urls = [
'textures/cube/canary/pos-x.png',
'textures/cube/canary/neg-x.png',
'textures/cube/canary/pos-y.png',
'textures/cube/canary/neg-y.png',
'textures/cube/canary/pos-z.png',
'textures/cube/canary/neg-z.png'
];
//var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
break;
case 'Park2':
var urls = [
'textures/cube/Park2/posx.jpg',
'textures/cube/Park2/negx.jpg',
'textures/cube/Park2/posy.jpg',
'textures/cube/Park2/negy.jpg',
'textures/cube/Park2/posz.jpg',
'textures/cube/Park2/negz.jpg'
];
//var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
break;
case 'Park3Med':
var urls = [
'textures/cube/Park3Med/px.jpg',
'textures/cube/Park3Med/nx.jpg',
'textures/cube/Park3Med/py.jpg',
'textures/cube/Park3Med/ny.jpg',
'textures/cube/Park3Med/pz.jpg',
'textures/cube/Park3Med/nz.jpg'
];
//var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
break;
case 'Bridge2':
var urls = [
'textures/cube/Bridge2/posx.jpg',
'textures/cube/Bridge2/negx.jpg',
'textures/cube/Bridge2/posy.jpg',
'textures/cube/Bridge2/negy.jpg',
'textures/cube/Bridge2/posz.jpg',
'textures/cube/Bridge2/negz.jpg'
];
//var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
break;
case 'pisa':
var urls = [
'textures/cube/pisa/px.png',
'textures/cube/pisa/nx.png',
'textures/cube/pisa/py.png',
'textures/cube/pisa/ny.png',
'textures/cube/pisa/pz.png',
'textures/cube/pisa/nz.png'
];
//var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
break;
default:
var urls = [
'textures/cube/canary/pos-x.png',
'textures/cube/canary/neg-x.png',
'textures/cube/canary/pos-y.png',
'textures/cube/canary/neg-y.png',
'textures/cube/canary/pos-z.png',
'textures/cube/canary/neg-z.png'
];
break;
}
var cubemap = THREE.ImageUtils.loadTextureCube(urls,undefined, render); // load textures
cubemap.needsUpdate = true;
cubemap.format = THREE.RGBFormat;
var shader = THREE.ShaderLib['cube']; // init cube shader from built-in lib
shader.uniforms['tCube'].value = cubemap; // apply textures to shader
// create shader material
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
depthWrite: false,
side: THREE.BackSide
});
alert(skybox);
if (skybox)
{
sceneCube.remove(skybox);
}
skybox = new THREE.Mesh( new THREE.BoxGeometry( 1000, 1000, 1000 ), skyBoxMaterial );
sceneCube.add( skybox );
var reflectionMaterial = new THREE.MeshBasicMaterial({
color: 0xcccccc,
envMap: cubemap
});
var object = scene.getObjectByName ("myname", true);
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh )
{
//child.geometry.computeFaceNormals();
var geometry = child.geometry;
//console.log(geometry);
material = child.material;
material.transparent = true;
child.material.needsUpdate = true;
child.material.map = reflectionMaterial;
mesh = new THREE.Mesh(geometry, reflectionMaterial);
scene.add(mesh);
}
});
}

After the work around fixed it myself
i used child.material=reflectionMaterial; instead of child.material.map = reflectionMaterial; and the refection is worked on the object material
So now while switch from one environment to another environment the reflection applied to my Object too
and there is no need of add new mesh below
mesh = new THREE.Mesh(geometry, reflectionMaterial);
scene.add(mesh);

Related

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

Animating a THREE.Points object

I'm trying to load a model from Blender, apply a PointsMaterial to it and animate it. So far, I've been able to load the model and animate it successfully as long as I use a material other than THREE.PointsMaterial to create the mesh.
When I create a THREE.Points object, the animation doesn't play. I noticed that when I set the PointsMaterial's morphTargets property to true, there's a warning saying that there is no such property of PointsMaterial. Does Threejs not support animation of Points objects using morph targets?
monster refers to a mesh that works when animated. It uses the loaded geometry and material. ParticleSystem is the the THREE.Points object.
Code:
function loadObject(path){
var loader = new THREE.JSONLoader();
loader.load(
path,
function(geometry, materials){
var material = materials[ 0 ];
material.morphTargets = true;
material.color.setHex( 0xffaaaa );
monster = new THREE.Mesh( geometry, materials );
monster.position.set( 0, 0, 0 );
var s = .003;
monster.scale.set( s, s, s );
var particleMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: .005,
morphTargets: true
});
particleSystem = new THREE.Points(geometry, particleMaterial);
particleSystem.morphTargetInfluences = monster.morphTargetInfluences;
particleSystem.morphTargetDictionary = monster.morphTargetDictionary;
particleSystem.position.set(0, 0, 0);
particleSystem.scale.set(s, s, s);
particleSystem.matrixAutoUpdate = false;
particleSystem.updateMatrix();
particleSystem.geometry.verticesNeedUpdate = true;
scene.add(particleSystem);
mixer.clipAction( geometry.animations[ 0 ], particleSystem )
.setDuration( 5 ) // one second
.startAt( - Math.random() ) // random phase (already running)
.play(); // let's go
}
)
}

how to Smooth .obj in Three.js

Is there any way to smooth an .OBJ in three.js ? I already load the model but it looks faceted
I already use the shading: THREE.SmoothShading, in the material but doesn't affect it
var Loader = new THREE.OBJLoader();
Loader.load('models/stockcarchasisc.obj', function(carGeo, materials) {
// var material = new THREE.MeshFaceMaterial(materials);
var map = new THREE.TextureLoader().load( "models/st_tex.jpg" );
map.wrapS = map.wrapT = THREE.RepeatWrapping; // This set/place UV coordinates at 0 !
var material2 = new THREE.MeshStandardMaterial({
color: 0xa65e00,
side: THREE.DoubleSide,
map: map,
});
carGeo.traverse( function(child) {
if (child instanceof THREE.Mesh) {
// apply custom material
child.material = material2;
// enable casting shadows
child.castShadow = true;
child.receiveShadow = true;
}
});
carGeo.position.y = 25;
carGeo.scale.set(25, 25, 25);
var helper = new THREE.VertexNormalsHelper( carGeo, 5, 0x00ff00, 5 );
scene.add(carGeo);
scene.add(helper);
});

How to add reflectionMaterial for an object in threejs

How to add reflectionMaterial with environment map, am using two cameras and two scene in order to achieve it, based on the webgl_materials_cubemap
and am using Object that is loaded using OBJMTLLoder, i can see the both Environment map, and Object on my scene, but the reflection of environment is not working on the object..
find my code below :
var urls = [
'textures/cube/canary/pos-x.png',
'textures/cube/canary/neg-x.png',
'textures/cube/canary/pos-y.png',
'textures/cube/canary/neg-y.png',
'textures/cube/canary/pos-z.png',
'textures/cube/canary/neg-z.png'
];
var cubemap = THREE.ImageUtils.loadTextureCube(urls); // load textures
cubemap.format = THREE.RGBFormat;
var shader = THREE.ShaderLib['cube']; // init cube shader from built-in lib
shader.uniforms['tCube'].value = cubemap; // apply textures to shader
// create shader material
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
depthWrite: false,
side: THREE.BackSide
});
skybox = new THREE.Mesh( new THREE.BoxGeometry( 1000, 1000, 1000 ), skyBoxMaterial );
scene.add( skybox );
var object = scene.getObjectByName ("myname", true);
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh )
{
//child.geometry.computeFaceNormals();
var geometry = child.geometry;
var reflectionMaterial = new THREE.MeshBasicMaterial({
color: 0xcccccc,
envMap: cubemap
});
mesh = new THREE.Mesh(geometry, reflectionMaterial);
sceneCube.add(mesh);
}
});
Here am just changing the scene.add(mesh); to sceneCube.add(mesh); the reflection worked but the camera doesn't ..
you can see the differences here
Example 1
Example 2
In the first demo you can see that the scene working fine with the environment and without Object reflection
In the second you can see that the Reflection working fine but the camera behavior gets wired
i fixed it myself by adding following line inside the Object traverse
child.material.map = reflectionMaterial;
child.material.needsUpdate = true;
However i don't know am doing is correct or not but it is worked as like expected,

Offsetting environment map texture in three.js

I'm trying to offset a texture that's being used as an environment map, but not having much luck.
The texture is loaded with the loadTextureCube() method, which gets applied to my mesh just fine, but the offsets don't seem to have any effect.
The texture is just a big gray circle to give a little bit of gloss.
Any thoughts on what I'm doing wrong?
var urls = [
'pos-x.png',
'neg-x.png',
'pos-y.png',
'neg-y.png',
'pos-z.png',
'neg-z.png'
];
var cubemap = THREE.ImageUtils.loadTextureCube(urls);
cubemap.offset.y = -.5;
cubemap.offset.x = -.5;
cubemap.needsUpdate=true;
I'm assuming based on loadTextureCube that your utilizing the cube shader approach to skyboxes. So far everything with your code is fine. The problem your seeing is that while your texture has offset properties, the material (or more specifically the cube shader program therein) does not have uniforms to pass this along to the fragmentation shader. This of course is assuming your doing something like this:
Eg. cube shader material
var skyboxGeo = new THREE.CubeGeometry( 5000, 5000, 5000 );
var cubeShader = THREE.ShaderUtils.lib[ "cube" ];
cubeShader.uniforms[ "tCube" ].value = cubemap;
var skyboxMat = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
side: THREE.BackSide
});
var skybox = new THREE.Mesh( skyboxGeo, skyboxMat );
scene.add( skybox );
There's likely a number of work arounds, but you could alway try something like a MeshFaceMaterial on a standard cube to achieve the desired result:
Eg. standard material
var skyboxGeo = new THREE.CubeGeometry( 5000, 5000, 5000 );
var materialArray = [];
for (var i = 0; i < 6; i++) {
var cubeTex = THREE.ImageUtils.loadTexture( urls[i] );
cubeTex.offset.x = -.5;
cubeTex.offset.y = -.5;
materialArray.push( new THREE.MeshBasicMaterial({
map: cubeTex,
side: THREE.BackSide
}));
}
var skyboxMat = new THREE.MeshFaceMaterial( materialArray );
var skyBox = new THREE.Mesh( skyboxGeo, skyboxMat );
Hope that helps
~D

Resources