Modify shader chunk UV tiling

I’m currently failing to adjust the tiling of the UVs in my shaderchunk which adds a secondary normal map:
I’m trying to do \$UV * normalMap2_tiling which errors in:
Failed to execute 'uniform2fv' on 'WebGL2RenderingContext': Overload resolution failed.
When I do \$UV * vec2(10.0, 10.0) it somehow works.
What am I doing wrong here?

var SecondaryNormal = pc.createScript('secondaryNormal');

SecondaryNormal.attributes.add('normalMap', { type: 'asset', assetType: 'texture' });
SecondaryNormal.attributes.add('bumpiness', { type: 'number', default: 1, min: 0, max: 2 });
SecondaryNormal.attributes.add('tiling', { type: 'vec2', default: [1, 1] });

SecondaryNormal.prototype.initialize = function () {
    this.material = this.entity.render.meshInstances[0].material.clone();
    this.entity.render.meshInstances[0].material = this.material;

    // vUv0, vUv1
    this.material.chunks.normalMapPS = `
        uniform sampler2D normalMap2;
        uniform float material_bumpiness2;
        uniform vec2 normalMap2_tiling;
        #ifdef MAPTEXTURE
            uniform float material_bumpiness;
        #endif

        void getNormal() {
            #ifdef MAPTEXTURE
                vec3 normalMap = unpackNormal(texture2DBias(\$SAMPLER, \$UV, textureBias));
                normalMap = mix(vec3(0.0, 0.0, 1.0), normalMap, material_bumpiness);
                vec3 normalMap2 = unpackNormal(texture2DBias(normalMap2, \$UV * normalMap2_tiling, textureBias));
                normalMap2 = mix(vec3(0.0, 0.0, 1.0), normalMap2, material_bumpiness2);
                normalMap = vec3(normalMap.xy + normalMap2.xy, normalMap.z);
                dNormalW = normalize(dTBN * addNormalDetail(normalMap));
            #else
                dNormalW = dVertexNormalW;
            #endif
        }
    `;
    this.material.chunks.APIVersion = pc.CHUNKAPI_1_65;

    this.material.setParameter('normalMap2_tiling', this.tiling);
    this.material.setParameter('material_bumpiness2', this.bumpiness);
    this.material.setParameter('normalMap2', this.normalMap.resource);
    this.material.update();
};

If you need an additional normal map, this functionality could be useful for you possibly: Detail Maps · Issue #1962 · playcanvas/engine · GitHub

I think your problem could be that the parameter type for vec2 in the shader is not Vec2 in the engine, but Float32Array of size 2.

this.material.setParameter('normalMap2_tiling', 
           new Float32Array(this.tiling.x, this.tiling.y));
1 Like

Your absolutly right! This works:
this.material.setParameter('normalMap2_tiling', [this.tiling.x, this.tiling.y]);

Thanks for github link. Looks promising! Does every map also implement a detail map or only the ones listed in the PR?
Because I also need a detail map for glossiness.

Oh it’s all documented here
My bad. Guess I have to do glossiness myself :slight_smile:

1 Like

Ok so I’ve tried around a bit with the normal detail map. But it seems like it is not working as intended or I’m doing something wrong.
It seems like the normalDetailMapTiling affects the tiling of the standard normal map as well.
Also when setting bumpiness of my default normal map to 0 I can somehow still see it on the mesh.

Unfortunetly I can’t create a sample right now as I’m quite busy.

For reference here is the script I’m currently using:

var ShaderChunkExtensions = pc.createScript('shaderChunkExtensions');

ShaderChunkExtensions.attributes.add('useNormalMap', { type: 'boolean', default: false });
ShaderChunkExtensions.attributes.add('normalDetailMap', { type: 'asset', assetType: 'texture' });
ShaderChunkExtensions.attributes.add('normalDetailMapBumpiness', { type: 'number', default: 1, min: 0, max: 2 });
ShaderChunkExtensions.attributes.add('normalDetailMapOffset', { type: 'vec2', default: [0.0, 0.0] });
ShaderChunkExtensions.attributes.add('normalDetailMapRotation', { type: 'number', default: 0, min: 0, max: 360 });
ShaderChunkExtensions.attributes.add('normalDetailMapTiling', { type: 'vec2', default: [1.0, 1.0] });
ShaderChunkExtensions.attributes.add('normalDetailMapUv', {
    type: 'number', enum: [
        { 'UV0': 0 },
        { 'UV1': 1 }
    ], default: 0
});

ShaderChunkExtensions.prototype.initialize = function () {
    this.material = this.entity.render.meshInstances[0].material.clone();
    this.entity.render.meshInstances[0].material = this.material;

    this.material.chunks.APIVersion = pc.CHUNKAPI_1_65;

    if (this.useNormalMap) {
        this.setupNormalDetailMap();
    }

    this.material.update();
};

ShaderChunkExtensions.prototype.setupNormalDetailMap = function () {
    this.material.normalDetailMap = this.normalDetailMap;
    this.material.normalDetailMapBumpiness = this.normalDetailMapBumpiness;
    this.material.normalDetailMapOffset = this.normalDetailMapOffset;
    this.material.normalDetailMapRotation = this.normalDetailMapRotation;
    this.material.normalDetailMapTiling = this.normalDetailMapTiling;
    this.material.normalDetailMapUv = this.normalDetailMapUv;
};