mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.64k stars 35.3k forks source link

collada child bump map #2207

Closed olivierhuntemann closed 11 years ago

olivierhuntemann commented 12 years ago

Hi all and thanks in advance for your help.

I try to create bump map on collada chidren, but nothing works, only with JSON models.

Anyone can help me ?

Thanks,

Olivari

crobi commented 12 years ago

I bumped into this today as well. As far as I can see, there are two problems:

  1. The COLLADA format does not support bump/normal/height maps per default.
  2. three.js does not support bump/normal/height maps rendering per default (except through using a custom ShaderMaterial).

Most COLLADA exporters I have seen add the information about the additional textures in their own tags, where they can write whatever they want. So the collada loader would have to understand the format of each exporter. What exporter are you using?

I have a fork of three.js where I have updated the collada loader to read bump maps from OpenCOLLADA 3ds max files, you can have a look at https://github.com/crobi/three.js/blob/master/examples/js/loaders/ColladaLoader.js. It's work in progress, though. If it does not work with your files, you would have to extend the methods Effect.prototype.parseTechniqueExtra and Effect.prototype.parseTechniqueOpenCOLLADA.

The second problem is that three.js default materials only support one texture per material. My loader passes a parameter called normalmap to the material constructor, where it gets ignored because the material does not know what that is. So you would need to change the constructor of whatever material you use to read this parameter.

If I have time, I will try to hack in normal maps into default materials. If the user has the OES_standard_derivatives webgl extension, it should be possible to use a tangent space free approach (see http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html) and implement the normal perturbation as a small and independent shader chunk in WebGLShader.js (that approach only uses eye space coordinates, texture coordinates, and the normal map texture).

olivierhuntemann commented 12 years ago

Thanks for your reply crobi,

I use 3ds file export to collada format.

With your method, what can i have to do ?

the source :

var objloader = new THREE.ColladaLoader();

objloader.load('object.dae', function colladaReady(collada) {

dae = collada.scene;

THREE.SceneUtils.traverseHierarchy(dae_cadran, function(child) {

    if (child.name == 'objet_bump') {
        child.material = bump_map;
    };
});

});

So what the bump_map material does look like ?

Thanks

crobi commented 12 years ago

