Layered textures in three.js - javascript

I'm loading a fbx model with multiple objects inside made with Cinema4D.
When the model is loaded I get this warning console message.
THREE.FBXLoader: layered textures are not supported in three.js. Discarding all but first layer.
I understand that this message is about the normal layers, bump maps or other, but in the fbx file are loaded with it's own url. Anyone know if there is any way to load this properly? Or export it differently from C4D?
Thanks

By default, Three.js only draws one texture type per mesh. For instance, you can only assign one texture to material.map, you can't layer them one on top of the other. It sounds like your Cinema4D objects have two or more textures layered one on top of the other.
In order to layer multiple textures one on top of the other, you'll need to create one mesh per texture. Maybe give them a very slight offset in position to layer them in the correct order. Alternatively, you could flatten your layered textures into a single image.

how about using several meshes with slightly different scale-ings and different textures ? Like matroschka puppets.
So if the textures are transparent you can see the underlying ones, too.

Related

THREE.js not rendering .obj with .mtl - exporting files for THREE.js

***UPDATE***This has to be an issue with the files and the way they are exported, i just don't know what that issue is. I have downloaded some more example models and they all render just fine.
I am experiencing an issue with Three.js when loading .obj and .mtl files.
I have a bunch of objects and their corresponding material files exported from 3ds. I am not the one who has exported these files, I am not a 3d modeler however if this turns out to be an issue with the files I can ask the modeler to export them again.
I have used THREE.js a few times and never come across this issue, I am loading the .mtl and .obj file using the following:
mtlLoader.load("stands/objects/Table&Chairs.mtl", function(materials){
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load("stands/objects/Table&Chairs.obj", function(object){
scene.add(object);
object.position.set(-5, 0, 4);
});
});
My problem is the object loads fine, there are no errors, however nothing is shown. The object is not being rendered to the scene.
If i download some example assets from other sources and switch out the files that are being uploaded, without changing anything else, the object renders.
This leads me to believe it could be an issue with the way in which the files are being exported.
screen showing of my .obj being rendered
Screen showing the example .obj being rendered
Any help as to what could be causing this would be much appreciated.
I have uploaded the objects and materials here.
Mine are the Table&Chairs, the example ones are the Tent_Poles_01 files.
The great thing about .OBJ files is that you can just open them up in the text editor of your choice and see what is inside. This will give you a rough idea of position and scale:
Looking at the vertices in your tent model, it seems to have a size of about 2 units in each dimension, centered around the origin.
Looking at the vertices in the Table & Chairs model, they have a size of a couple of hundred/thousand units, and start near (+6000,0,-2000).
In other words, the first suspect would be your model being rendered somewhere far outside the visible viewport.
Usually, when you work together with a 3D artist, you discuss the scale you want to work at beforehand, and have them nicely align the model with the origin.
You can (sort of) correct this in code, but it will not be as practical.
mesh.geometry.center() will recenter the geometry around (0, 0, 0)... but do note that is usually not what you want. For example, a table will then be half-way through the floor in it's default centered position.
to scale the geometry to an absolute size, use something like (pseudocode)
var currentSize = new THREE.Box3().setFromObject(model).getSize();
mesh.geometry.scale(
targetWidth / currentSize.X,
targetHeight / currentSize.Y,
targetDepth / currentSize.Z)

Three.js - How to group together multiple imported models

I'm attempting to reduce the amount of drawcalls in my THREE.js scene. I have a large 32x32 of tiles that are .gtlf models imported from disk. Some grid tiles get a model (that has just 8 vertices and a texture). However, inspecting this canvas with a third part tool like Spector shows that there's 151 draw calls, and it seems like every model is being drawn separately.
They are created by looping through the grid for every tile, seeing if that tile needs a model, if so, it gets the model data from a Map where it was loaded with the THREE.GLTFLoader. Sometimes, but rarely, the material changes and so may the rotation, but only during setup.
These tiles will never need to be moved or have their transforms changed. They will be static. Is there some sort of optimisation I can perform to group the rendering of these tiles into as few drawcalls as possible, seeing as they are in essence the same object?
You can merge your tiles into one geometry.
Something along the lines of this
const mergedGeom = new THREE.BufferGeometry()
tiles.forEach( tile=>{
const geom = tile.geometry.clone()
geom.applyMatrix(tile.matrixWorld)
mergedGeom.merge(geom)
}
If you do have many different materials and textures you will somehow have to manage that though.

"Liquify" Surface of Points Mesh in Three.js

I loaded a Mesh from a JSON File, here is my current result:
my Project
It is an object I exported from blender as JSON and then used its vertices to create a geometry of Points (THREE.Points) (which is important for the looks of it)
I am now looking for a way to "animate" the Points, so that the "surface" looks vivid / living. So basically it should be moving around a bit, something like this (without the rotation):
Link to animated Gif
I have ruled out displacementMap, as this does not work for the PointsMaterial (or does someone know a workaround?)
Does anyone have hints or ideas? I thought of maybe morphing 2-3 Objects .. but I am not sure if this will work for a points mesh.
One approach to achieve your desired effect is to use morph target animation (also called vertex morphing). As you can see at the following example, three.js does support morph target animations with points.
https://threejs.org/examples/webgl_morphtargets_sphere.html
There is a lot of existing literature about vertex morphing, so it should be no problem to get familiar with this technique. I suggest you create your animations in Blender, export the model to glTF and the load the file via GLTFLoader into your app like shown in the example.

Three.js complex material with displacement

I am wondering if there is a way to combine two normal maps at runtime in javascript/threejs. My problem is. I have a lot of cube like models, each of them is made from:
the box like mesh
a front face that hide the inside of the box
All box-like meshes use MeshStandartMaterial and they all have normal maps applied to them.
Plane-like meshes (fronts) all have displacement and normal maps applied to them. I use normal map (with front) to make displacement look more defined.
The problem is I need to apply to front the "material" normal map as well, so I am looking for the way to combine it with displacement normal map.
Is it possible to combine them using canvas 2d context?

Three.js running out of texture units

I have written an app using Three.js (r73) that allows the user to load multiple .dae files using the ColladaLoader.
If the user selects a sufficient number of objects the texture will not show for any of the objects...at this point I get this:
WebGLRenderer: trying to use 26 texture units while this GPU supports only 16
The error message seems fairly self-explanitory - does this mean I can only load 16 textures at any one time? Is there a way around this? Can I render my scene with half my objects - clear the texture units - and then render the other half?
Quite new to Three.js - so sorry if its a stupid question.
This number is based on what your GPU supports, you can see it listed here at WebGL Report, under Max Texture Image Units: 16.
Many people confuse this number with how many textures you can have in a single scene, this is false. This number represents how many textures you can use for a single object (i.e. in a single draw call).
So if you have an extremely complicated object, with hundreds of separate textures. You'll have to find a way to either merge the textures together, or split the object into multiple objects that can be drawn separately.
However, if you draw 1000 separate objects, each with a different texture, this shouldn't be a problem.
The warning comes from exceeding the maximum number of "total" texture units, and not the Vertex texture units. Refer to WebGLRenderer.js, function getTextureUnit() for the reasoning behind this and the printing of this error message. (ex, https://searchcode.com/codesearch/view/96702746/, line 4730)
To avoid the warning, analyse the shaders, and reduce the count of texture units required in the shader, for the rendering.

Categories

Resources