We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.

Replace all textures on runtime

Home Forums Programming Replace all textures on runtime

Viewing 15 posts - 1 through 15 (of 15 total)
  • Author
    Posts
  • #29829
    web
    Customer

    Hello guys,
    I’m working on some logic of replacing all scene textures on runtime.

    I found a code snippet here in the forum, which I tried to modify to fit my needs, but the textures are not getting updated. Maybe someone can give a hint?

    This is the current code:

    app.scene.traverse(function(obj){
        if(obj.material){
            for (var i_index in obj.material.nodeTextures){
                var imageSrc = obj.material.nodeTextures[i_index].image.src
                var imageFilename = imageSrc.split('\\').pop().split('/').pop();
                var loader = new v3d.TextureLoader();
                loader.load('./assets/8k/' + imageFilename, function(texture) { 
                    obj.material.map = texture;
                })
            }
        }
    });
    #29871
    web
    Customer

    Okay, I think I know whats the issue.

    The “material.map” doesnt apply to “MeshNodeMaterial”. In the api its mentioned that its better to use the “replace Texture” puzzle for this material types.

    I wonder if it is possible to execute the puzzles from the “main” js file, instead of the “visual_logic.js” without wrapping it in a external function?

    #29910

    Hi,

    Yep, setting material.map is not applicable for MeshNodeMaterials.

    You can add custom logic to the main js file of your application. Simply put it inside the runCode() function.

    function runCode(app) {
        // add your code here, e.g. console.log('Hello, World!');
    
    }
    

    Soft8Soft Tech Chief
    X | FB | LinkedIn

    #29948
    web
    Customer

    Okay, thanks for clearing that up.

    To maybe clarify my question regarding the “executing puzzles”.
    At the moment I’m using a mix of using puzzles and self written logic by looking in the api of verge.

    In the first bigger application I used mainly the “visual_logic.js” for all verge related stuff. Therefor I added the needed puzzles via the puzzle editor to my project so that they are written into the “visual_logic.js”. I then added manualy external function I could directly use in the “main js file”.

    But instead of that I would like to just have the “visual_logic.js” untouched so that I can easily update. And would like to just execute the puzzles in the “main js”.

    For example like this:
    v3d.puzzles.tweenCamera('Cam_01', 'Cam_01.Target', 2, function () {});

    #29959

    Do you mean using some internal Puzzles logic inside your custom JavaScript? Unfortunately, this is not possible. If you still need to do so, the best way is to copy blocks of code from visual_logic.js to your main script.

    Soft8Soft Tech Chief
    X | FB | LinkedIn

    #29966
    web
    Customer

    Yeah exactly. Hmm, okay. Is it possible to change this behaviour in future updates? Or does it simple not work programmaticaly this way?

    #34926
    web
    Customer

    I wanted to bring this thread up again.

    I would really like to implement a replace all textures function to my apps. This is what I currently got:

    app.scene.traverse(function(obj){
        if(obj.material && obj.material.type == 'MeshNodeMaterial'){
            var mat = obj.material;
            
            for (var i_index in mat.nodeTextures){
                var imageSrc = mat.nodeTextures[i_index].image.src;
                var imageFilename = imageSrc.split('\\').pop().split('/').pop();
        
                var loader = new v3d.TextureLoader();
                loader.setCrossOrigin('Anonymous');
    
                loader.load('./assets/512/' + imageFilename, function(texture) { 
                    mat.nodeTextures[i_index].image = texture;
                    mat.nodeTextures[i_index].format = v3d.RGBFormat;
                    mat.nodeTextures[i_index].needsUpdate = true;
                })
    
            }
        }
    });

    The images seems to get loaded correctly regarding the source/url but I see no update in the webGL. For some maps I get an error in the browser console:
    v3d.WebGLState: TypeError: Failed to execute 'texImage2D' on 'WebGL2RenderingContext': Overload resolution failed.
    Could anyone give a hint what could be the issue?
    I tried to compare my functions to the replaceTexture puzzle but couldnt see any issues. Except that my function is purely for jpg based textures.

    #34971
    thomasup
    Customer

    use v3d.ImageLoader(); instead of v3d.TextureLoader();

    that does the trick for me

    #34972
    thomasup
    Customer

    also, mat.nodeTextures[i_index].image.src; can be undefined, make sure to check for that.

    #34976
    web
    Customer

    :good:
    Nice works now for me too.
    Thanks mate :rose:

    One step closer to a more efficient preload.

    #37828
    GLiFTeK
    Customer

    :good: Nice works now for me too. Thanks mate :rose:
    One step closer to a more efficient preload.

    hey web,
    i am copying materials and objects to make unique copies.
    no problem except when it comes to blender-profile object materials with the nodeTextures item that i can’t seem to have copy uniquely.
    have you found a way to do so, so that when a texture is changed on the material.. ALL the other copies do not change?

    i can change their color.. anything else on the material separately.. not the texture image.

    i’m experimenting with your code here.

    can do it with normally newly made materials in js but not with the blender generated ones.

    thanks!
    :good:

    EDIT: rather.. reading this on MeshNodeMaterials, i’m trying to figure out how to get a uniquely generated texture (uuid and all) from my material copying process…

    #37838
    GLiFTeK
    Customer

    I tried a JSON stringify and parse to generate a new fresh object for the nodeTextures node but the “image” node of that did not copy. (Just got a serial number there) any tips?

    #37943
    web
    Customer

    hey gliftek,
    wasn’t very active here the last weeks. I’m not really sure what you want to achieve. I was just trying to create a function which switches all the textures in the scene on load.

    This is the function I’ve written for that purpose:

            function loadFullResTextures(imageformat){
                setTimeout(function(){ 
                    app.scene.traverse(function(obj){
                        if(obj.material && obj.material.type == 'MeshNodeMaterial'){
                            var mat = obj.material;
                            
                            for (var i_index in mat.nodeTextures){
                                var imageSrc = mat.nodeTextures[i_index].image.src;
                                var imageFilename = imageSrc.split('\\').pop().split('/').pop();
                                var imageFilenameNoSuffix = imageFilename.split('.').slice(0, -1).join('.');
                        
                                var loader = new v3d.ImageLoader();
                                loader.setCrossOrigin('Anonymous');
                     
                                loader.load(url + '/assets/full/' + imageFilenameNoSuffix + imageformat, function(texture) { 
                                    mat.nodeTextures[i_index].image = texture;
                                    mat.nodeTextures[i_index].format = v3d.RGBFormat;
                                    mat.nodeTextures[i_index].needsUpdate = true;
                                })
                     
                            }
                        }
                    });
                }, 2000);
            }

    You need to pass the filetype when executing the function.
    loadFullResTextures('.jpg');
    or
    loadFullResTextures('.webp');

    For my purpose its working good. This way I can have low res textures which are getting loaded by v3d by default and execute that function to load the full res versions afterwards. This speeds up the whole loading time for the app. You can also alter the function to add more variables, and do different loading as needed. For example different textures for different devices.

    #37954
    GLiFTeK
    Customer

    hey web,
    thanks for the response.
    yeah i have been trying to copy textures (nodeTextures) from MeshNodeMaterial from blender using JS and have had no luck.
    the api says it’s not a deep copy when you use .clone,
    like i said i tried using the JSON stringify and parse.. no dice..

    there’s got to be a way.
    :wacko:

    #38009
    web
    Customer

    Hmm, I never tried to copy textures.
    JSON.parse(JSON.stringify(data));
    Would also so be my approach, when I need a hard copy of some variables.

    Think you have to wait for a response from the v3d developers.

Viewing 15 posts - 1 through 15 (of 15 total)
  • You must be logged in to reply to this topic.