First, if you use 3ds, I would recommend the OpenCOLLADA plugin (source: https://github.com/KhronosGroup/OpenCOLLADA, binaries: http://opencollada.org/download.html), the built-in collada exporter is apparently not very good.

Second, it's not that simple getting the bump map from my loader. The only way of getting a bump mapped material in three.js at the moment is creating a custom shader, and my loader does not do that. I'm afraid you would have to change the loader code or the three.js material code to get it to work.

I won't have time to work on it until next week. Your best bet right now would be to edit the loader code. Go to line 3203 (in function Shader.prototype.create). This is the place where the material object is created. If the normal map was found, the props object will contain a property props.normalmap. Then, instead of creating a THREE.MeshBasicMaterial (line 3208), THREE.MeshPhongMaterial(line 3215), or THREE.MeshLambertMaterial (line 3222), create a THREE.ShaderMaterial. If you want to know how to create a custom shader with normal mapping, see for example http://mrdoob.github.com/three.js/examples/webgl_trackballcamera_earth.html.

For reference, here is the relevant part from the collada file (which is just an xml file that you can open in a text editor): The texture name is a reference to a <sampler> element, which in turn contains a reference to a <surface> element, which in turn contains a reference to an <image> element, which contains the actual file name. This convoluted structure is from the collada format 1.4 definition. Not all exporters follow the definition, and the definition changes with every new collada version.

<extra>
    <technique profile="OpenCOLLADA3dsMax">
        <bump bumptype="HEIGHTFIELD">
            <texture texture="normalmap_png-sampler" texcoord="CHANNEL1"/>
        </bump>
    </technique>
</extra>

If your structure looks different, post your collada file as an issue on https://github.com/crobi/three.js and I'll try to adapt the loader.

alteredq commented 12 years ago

three.js does not support bump/normal/height maps rendering per default (except through using a custom ShaderMaterial).

three.js does support normal maps, just there is no specific named material class for this:

http://mrdoob.github.com/three.js/examples/webgl_materials_normalmap.html http://mrdoob.github.com/three.js/examples/webgl_materials_normalmap2.html

If you would like to add support to ColladaLoader you can have a look how it's implemented in Loader base class:

https://github.com/mrdoob/three.js/blob/master/src/loaders/Loader.js#L306

crobi commented 12 years ago

Thanks, that Loader code is exactly what I meant! Add the code from https://github.com/mrdoob/three.js/blob/master/src/loaders/Loader.js#L306 to https://github.com/crobi/three.js/blob/master/examples/js/loaders/ColladaLoader.js#L3202, and it should work.

three.js does support normal maps, just there is no specific named material class for this

Yes, there is a normal mapping shader built in into three.js. But doesn't that shader have limitations? Looking at the shader source, it does not seem to support morph animations, for example. Wouldn't that add a rather strange restriction that normal mapped objects can not have animations?

Since normal maps are not that uncommon, wouldn't it make sense to add support for them to the named material classes? Plus specularity textures, since we're at it. I can not promise anything, but I might be able to do it in the next couple of weeks.

olivierhuntemann commented 12 years ago

Have an example of the code after modifications, what lines i have to add in ColladaLoader.js ?

Previously, i have tested this, but doesn't work :

var ambient = 0x090909, diffuse = 0xaaaaaa, specular = 0xffffff, shininess = 4.0, scale = 23;

var uniforms = {

tNormal: { type: "t", value: 2, texture: ImageUtils.loadTexture( 'data/material/bouton_NRM.png') }, tDiffuse: { type: "t", value: 0, texture: ImageUtils.loadTexture( 'data/material/bouton_COLOR.png' ) }, tSpec: { type: "t", value: 3, texture: ImageUtils.loadTexture( 'data/material/bouton_SPEC.png' ) }, tOcc: { type: "t", value: 3, texture: ImageUtils.loadTexture( 'data/material/bouton_OCC.png' ) }, tDisp: {type:"t", value: 1, texture: ImageUtils.loadTexture( 'data/material/bouton_DISP.png' ) },

uDisplacementBias: { type:"f", value: -0.428408 * scale}, uDisplacementScale: { type:"f", value: 2.436143 * scale},

uDiffuseColor: { type:"c", value: new THREE.Color( diffuse ) }, uSpecularColor: { type:"c", value: new THREE.Color( specular )}, uAmbientColor: { type:"c", value: new THREE.Color( ambient )},

uShininess: { type:"f", value: shininess}

};

var bump_material = new THREE.MeshShaderMaterial( { uniforms: uniforms, vertex_shader: document.getElementById( 'vertex_shader' ).textContent, fragment_shader: document.getElementById( 'fragment_shader' ).textContent } );

And then i have assigned my bump_material to dae child, but does'nt work, work with json, but not collada

Thanks

olivierhuntemann commented 12 years ago

Any idea ?

crobi commented 12 years ago

I didn't have time to look into your problem, but I have started writing my own collada loader to handle meshes with normal maps. It is work in progress, but it can load a static mesh and creates a shader material if there is a bump map in the effect (no animations yet). If you have a static mesh, you could give it a try.

You can get it at https://github.com/crobi/ColladaAnimationCompress/tree/collada-loader (note the collada-loader branch). If you don't want to build it, you can download the built version with a viewer tool from https://github.com/downloads/crobi/ColladaAnimationCompress/Viewer.zip

My original motivation for writing it was the fact that the that the three.js collada loader code is very complex and quite slow for big meshes. I had difficulties extending it to support multi-textured materials, for example. I wanted my loader to follow the collada specifications a bit closer than the original three.js collada loader. On the other hand, I wanted the code to be simple and do not plan to ever support non-triangle meshes.

When writing my loader I realized that the reason for the problems with the original loader is not the design of the code, but the unbelievably convoluted specification of the collada format. But now that I have started it, I plan on finishing it with animation support. If it turns out to be useful, I plan on submitting it to three.js, together with the viewer tool mentioned above. Big parts of the code are copied from the original loader, so credits for that go to the original authors.

Oh and it is written in coffeescript. Coffeescript compiles into plain javascript, but the generated file is nowhere near as readable as the original code. You can have a look at the current version at https://github.com/crobi/ColladaAnimationCompress/blob/collada-loader/ColladaLoader2.coffee

mrdoob commented 12 years ago

My original motivation for writing it was the fact that the that the three.js collada loader code is very complex and quite slow for big meshes. I had difficulties extending it to support multi-textured materials, for example. I wanted my loader to follow the collada specifications a bit closer than the original three.js collada loader. On the other hand, I wanted the code to be simple and do not plan to ever support non-triangle meshes.

You have all my support! ;)

When writing my loader I realized that the reason for the problems with the original loader is not the design of the code, but the unbelievably convoluted specification of the collada format.

Yeah...

Oh and it is written in coffeescript.

Oh... that's a bit of a problem :/

crobi commented 12 years ago

Just an update, I paused the development on the collada loader until I see how https://github.com/Motorola-Mobility/collada2json is developing. They use the official OpenCollada SDK to parse the collada file and convert it into an efficient json/binary file combo. They also have a threejs loader.

Also, since threejs version r50 added support for bump maps and specular maps in the default materials, all comments above mentioning ShaderMaterial are probably obsolete. Just create a MeshPhongMaterial and set its bumpMap property.

olivierhuntemann commented 12 years ago

Thanks Crobi, I have already opened the collada loader of the three js r50 but no bump map nowhere, have you worked on an update and can you send me it ?

crobi commented 12 years ago

I am not working on the collada loader that comes with threejs. I have my own loader in my own repository (or if you dont want to built it, download a recent version here - then open the file viewer.html and follow the on-screen description).

I have updated my loader to use threejs r50 and the built-in bump mapping. The built-in bump mapping doesn't look as good as the ShaderMaterial bump mapping, I'm still figuring out why.

olivierhuntemann commented 12 years ago

Okay Crobi,

So, how to load my collada file using your own loader ?

I have this :

var objloader = new THREE.ColladaLoader();

objloader.load('object.dae', function colladaReady(collada) {

dae = collada.scene;

THREE.SceneUtils.traverseHierarchy(dae, function(child) {

    if (child.name == 'objet_bump') {
        child.material = bump_map;
    };
});
});

Appreciate your help

crobi commented 12 years ago

Basically, you just write

var objloader = new ColladaLoader2();

Most (but not all) of the API is the same.

If you have specific questions about my loader, it might be a good idea to open a ticket in its own project, since it doesn't really belong to threejs.