Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the material of a primitive in a ModelMesh #2387

Closed
fradelg opened this issue Jan 8, 2015 · 17 comments · Fixed by #10644
Closed

Change the material of a primitive in a ModelMesh #2387

fradelg opened this issue Jan 8, 2015 · 17 comments · Fixed by #10644

Comments

@fradelg
Copy link

fradelg commented Jan 8, 2015

Is there a way of changing the material linked to a primitive in a ModelMesh created from a glTF model?

The goal is to highlight the picked node by changing the material's parameters but ModelMaterial.selValue is applied over every primitive linked to that material. I think that the best solution is to temporary link the primitive to a special 'highlight' material but it does not have any effect over the rendered model. Maybe there is a better solution to solve the problem so I am open to suggestions!

Thanks!

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 8, 2015

I agree it would be useful to have a high-level way to do this (also mentioned in #184).

In the meantime, a workaround would be to author the model such that each mesh uses a different material.

CC #927

@fradelg
Copy link
Author

fradelg commented Jan 9, 2015

How I can create multiple instances of a loaded Model?

I think that I can create a pre-highlighted model hidden instance of the main model in the background showing only the selected node when picked.

Thanks for adding the issue as a future enhancement!

@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 9, 2015

Create two separate Model instances and set the show property of each one accordingly. There is caching starting in Cesium 1.5 to make this efficient.

@fradelg
Copy link
Author

fradelg commented Jan 9, 2015

Thanks! I will do it in that way

@fradelg fradelg closed this as completed Jan 9, 2015
@pjcozzi
Copy link
Contributor

pjcozzi commented Jan 9, 2015

OK, I'm going to keep this issue open though to consider the case for picking individual nodes without affecting all nodes with the same material.

@yqrashawn
Copy link

So if I want to pick individual nodes without affecting nodes with the same material, I need to modify the parseNodes and maybe parseMeshes as well. Will this affect the performance? It's actually duplicating meshes every time per node using it. Is doing this cost much more on the I/O with the radio card?

@pjcozzi
Copy link
Contributor

pjcozzi commented Jul 21, 2016

@yqrashawn if you want to be able to change the material of an individual node, e.g., mouseover highlight, then each node will need a unique material. You could try modifying Cesium as you suggested, but you could also just author the model to have many material objects (even if they are the same material in practice) so each node can reference a different one. Generally, this won't bloat the size of the glTF asset much, but there is potentially more WebGL overhead at runtime.

If you update Cesium, we would gladly accept a pull request, see https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTING.md#opening-a-pull-request

@yqrashawn
Copy link

@pjcozzi Thanks for your reply. I'm on this these days. I modified the parseNodes parsMeshes parsMaterials function. But model loading went really slow because of so many for loops. There are some functions looping to read the technique in material after the parse func, which cost much. And gltf can't find mesh's parent nodes and material's parent meshes, which leads to more loops.

Is there anything I missed or better way I hadn't found?

Or maybe modify the gltf file is a better choice.

What about shader level, can we change the material of nodes in runtime rather than modify it? Thus I can achieve highlighting or translucent.

@pjcozzi
Copy link
Contributor

pjcozzi commented Jul 31, 2016

Or maybe modify the gltf file is a better choice.

Yes, this should be more simple than changing the loading code.

What about shader level, can we change the material of nodes in runtime rather than modify it?

Yes, if you use a custom fragment shader with an extra uniform that is the highlight color that is multiple with the computed color (default to white for no highlight). Note that you won't be able to change a material from opaque to translucent or vice versa without more work since the render state also would need to change.

@yqrashawn
Copy link

yqrashawn commented Jul 31, 2016

@pjcozzi realy thanks for your reply. I've already came up with a command line tool to make each material and node correspond.

Note that you won't be able to change a material from opaque to translucent or vice versa without more work since the render state also would need to change.

So if I want to change the material of specific node translucent at runtime, other than modify the shader, I also need to modify the render state. Right?
Could tell me where to modify the render state, or what I'm I looking for.

@QingchaoHu
Copy link

QingchaoHu commented Aug 2, 2016

@pjcozzi @yqrashawn Thanks two. It helps me much.

Yes, if you use a custom fragment shader with an extra uniform that is the highlight color that is multiple with the computed color (default to white for no highlight). Note that you won't be able to change a material from opaque to translucent or vice versa without more work since the render state also would need to change.

We need to highlight individual nodes or make individual nodes translucent after loading models in gltf format.

By studying the source of Cesium, I am clear about that Instanced Rendering was used to improve the rendering performance. Materials are shared by meshes and meshes are shared by nodes. It's difficult to modify only one node's color by changing it's material of meshes.

I intend to add some attributes to vertex/fragment shader, binding another two buffers to webgl context when drawing. Maybe like below...

//var colorData=...
//var translucentData=...


var colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colorData, gl.STATIC_DRAW);

var translucentBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, translucentBuffer);
gl.bufferData(gl.ARRAY_BUFFER, translucentData, gl.STATIC_DRAW);

//...

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.enableVertexAttribArray(shader.attribute.color);
gl.vertexAttribPointer(shader.attribute.color, 3, gl.FLOAT, false, 12, 0);
instanceExt.vertexAttribDivisorANGLE(shader.attribute.color, 1);

gl.bindBuffer(gl.ARRAY_BUFFER, translucentBuffer);
gl.enableVertexAttribArray(shader.attribute.translucent);
gl.vertexAttribPointer(shader.attribute.translucent, 1, gl.FLOAT, false, 12, 0);
instanceExt.vertexAttribDivisorANGLE(shader.attribute.translucent, 1);

instanceExt.drawElementsInstancedANGLE(gl.TRIANGLES, indexCount, gl.UNSIGNED_SHORT, 0, instanceCount);

Is this the right way? Thanks.

@QingchaoHu
Copy link

I am familiar with Three.js and OpenGL ES shader, and have created some advanced materials by write shaders. But Cesium is so complex that I haven't find any entries.

@pjcozzi
Copy link
Contributor

pjcozzi commented Apr 12, 2017

The ability to change a material's texture was mentioned in https://groups.google.com/forum/#!topic/cesium-dev/mW0VxrU3yhA

@lilleyse
Copy link
Contributor

lilleyse commented Apr 5, 2018

Related forum post about wanting to change a model node's color: https://groups.google.com/forum/#!topic/cesium-dev/HGUDMzBBIeo

@Amber-372
Copy link

Hi,@QingchaoHu Have you highlight individual nodes of model successfully? and how to?

@hpinkos
Copy link
Contributor

hpinkos commented Jul 23, 2018

@wangxiaolun sorry, but we haven't had a chance to implement this feature yet. If you have a chance to implement it yourself we'd be happy to review a pull request!

@hpinkos
Copy link
Contributor

hpinkos commented Sep 6, 2018

Also requested by @m7567 in #7009

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants