exporting threejs ShaderMaterial as mtl file? - three.js

Is there a way to export a general threejs shadermaterial of the type:
var the_material = new THREE.ShaderMaterial( { uniforms: u, vertexShader: vs, fragmentShader: fs ,name:id} );
into a .mtl file ?

An .mtl file can only represent specific classic material types, like "phong" or "lambert". See this document: http://paulbourke.net/dataformats/mtl/. As a result, it is not possible to put arbitrary shader code into an .mtl file. To export an arbitrary shader, you'll very likely need to export the entire vertex+fragment shader (e.g. .glsl).

Related

how do i convert all materials in a loaded gltf from mesh basic to mesh phong?

I am loading a GLTF model into threejs. All the materials used on the object (and there a quite a few of them), use a mesh basic material, and we want them to be a material that can be affected by lights. Is there a way to convert all materials from a basic material to one that can receive lights, like Phong (including their existing properties?).
I can currently add a new material as follows:
glb.scene.traverse(child => {
if (child.isMesh) {
//child.material = new THREE.MeshPhongMaterial({ flatShading: true });
}
});
but everything just looks a solid gray color and doesn't contain any of the properties of the mesh basic material it replaced.
The default material in glTF is usually mapped to MeshStandardMaterial in three.js — your model must have the "unlit" glTF extension (KHR_materials_unlit) enabled if it's creating MeshBasicMaterial. Short of changing that in a modeling tool like Blender, which might be easiest, you can also convert it in three.js...
model.traverse((child) => {
if ( ! child.isMesh ) return;
var prevMaterial = child.material;
child.material = new MeshPhongMaterial();
MeshBasicMaterial.prototype.copy.call( child.material, prevMaterial );
});
Note that the reverse does not necessarily work — calling a complex material's copy() method on a simpler material (like MeshBasicMaterial) will cause it to look for properties that do not exist.

ThreeJS GLTFExporter doesn't export PBR material maps

