[SOLVED] Increase Material Diffuse Map Offset not working

I want all the entities with a material assigned change the Material Diffuse Map Offset to make something like this:

I thought about changing that value directly to the material asset, so I did the following script:

var TextureDisplace = pc.createScript('textureDisplace');

TextureDisplace.attributes.add('materialAsset', {type: 'asset', assetType: 'material'});
TextureDisplace.attributes.add('velocity', {type: 'number'});

TextureDisplace.prototype.initialize = function() {
    this.currentOffset = 0;
    this.material = this.materialAsset.resource;
};

TextureDisplace.prototype.update = function(dt) {
    this.currentOffset += this.velocity * dt;
    
    if (this.currentOffset >= 1) {
        this.currentOffset -= 1;
    }
    
    this.material.diffuseMapOffset.set(0, this.currentOffset);
};

The update is executed and the currentOffset value changed, but it still doesn’t work (actually it doesn’t happen anything). What am I doing wrong? Thanks!

EDIT: Here is the final solution.

Hi @PolVegaTPM,

So for that to work, you need to update the material, each time you change a material value:

this.material.update();

Though that can be costly if you are doing it per frame. A better way is to use setParameter to set the new offset value directly in the shader.

Check this post on how to do it:

Nice! Then, if I want to use the .setParameter method for the material diffuse map offset, how the code line will look like? I have to call it like this.material.setParameter? What should I put in the string value?

So that parameter expects an array of length 4, for offsetX/Y and tilingX/Y:

this.material.setParameter('texture_diffuseMapTransform', [offsetX, offsetY, tilingX, tilingY);

If you aren’t changing the tiling just put the same values, get them from the material:

var tilingX = this.material.diffuseMapTiling.x;

Hmmm, my script looks now like this, but it still doesn’t make anything (also doesn’t give me any error).

var TextureDisplace = pc.createScript('textureDisplace');

TextureDisplace.attributes.add('materialAsset', {type: 'asset', assetType: 'material'});
TextureDisplace.attributes.add('velocity', {type: 'number'});

TextureDisplace.prototype.initialize = function() {
    this.currentOffset = 0;
    this.material = this.materialAsset.resource;
};

TextureDisplace.prototype.update = function(dt) {
    this.currentOffset -= this.velocity * dt;
    
    if (this.currentOffset <= -1) {
        this.currentOffset += 1;
    }
    
    this.material.setParameter(
        'texture_diffuseMapTransform', 
        [this.material.diffuseMapOffset.x, this.currentOffset, this.material.diffuseMapTiling.x, this.material.diffuseMapTiling.y]
    );
};

Any clue?

Hmm, not sure what that happens, check the following example, in the animating-texture.js script it uses the same parameter:

https://developer.playcanvas.com/en/tutorials/animated-textures/

If you are able, try posting a sample project that reproduces your issue to take a look.

Do you need to call this.material.update(); after changing the parameters?

If you use setParameter on the material or on mesh instances, no you don’t need to update the material.

Only when you change a value on the material pc.Material instance.

2 Likes

I created a sample project with my issue so you can take a close look. Here is the link: https://playcanvas.com/project/766091/overview/diffuse-offset-test

I’m still not getting what am I doing wrong.

Edit: I see setParameter is actually working fine. It updates the values and if you print them you see that is all correct. So the problem is just that that is not being displayed.

Ah so, that’s a common issue with shader chunks or uniforms missing. PlayCanvas tries to optimize the resulting shader and include only the relevant uniforms.

So parameters that have a default value can produce this behavior, of uniforms missing. To workaround this change the diffuse tiling or offset a bit and then the texture_diffuseMapTransform will be included in the shader:

image

1 Like

Hmmm, I have tried it just now and seems to still not work…

Edit: Also tried it with huge numbers without success.

I think the issue now is your script component is disabled, enable it and the texture will roll:

WOW hahahahha I deactivated few minutes ago to test other thinks, good point :sweat_smile:

Now, what I get is a black texture, but it is a step.

With these settings and no other change I get the following:

image

I setup your values and I obtained the same, nice! Nevertheless, I think I’m touching the correct values without getting what am I suppose to get. Touching the parameters through the inspector I get this (what I’m looking for).

Why touching the variables through code I’m not getting the same result?

It seems the order of the values in the array has changed since that post:

image

It’s tilingX/Y and then offsetX/Y. So try this:

    this.material.setParameter(
        'texture_diffuseMapTransform', 
        [this.material.diffuseMapTiling.x, this.material.diffuseMapTiling.y, this.material.diffuseMapOffset.x, this.currentOffset]
    );
2 Likes

Now YES!! Thank you so much for your help!

1 Like

[SOLUTION] :100:
For whoever in the future who is interested in this topic, this are my final results:

Script

var TextureDisplace = pc.createScript('textureDisplace');

TextureDisplace.attributes.add('materialAsset', {type: 'asset', assetType: 'material'});
TextureDisplace.attributes.add('velocity', {type: 'number'});

TextureDisplace.prototype.initialize = function() {
    this.currentOffset = 0;
    this.material = this.materialAsset.resource;
};

TextureDisplace.prototype.update = function(dt) {
    this.currentOffset -= this.velocity * dt;
    
    if (this.currentOffset <= -1) {
        this.currentOffset += 1;
    }
    
    this.material.setParameter(
        'texture_diffuseMapTransform', 
        [this.material.diffuseMapTiling.x, this.material.diffuseMapTiling.y, this.material.diffuseMapOffset.x, this.currentOffset]
    );
};

Material Values (A little bit changed in order to allow the script update them)

3 Likes

Many thanks for sharing that!

1 Like

Hi @Leonidas, the solution for this issue just has stopped working yesterday. Looks like some changes to Playcanvas made this script not work anymore.

Any clue on what is going on or how to fix it? Maybe @yaustar know something about what is happening?

PD: When I say is not working is because the texture does not move anymore.