Three JS, add specularity (shine) to texture - javascript

I have a texture I am applying to an object in three.js. I want to add some specularity or shininess to it.
I see examples that look like this
new THREE.MeshPhongMaterial( {
color: 0x996633,
specular: 0x050505,
shininess: 100
} );
However, my code looks like this:
// texture
var texture = new THREE.Texture();
var imgLoader = new THREE.ImageLoader( manager );
imgLoader.load( 'assets/uv.png', function ( image ) {
texture.image = image;
texture.needsUpdate = true;
} );
// model
var loader = new THREE.OBJLoader( manager );
loader.load( 'assets/obj.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.side = THREE.DoubleSide;
child.material.map = texture;
}
} );
object.position.y = - 95;
scene.add( object );
}, onProgress, onError );
I am not sure where to add the shininess or specular setting since I'm not using a THREE.MeshPhongMaterial, or if I did use the THREE.MeshPhongMaterial, how to combine it with THREE.texture.

I would suggest you override the object's material when it's loaded.
var loader = new THREE.OBJLoader(manager);
loader.load('assets/obj.obj', function (object) {
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshPhongMaterial({
color: 0x996633,
specular: 0x050505,
shininess: 100,
map: texture,
side: THREE.DoubleSide
});
}
} );
object.position.y = - 95;
scene.add(object);
}, onProgress, onError);

three.js provides quite a lot of materials that all behave differently and use different properties to be configured (see these examples here to get an overview). If you want to get a glossy look, you will probably go for either MeshStandardMaterial or MeshPhongMaterial. The ducomentation will also tell you the properties available to configure the materials.
MeshStandardMaterial is something like a newer version of the phong-material. It's the more "correct" (physically speaking) and more computationally expensive option while the MeshPhongMaterial is a good approximation.
The piece of Information you are probably missing is that you can just replace materials as you like, so in your example that would be something like
if ( child instanceof THREE.Mesh ) {
var oldMaterial = child.material;
child.material = new THREE.MeshStandardMaterial({
side: THREE.DoubleSide,
map: texture
// ..if neccesary, copy properties like color from oldMaterial
});
}
to completely replace the material.

Related

Create a mesh from GLTFLaoder().load() in Thre.js

I have a local 3D object model and I load it with:
const loader = new GLTFLoader();
loader.load("path/to/model", gltf => {
scene.add(gltf.scene);
});
How should I create a mesh out of the gltf, because when I try:
loader.load("path/to/model", (geometry, materials) => {
var mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
mesh.position.z = -10;
});
I get the error:
Cannot convert undefined to object
I found out that actually by modifying the first function above like this:
loader.load("path/to/model", gltf => {
var object = gltf.scene.children[0];
scene.add(gltf.scene);
});
is the solution.
Because now object variable can be totally handled like a normal mesh.
Maybe a video to help you.

THREE.SmoothShading has no effect on geometry

Smooth shading seems to have no effect on my model - the polygons are clearly visible and toggling between smooth and flat shading in the three.js inspector has no effect. There is vertex normal data in the obj so using geometry.computeVertexNormals() shouldn't be needed as has been suggested on a few other posts.
Using THREE.WebGLRenderer
Any leads appreciated :)
obj,mtl,img files
This is my loader function:
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl(pathToLoad);
mtlLoader.setPath(pathToLoad);
mtlLoader.load('model_mesh.obj.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath(pathToLoad);
objLoader.load('model_mesh.obj', function (obj) {
obj.name = pathToLoad.substring(12, 17);
testArray.push(obj);
scene.add(obj);
loadNextPath();
});
});
screenshot, polygons visible
The problem is with your model. It has "flat" vertex normals.
If you don't want to fix your model, you can recompute smooth vertex normals by using a pattern like this one:
loader.load( 'model_mesh.obj', function( object ) {
var mesh = object.children[ 0 ];
mesh.geometry = new THREE.Geometry().fromBufferGeometry( mesh.geometry );
mesh.geometry.mergeVertices();
mesh.geometry.computeVertexNormals();
// convert back to BufferGeometry prior to rendering
mesh.geometry = new THREE.BufferGeometry().fromGeometry( mesh.geometry );
scene.add( object );
});
three.js r.95

Three.js objloader + texture

