[SOLVED] Increase Material Diffuse Map Offset not working

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.

Hi @PolVegaTPM,

We added support for rotation to augment the texture offset & tiling and in the process changed the format of the shader uniform. Instead of a one vec4 with [tiling.x, tiling.y, offset.x, offset.y], we now have a 3x2 texture matrix stored as two vec3’s.

We are in discussions to change the internal format again, because it has become difficult to override. In any case, to fix this now you can set tiling & offset as follows:
‘texture_diffuseMapTransform0’: [tiling.x, 0, offset.x]
‘texture_diffuseMapTransform1’: [0, tiling.y, offset.y]

Sorry for the trouble!

2 Likes

Thanks for the answer @slimbuck,

With this change it works now fine again.

Please, update this post in case you change again this method.

@PolVegaTPM please see this thread about this change Material parameter uniform names have changed since 1.46.0 - #2 by Leonidas

Unfortunately, as it’s private API and uniforms, it’s subject to change without formal notice since it doesn’t change/break public API.

If it does change, it’s likely to be in the release version as part of an 1.X.0 release with notes on material refactor (If you can subscribe to the engine repo releases)

If it’s possible, swap to using a cloned material and use the material’s offset/tiling properties to be future proof as they are public API

It will break batching but the performance cost should be negligible.

Setting uniforms on meshInstance breaks batching already.

2 Likes