I have a simple Cube with a PBR Material. Used maps are color, metalness, roughness, bump. When I export the scene via this code, the exported glb is missing all maps but the color. Is this a bug in ThreeJS?
e = new THREE.GLTFExporter();
e.parse(STAGE.scene.mesh, (glb) => {
let blob = new Blob([glb], { type: "application/octet-stream" });
let d = document.createElement('a');
d.href = window.URL.createObjectURL(blob);
d.download = "orbis.glb"
document.body.appendChild(d);
d.click();
document.body.removeChild(d);
}, {binary: true});
You should use different textures. The reason for this is the gltf specification:
gltf uses a normalMap instead of a bumpMap, so bumpMaps are not exported
metalnessMap and roughnessMap are only exported if they are the same texture because gltf uses a single texture for both (see https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material and https://github.com/mrdoob/three.js/issues/14940 for a feature request to merge those textures in the exporter)

Three.js custom shader not displaying

I recently started learning about shaders and three.js. I tried to display a shader with a texture but it displays all black.
Here's the codepen: https://codepen.io/LDB95/pen/MxmWNq
These are my uniforms:
uniforms: {
tDiffuse: { value: null },
time: { type: "f", value: 1.0 },
resolution: { type: "v2", value: new THREE.Vector2() },
iChannel0: { type: 't', value: new THREE.TextureLoader().load('https://naqyr37xcg93tizq734pqsx1-wpengine.netdna-ssl.com/wp-content/uploads/2017/11/10-Things-We-Can-Learn-From-the-Incredible-Steve-Jobs.jpg')},
iChannel1: { type: 't', value: new THREE.TextureLoader().load('https://gobelmont.ca/Portals/0/xBlog/uploads/2018/8/30/white%20noise.jpg')},
},
I just can't seem to find the fix. Would be really awesome if someone could help me out here :)
Thanks!
I'm afraid your codepen is full of mistakes. It seems you are trying to port a shader from shadertoy to three.js, right?
I have removed all errors here but the effect still looks broken: https://codepen.io/anon/pen/XGRVew
Anyway, here are a few things to keep in mind:
You have to assign the textures to the uniforms after you have created the shader pass. Uniforms are cloned for the internal material of ShaderPass. That means textures are cloned, too. The respective needsUpdate flag is not set correctly if you load the texture before the material creation.
As mentioned by #Marquizzo, your texture are blocked for security reasons. I've added some textures from the three.js repo for test purposes.
The following line of code is not necessary since uv coordinates are provided with the geometry. It's not necessary to compute them on-the-fly like shadertoy does. Just use the varying vUv in the fragment shader.
vec2 uv = gl_FragCoord.xy / resolution.xy;
For such simple one-pass shaders, it's not necessary to use EffectComposer. Try to use an approach similar to this official example.
You always have to ensure that the example files like ShaderPass or EffectComposer match the three.js version in your code. I've changed this in the codepen in order to remove all deprecation warnings.

Threejs export marchingcubes in obj file with mtl

I have seen plenty of examples on how to export a mesh or a whole scene from ThreeJS to an OBJ file. Starting from MrDoob example here:https://threejs.org/examples/#misc_exporter_obj
But since a marching cube like this : https://threejs.org/examples/webgl_marchingcubes.html is not an instance of THREE.Mesh, what would be the workaround to export its current geometry into an Obj file? And by extension its material into an mtl file as explained in this question : Export a three js textured model to a .OBJ with .MTL file
EDIT
As far as I understand, it is possible to export a copy of the current state of the metaballs by using the generateGeometry() function provided by marching cubes. Below is an example using filesaver.js and JSZip.js to export the geometry and material as two files in a zip. THREE.OBJExporter comes from the modified version of the original obj exporter of threeJS done as mentionned above (Export a three js textured model to a .OBJ with .MTL file):
function exportToObj(the_object){
var zip = new JSZip();
var the_exporter = new THREE.OBJExporter();
var result = the_exporter.parse(the_object);
zip.file("Blob.obj", result.obj);
zip.file("Blob.mtl", result.mtl);
zip.generateAsync({type:"blob"}).then(function (blob) {
saveAs(blob, "Blob.zip");
});
}
$(document).on('keyup',function(e) {
if (e.which == 13){ // enter key to export to OBJ
var TempMesh = new THREE.Mesh(effect.generateGeometry(),effect.material);
//effect is of the type: new THREE.MarchingCubes()
exportToObj(TempMesh);
}
});
In that way, if a color is provided to the material, it will be exported in the .mtl file. But the last missing piece is probably how to properly convert a shaderMaterial for example? Save it as a texture maybe?

How to apply Three.js shaders to nodes

I'm trying to apply the shaders from the shaderLib but most of them either turn the node to complete white or black. Only the normal shader seem to work.
This is how I apply it:
const shader = THREE.ShaderLib.depth;
const uniforms = shader.uniforms;
const material = new THREE.ShaderMaterial({
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms
})
this._viewer.impl.matman().addMaterial(
data.name, material, true)
And set the material of the fragment with:
function setMaterial(fragIds, material) {
const fragList = this._viewer.model.getFragmentList()
this.toArray(fragIds).forEach((fragId) => {
fragList.setMaterial(fragId, material)
})
this._viewer.impl.invalidate(true)
}
Just like in this example: https://forge.autodesk.com/blog/forge-viewer-custom-shaders-part-1
I also tried to add colors to the uniforms like that example but it didn't help.
Any ideas why they don't work?
As I said in the comment, Forge Viewer is using a privately owned three.js, and its' WebGLRender didn't implement all functionalities as three.js, either. So, it might not support all functions in the three.js.
To identify what happened to this case, you can consider providing a reproducible case demonstrating that, I will gladly pass it to our dev team. Those following items should be in the reproducible case:
A short exact description of what you are trying to achieve. The behavior you observe versus what you expect, and why this is a problem.
A complete yet minimal sample source model to run a test in.
A complete yet minimal Forge app that can be run and debugged with a simple procedure to analyze its behavior lives in the sample model.
A complete yet minimal three.js app that can be run and demonstrated the shader effect you want. Note. Forge Viewer is using r71 three.js.
Detailed step-by-step instructions for reproducing the issue, e.g. which element to pick, what command to launch etc.
If your reproducible case could not be posted here publicly, please send it to the forge.help#autodesk.com and remove sensitive data or information before you send.
======== Old response
Could you provide more detail for further debugging, please?
It seems to works fine on my side. Here are my test codes. It's tested on the Forge RCDB (https://forge-rcdb.autodesk.io/database?id=57efaf0377c8eb0a560ef467).
var shader = THREE.ShaderLib.depth;
var uniforms = shader.uniforms;
var material = new THREE.ShaderMaterial({
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms
})
NOP_VIEWER.impl.matman().addMaterial( 'ShaderLabDepth', material, true );
var sel = NOP_VIEWER.getSelection();
var fragList = NOP_VIEWER.model.getFragmentList();
var it = NOP_VIEWER.model.getData().instanceTree;
it.enumNodeFragments( sel[0], function( fragId ) {
fragList.setMaterial( fragId, material )
});
NOP_VIEWER.impl.invalidate( true );
And Its' result is like this. Did it what you want?

Resources