Mapping of Roughness map/ AO map/ Metalness Map into RGB channels

I need guidance, how we can map one texture into three different RGB channels in a GLB file and I am not loading any texture from outside I just need to manipulate that textures which are with GLB model. I write below code

gltf.scene.traverse(function (child) {
                if (child instanceof THREE.Mesh) {
                    const mat = new THREE.MeshPhysicalMaterial({})
                    if (value === 'normalMap') {
                        if (child.material.normalMap) {
                   = child.material.normalMap;
                            child.material.needsUpdate = true;
                            console.log('Normal map exist');
                    if (value === 'alphaMap') {
                        if (child.material.alphaMap) {
                   = child.material.alphaMap;
                            child.material.needsUpdate = true;
                            console.log('Alpha map exist');
                    if (value === 'aoMap') {
                        if (child.material.aoMap) {
                   = child.material.roughnessMap;
                            child.material.needsUpdate = true;
                            console.log('AO map exist');
                    if (value === 'emissiveMap') {
                        if (child.material.emissiveMap) {
                   = child.material.emissiveMap;
                            child.material.needsUpdate = true;
                            console.log('Emissive map exist');
                    if (value === 'roughnessMap') {
                        if (child.material.roughnessMap) {
                   = child.material.roughnessMap;
                            //mat.needsUpdate = true;
                            child.material.needsUpdate = true;
                            console.log("mat", mat)
                            console.log('Roughness map exist');
                    if (value === 'metalnessMap') {
                        if (child.material.metalnessMap) {
                            //child. = mat;
                   = child.material.metalnessMap;
                            child.material.needsUpdate = true;
                            console.log('Metalness map exist');

In the above code roughness map, metalness map and ao map all share same textures and I don’t need how split this texture into three parts for RGB channels. Thanks for your time and help

Maby you have to show why isn’t working and, what is the message of the error

It doesn’t giving me any error just wanna know how to split one texture into three RGB channels so I will assign one texture to three inputs

I think three js isn’t blender. You have to split Image in to RGB channel, and just load it with texture loader.

Texture loader is for loading texture not only png, rgb file for local but also on online like base64 url

But all the texture maps are already stored in a GLB file see below link


I need this same but don’t wanna import any image just split texture map which is stored in a GLB file.

I don’t get what is ‘split’ texture that you’ve been saying

I’m not expertise I think you have to divde image texture in each RGB channel with other web module.

and plus, if you change texture you have to type material.needsUpdate = true

I tried this but didn’t work, main issue is I can’t able to understand how I divide texture into three channels like donmccurdy sir did, just wanna know is it possible, if yes then how and one more article is there

in the above link they explain but I didn’t find any path.

Where are you defining value in this? You are checking against value, but, as far as I can see, you didn’t define it anywhere.

Into console have some logs of exist map? console.log('Normal map exist');

I create one drop drop down with dat.gui those values are I am comparing

yes it displays message works fine main issue in Roughness Map, Occlusion Map, and Metalic Map

Ok… I am slightly confused… What effect are you trying to achieve here. Are you just trying to visualize the different textures, or what are you trying to get done. Because, from your code, it does seem as though you are just trying to visualize the textures.

Yes, change textures of GLB at run time like sketchfab we can see normal map, base color and so on.

are you able to create a fiddle of your entire code? Rather than just the traversal. That would be helpful, at least for me, if not for others as well.

Sir, I can’t share whole code as per organization rule, you have any other way just need guidance.

That’s fair.

You are getting the logs. Is it only on Roughness, occlusion, and metallic that you are getting the issue? And, if so, are you still getting the logs? I know gltf format does combine metalness/roughness map (blue channel is metalness, green is roughness), and I don’t know if it combines the alpha map as well (if so, it would be red channel). Umm… You could use the onBeforeCompile with the material to update the fragment shader a bit.
Side note: You shouldn’t need to update the material. The only time you would need to do that is if you are changing whether or not the material has its own map property.
Why not try logging the material, and checking all the roughness, metalness, and ao map to see if they are the same texture. Dunno if that would work, but it might be worth a try.

yes, you are right in single texture image I have three channels RGB in image but I don’t know to pass single by single to three Metalness, Roughness and Occlusion. If I run my code it shows together with mixing of ORM values. I hope you understand my point and you have any resource related to onBeforeCompile and how we can override fragment shaders for this.

Yes. I understand your issue now. I am quickly testing something, and will get back.

I already checked the log values all have same values and same uuid values by using


Ok… results of my testing. Using needsUpdate does recompile the material, but it doesn’t trigger the onBeforeCompile function.
Best thought of mine, add a uniform to the shader, call it like, imageType. In the shader, add a conditional, and if imageType is one of 3 values, update gl_FragColor with the correct texel.
That would probably look something like this:

//When loading the gltf (or before the first render frame) inside a traverse function
child.material.onBeforecompile = function(shader){
    //unprocessed fragment shader. Change this, change what gets plugged
    // into three.js You will need to figure out where to change the code
    // Putting it directly at the end might work.
    //add something similar to this code
    `if([uniform name] == [whatever number you are using to signify roughness map]){
         gl_FragColor.rgb = texture2D(roughnessMap, vUv).ggg;
     }else if([uniform name] == [metalness map number]){
         gl_FragColor.rgb = texture2D(metalnessMap, vUv).bbb;
     }else if([uniform name] == [ao map number]){
        gl_FragColor.rgb = texture2D(aoMap, vUv).rrr;

    //putting this (or similar) at the beginning
    'uniform int [uniform name];';
    shader.uniforms.[uniform name] = {};
    Object.defineProperty(shader.uniforms.[uniform name], "value", {get:function(){
        return child.material.[uniform name];

And then, in the traversal, you would just do

child.material.[uniform name] = [number for whatever option was chosen];

And, that should work. No guarantees, and you will probably have to do a bit of debugging. But, fingers crossed, that should work.
Also make sure to replace the stuff in brackets. I don’t know if i made that obvious, but, please do not just copy paste that code. Replace the things in brackets (and the brackets themselves) with what they mean. I have done dumber things, and dont want you to waste lots of time debugging that because of a misunderstanding.