[SOLVED] Shader chunk issues - "this.material.setParameter is not a function"

Here is the project I will be referencing.
https://playcanvas.com/project/608682/overview/shaders

I’ll start by saying that I don’t really know what i’m doing when it comes to shader language, but what i’m trying to do is not very complicated (eg. Mixing 2 textures in the shader to use as a single diffuse) and I’ve managed to figure out enough that I thought I’d be able to get something going.

I’ve been going in circles for a long time and unable to find a proper way to use shader chunk replacement with custom parameters.

I can replace the shader chunk, mess around with the colors etc. BUT my problem is that I don’t seem to be able to send any information to the shader, the key issue I think is that MaterialReplaceChunk line 50:

this.material.setParameter('uTexMap', this.TexMap.resource);

results in: “this.material.setParameter is not a function” when launched.
As you might be able to see with everything commented out in the code I’ve been going in circles trying different approaches to figure out what the deal is and what i’m doing wrong.

There are a few parts of this script that are taken from tutorials that I don’t totally understand but that I don’t think will interfere with what i’m trying to do.

Is there anything really obvious i’m missing somewhere? The documentation just doesn’t exist and I’ve managed to get most of my understanding from a few tutorials and scattered forum posts.

Cheers for any help, this is driving me mad.
Joe.

this.material is referencing an asset, not the material itself. Try this.material.resource.setParameter instead.

1 Like

Weird, I was sure i’d tried that! cheers :slight_smile:
My new issue is accessing a texture parameter.

I can’t seem to figure out how to convert my ‘uniform sampler2D uTexMap1’ into RGB values to use with the dAlbedo output.
Most recent attempt is this:

vec4 uTexMap1Tex = texture2D(uTexMap1, $UV);

But then I get the error ‘failed to compile fragment shader’

Ok, I’ve spent more time fiddling around with this and I seem to have cracked it (But I don’t totally remember what i’m doing differently now)

For anyone having issues with pushing your own parameters to custom shader chunks with playmaker, here is my current working solution:

frag shader:

uniform vec3 material_diffuse;
uniform sampler2D texture_diffuseMap;

//CUSTOM PARAMETERS//

uniform sampler2D uTexMap1;
uniform sampler2D uTexMap2;
uniform float utest;

//////////////////////

void getAlbedo() {
    
    dAlbedo = material_diffuse;
    
    #ifdef MAPTEXTURE
    
    vec3 TexCol = texture2DSRGB(uTexMap1, $UV).$CH;
    TexCol += (texture2DSRGB(uTexMap2, $UV).$CH)*.5;
       dAlbedo *= TexCol*utest;
        #endif

    
    //dAlbedo = material_diffuse.rgb;
}

.JS:

var MaterialReplaceChunk = pc.createScript('materialReplaceChunk');

MaterialReplaceChunk.attributes.add('material', {
    type: 'asset',
    assetType: 'material'
});

MaterialReplaceChunk.attributes.add('fragshader', {
    type: 'asset',
    assetType: 'shader',
    title: 'Fragment Shader'
});


///////////////ATTRIBUTES/////////////////

MaterialReplaceChunk.attributes.add('TexMap', { type: 'asset', assetType: 'texture'});
MaterialReplaceChunk.attributes.add('TexMap2', { type: 'asset', assetType: 'texture'});


/////////////////////////////////////////


MaterialReplaceChunk.prototype.initialize = function() {
    this.onShaderLoad();
    
    if (this.fragshader)
        this.fragshader.on('load', this.onShaderLoad, this);
    
    this.on('attr:fragshader', function(value, valueOld) {
        if (valueOld)
            valueOld.off('load', this.onShaderLoad, this);
        
        if (value)
            value.on('load', this.onShaderLoad, this);
        
        this.onShaderLoad();
    });
    
    this.on('attr:material', this.onShaderLoad, this);
};

MaterialReplaceChunk.prototype.onShaderLoad = function() {
    if (! this.material)
        return;
    
    this.material.resource.chunks.diffusePS  = this.fragshader && this.fragshader.resource || '';
    
    //LOAD IN YOUR ATTRIBUTE PARAMETERS HERE
    
     this.material.resource.setParameter('utest',1);
    this.material.resource.setParameter('uTexMap1', this.TexMap.resource);
        this.material.resource.setParameter('uTexMap2', this.TexMap2.resource);
    
    /////////////////////////////////////////
    
    
    console.log(this.material.resource.getParameter('uTexMap1'));

    this.material.resource.update();
};

Instsructions:
In your assets folder create a .Js file, frag shader, material, and bring in 2 different textures.

Copy and paste the frag shader segment from above into the frag shader.
Copy and paste the JS segment above to the .Js file.
Add the JS script to an entity in the scene and parse it.
Add your frag shader, material and 2 textures to the attributes of the script.
IMPORTANT: Make sure you supply your material with an initial diffuse texture, this is what triggers the #ifdef MAPTEXTURE” in the shader, without it you will get errors if no initial texture is defined, with it your object will just appear with the diffuse color and no textures when no initial texture is defined.
Now Add your material to any object in the scene.

When you hit launch you should see your object with the 2 textures blended together.
You will get errors if you don’t supply both texture parameters.
Hopefully this helps someone in future! Took me a while to get this working, and I still don’t totally understand but hopefully this is enough for what I need. :slight_smile:
Happy Playcanvas-ing!

Cheers,
Joe.

3 Likes