I have been using Three.js for a few weeks now, I managed to apply a texture to a cube created directly via the code, but once I tried to load an OBJ file with OBJLoaderI noticed that I couldn't use the same method to load simple png or jpg textures with TextureLoader.
Now I'm not entirely sure what is going wrong, if either this is not the right way to do it, if I just can't load a simple image fine or if I'm not applying it right.
I've seen that applying a texture seems quite easy to do with an MTL file, but unfortunately I'm not sure how to make one.
My current code looks like something like this:
var loader = new THREE.OBJLoader( manager );
loader.load( 'models/tshirt.obj', function ( object ) {
object.position.x = 0;
object.position.y = -200;
object.scale.x = 10;
object.scale.y = 10;
object.scale.z = 10;
obj = object;
texture = THREE.TextureLoader('img/crate.png'),
material = new THREE.MeshLambertMaterial( { map: texture } );
mesh = new THREE.Mesh( object, material );
scene.add( mesh );
} );
But it just doesn't seem to work. The model doesn't load and gives me random errors from Three.js. If instead of the code above I change scene.add( obj); the model actually loads.
What should I be doing here? Should I just go ahead and try to make an MTL file?
My full working code can bee seen at http://creativiii.com/3Dproject/old-index.html
EDIT: The error I get when adding mesh instead of obj is
three.min.js:436 Uncaught TypeError: Cannot read property 'center' of undefined
Try this code:
var OBJFile = 'my/mesh.obj';
var MTLFile = 'my/mesh.mtl';
var JPGFile = 'my/texture.jpg';
new THREE.MTLLoader()
.load(MTLFile, function (materials) {
materials.preload();
new THREE.OBJLoader()
.setMaterials(materials)
.load(OBJFile, function (object) {
object.position.y = - 95;
var texture = new THREE.TextureLoader().load(JPGFile);
object.traverse(function (child) { // aka setTexture
if (child instanceof THREE.Mesh) {
child.material.map = texture;
}
});
scene.add(object);
});
});
The texture loading changes was taken from: How to apply texture on an object loaded by OBJLoader? .

ThreeJS - OBJLoader "Cannot read property 'uniforms' of undefined

I'm trying to use three.js to import and render an object I made. Everything was find, I even succeded to apply a wireframe texture.
But i wanted to apply a Point cloud texture (here) but either it just display a color on my object either i get an error like writte non the tittle
my code is like that
var loader = new THREE.OBJLoader( manager );
loader.load( 'obj/moimeme2.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = new THREE.PointCloudMaterial( {color: 0x6FF060 } );
}
} );
/*object.scale.y = 5;
object.scale.x = 5;
object.scale.z = 5;*/
scene.add( object );
}, onProgress, onError );
I'm kinda a beginner in JS and i don't really get what is the problem this
Thank you for reading !
Point cloud material is for point cloud geometry. Not for regular geometry.

Three.js: Load JSON file to be viewed in

i have a question regarding putting a 3dModel from Blender to a Three.js page.
I have created a 3D Human model in blender. I can export it using the 2.66 three.js-export plugin for blender.
When I use the exported .js file and load it into http://blackjk3.github.io/threefab/ it seems to work fine.
I used the http://mrdoob.github.io/three.js/examples/webgl_animation_skinning_morph.html example and tried to put my own model into it. And I can't get it to be displayed.
Firebug just tells me something like: "TypeError: a.hierarchy is undefined" and it seems like I can't really find the problem.
I use the JSON Loader as ususal:
var loader = new THREE.JSONLoader();
loader.load( "models/skinned/humanPrototype.js", function ( geometry, materials ) { createScene( geometry, materials, 0, FLOOR, -300, 60 ) } );
createScene looks like this:
function createScene( geometry, materials, x, y, z, s ) {
geometry.computeBoundingBox();
var bb = geometry.boundingBox;
THREE.AnimationHandler.add( geometry.animation );
for ( var i = 0; i < materials.length; i ++ ) {
var m = materials[ i ];
m.skinning = true;
m.morphTargets = true;
m.color.setHSL( 0.6, 0.5, 0.6 );
m.ambient.copy( m.color );
m.wrapAround = true;
}
mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshFaceMaterial( materials ) );
mesh.position.set( 0,0,0 );
mesh.scale.set( s, s, s );
scene.add( mesh );
mesh.castShadow = true;
mesh.receiveShadow = true;
animation = new THREE.Animation( mesh, geometry.animation.name );
animation.JITCompile = false;
animation.interpolationType = THREE.AnimationHandler.LINEAR;
//animation.play();
}
Since my model is loadable in threefab I think its ok. I guess I need to change something about the code. I feel this to be a inexact question and I want to apologize for that. But at the moment I'm really stuck. Any suggestions? =) Thank you very much.
Open knight.js and your exported.js file with an text editor, you will find the difference,
I think that this is still an experiment technology by the author.

Categories