Getting RGB Values of a Material

Hi, newbie here. I am working on a script to export data about my scene, but I am stuck on getting the RGB values of materials. In my implementation I am accessing all materials in the scene via ‘scene.materials’… then iterating them. However, after some browsing it doesn’t seem like that the RGB values of a standard material accessed through this method is available. Am I missing something obvious? Is there another way to do this?

Thank you!
Frank

Check this - https://www.babylonjs-playground.com/#20OAV9#743

I’ve added a couple of console logs at the bottom to print and I managed to get the hex value which I thinking could be converted to RGB ints.
Is this what you are looking for?

console.log(scene.materials[0].ambientColor)
console.log(scene.materials[0].ambientColor.toHexString())

Not sure if there is a better approach.

Edit:
Of course there are fours colors on standard material and you should get them all. Also there are different colors on PBRMaterial.

1 Like

Hi there, thank you for the response. That is indeed what I need, however, the method .ambientColor does not seem to work for me, I’m not sure why. It comes up as invalid, please see below:

“Property ‘ambientColor’ does not exist on type ‘Material’.”

Hey @frank_lin

Welcome to Babylon! Is there any way you could point us to a playground to look at to help troubleshoot?

Hello! I am currently working with the Desktop BabylonJS editor and calling the code from a custom script file. Could this issue be due to the setup? If you were to just open a blank project from the editor and attach a custom script with a one-liner “console.log(scene.materials[0].ambientColor);” to the start() function, you can reproduce the behavior. I would upload a .zip of what I’m talking about, but unfortunately it exceeds the max upload limit.

EDIT: Also seems a bit odd that the same “scene.materials” function returns arrays holding seemingly different objects with different properties (.ambientColor). Why is there a discrepancy?

Ah I see thanks for the more info. Let’s bring in @julien-moreau who is the master of all things editor. Perhaps he can pop in and help here.

@julien-moreau any insight would be appreciated :slight_smile:

Ambient Color is a property of some Materials. Other materials have other “color properties”

Can you do console.log(material.getClassName()) and tell us what the materials are?

Sure. I printed them out and they are all returning as “StandardMaterial”. image.
Odd that an object of class “StandardMaterial” doesn’t have access to the same properties listed here.

EDIT: I was curious to see what your playground example would have outputted, so I edited it to print the className as well. It’s also StandardMaterial.
https://www.babylonjs-playground.com/#20OAV9#749
image

What results do you get if you do
console.log(scene.materials[0]) in your project?

Seems to only print out the Name property, as far as I can tell.

In which case that is all the scene.materials[0] object consists off. I would expect

scene.materials[0]: 
Object { metadata: null, reservedDataStore: null, checkReadyOnEveryCall: false, checkReadyOnlyOnce: false, state: "", _alpha: 1, _backFaceCulling: true, onCompiled: null, onError: null, getRenderTargetTextures: getRenderTargetTextures(), … }

Seems like your material is not properly defined and is just a string.

But my materials are created in the BabylonJS editor as a StandardMaterial. How else should this be defined? Is this a bug?

If that’s the case, how do you explain this playground? I’m printing out the material object in here and it only prints a string as well. Is this example (taken from BabylonJS documentation) incorrectly defined? https://www.babylonjs-playground.com/#20OAV9#750

I now see the difference you are using

console.log("scene.materials[0]: " + scene.materials[0]);

whereas I was using

console.log("scene.materials[0]: " , scene.materials[0]);

scene.materials[0] is an object and you can only use + with strings so using + scene.materials[0] takes the object scene.materials[0] and just adds a string it can extract, eg name.

Using commas with console.log logs the list of objects given in full.

Also the function getClassName needs () to call it, eg getClassName() to print the name rather than the function description which you are getting at the moment.

Modified PG https://www.babylonjs-playground.com/#20OAV9#751

This might not solve your original problem but will get us a look at your material objects.

Hi John, thank you for taking the time to help me troubleshoot. I updated the code with the comma and now I am getting the full expected output:
image

Despite that, I am still unable to access the ambientColor property for the object within the BJS Editor. Shouldn’t it be right under alphaMode in the contextual menu?

Furthermore, I noticed something strange. I’m not sure if it’s worth mentioning but maybe someone can make something of it. I updated your playground example with two new lines of code:

var temp_mat = new BABYLON.StandardMaterial(“temp_mat”, scene);
temp_mat = scene.materials[0];

As expected, the assignment from scene.materials[0] to temp_mat does not give any errors. Why would it, after all, according to .getClass(), scene.materials[0] is class StandardMaterial (established in previous posts). However, over in BJS Editor, the same two lines of code fail with the following error:

Thanks all, for your time. Hope I’m not making a mountain out of a molehill :slight_smile:

It looks like, and I may well be wrong, that the Editor Code is in Typescript not Javascript. Certainly the error message is one of Type which Typescript would pick up but Javascript would not.

Looking at the BJS code for scene.materials

/**
    * All of the materials added to this scene
    * In the context of a Scene, it is not supposed to be modified manually.
    * Any addition or removal should be done using the addMaterial and removeMAterial Scene methods.
    * Note also that the order of the Material within the array is not significant and might change.
    * @see http://doc.babylonjs.com/babylon101/materials
    */
    public materials = new Array<Material>();

It is defined as an array of Type Materials and since StandardMaterial is of an extended Type they are not the same. You get the same error message in the Typescript version of the playground Babylon.js Playground.

Also note this sentence in the comments

Note also that the order of the Material within the array is not significant and might change

So the use of scene.materials is not a good way to access the materials.

Now I am stuck. Perhaps if it is you intention to use JavaScript rather than Typescript the Editor is not the way to go. As @julien-moreau seems not to be available perhaps @Deltakosh can provide some advice here.

You are correct, the Editor is using TypeScript, which explains the assignment failure from before. Is TypeScript also the culprit for making .ambientColor inaccessible?

As mentioned before, I am very new to all of this. What I am trying to do is to create a workflow where I can export useful scene information to a database via a POST request, which I then pull from and process in my “game”. With the hopes that I can reuse this workflow for later on to facilitate clients saving gamestates. I chose BJS Editor so I could use a GUI to construct my scene, rather than update digits one at a time and hitting refresh to see what changes the code made. I like BJS Editor and it has a good user experience. It would be preferable if I can continue using it. With that said, if scenes.materials is not a good way to access all materials in a scene (indeed, it doesn’t even seem to work for TS), then I won’t use it. What alternatives are available?

Will continue googling in the meantime…!

Fight on. Thanks

1 Like

Hey, it is possible to do the same as JavaScript using Typescript. Your problem here is the usage of scene.marerials that are instances of « Material ». ambient color is available on StandardMaterial so you can:

  • cast using (material as StandardMaterial).ambienColor = …
  • access the member using the brackets accessor: material[« ambienColor »] = …

Does it fit your needs ?

1 Like

Thanks, Julien! That did the trick. Posting my code for any future stumblers that might come across the same issue:

var temp_material = scene.materials[i];
var diffuse_color = (temp_material as BABYLON.StandardMaterial).diffuseColor;
console.log("diffuseColor: " + diffuse_color);

Note: I ended up using “.diffuseColor” since the values I specified in the editor weren’t being stored under .ambientColor, but .diffuseColor instead.

Just want to say that I am loving the Babylon.JS community. Thanks for everyone who pitched in. You guys are awesome. Keep rockin’ it.

Cheers,
Frank