Failed to execute 'uniform2fv' on 'WebGLRenderingContext'

Description of the problem

sorry for my poor english!
@pailhead use the code from your example:
http://dusanbosnjak.com/test/webGL/three-materials-extended/webgl_materials_extended_multiple_uvs_props_transform.html

    var material = new THREE.MeshStandardMaterial({metalness:0});
    var validMaps = {
        'map': true,
        'metalnessMap': true,
        'normalMap': true
    };

    var setUvTransform = function ( tx, ty, sx, sy, rotation, cx, cy ) {
        var c = Math.cos( rotation );
        var s = Math.sin( rotation ); 
        this.set(
            sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
            - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
            0, 0, 0
        );
    };
    
    var pattern = /#include <(.*)>/gm;
    function parseIncludes( string ){
        function replace( match , include ){
            var replace = THREE.ShaderChunk[ include ];
            return parseIncludes( replace );
        }
        return string.replace( pattern, replace );
    };

    var mapRegex = /texture2D\( (.*Map|map), vUv \)/gm;
    var onBeforeCompile = function ( shader ) {
        var prependUniforms = '';
        var _this = this;
        function replaceMaps( string ){
            function replace( match, mapName ) {
                var uniformName = `u_${mapName}Transform`;
                if(!validMaps[mapName] || shader.uniforms[uniformName]) return match;   //modify by leven                 
                prependUniforms += `uniform mat3 ${uniformName};\n`;
                shader.uniforms[uniformName] = _this.userData.extraUniforms[uniformName];
                shader.uniforms[uniformName].name = uniformName;
                var replace = `texture2D( ${mapName}, ( ${uniformName} * vec3( vUv, 1. ) ).xy )`;
                return replaceMaps( replace ) ;
            }
            return string.replace( mapRegex, replace );
        }
        shader.fragmentShader = parseIncludes(shader.fragmentShader) ;//"unroll" the entire shader
        shader.fragmentShader = replaceMaps(shader.fragmentShader); //patch in the mapping stuff
        shader.fragmentShader = prependUniforms + shader.fragmentShader;
    };

    var extraUniforms = {}
    material.userData.extraUniforms = extraUniforms

    var extraProps = []
    material.userData.extraProps = extraProps

    for ( var mapName in validMaps ){
        if(material[mapName] !== undefined) {
            material[`${mapName}Scale`] = new THREE.Vector2(1,1);               
            material[`${mapName}Rotation`] = 0;

            var uniformName = `u_${mapName}Transform`;

            var uniform = { value: new THREE.Matrix3() , name: mapName };
            uniform.value.name = mapName;
            uniform.value.setUvTransform = setUvTransform.bind(uniform.value);

            extraUniforms[uniformName] = uniform ;
            extraProps.push(mapName);

            material[`${mapName}UpdateMatrix`] = function(_mapName){
                var _uniformName = `u_${_mapName}Transform`;
                this.userData.extraUniforms[_uniformName].value.setUvTransform( 
                    0,
                    0, 
			        this[`${_mapName}Scale`].x,
			        this[`${_mapName}Scale`].y, 
			        this[`${_mapName}Rotation`], 
			        0, 
			        0
                )
            }.bind(material);
        }
        else{
            validMaps[mapName] = false;         
        }
    }
    material.onBeforeCompile = onBeforeCompile.bind(material);

when set normalMap then get a error:

What version are you on? I think that some Vector2 didn’t get passed properly.

r94 and dev

Works fine with 95 dev i just rebased, if you care to post the code i could take a look at it, i’m curious whats happening.

edit

herp derp, i didn’t read you were using normalMap which is doomed to fail, as this code doesn’t account for that. That GLSL has a different pattern, normalMap is the only map not covered by that example i think.

It’s not impossible to do it, but either way you slice it it feels hacky.

The new objectSpace normal map would interfere with the global regex, so the best thing to do would be to manually parse that one chunk that has perturbNormal2Arb(): And then follow the example to compute/wire the uniform (myTransformMatrix).

#ifdef USE_NORMALMAP

	uniform sampler2D normalMap;
	uniform vec2 normalScale;

	#ifdef OBJECTSPACE_NORMALMAP

		uniform mat3 normalMatrix;

	#else

		// Per-Pixel Tangent Space Normal Mapping
		// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html

		vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {
                        //ADD THIS
                        vec2 myUV = vUv;
                        myUv = myTransformMatrix * myUv;

			// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988

			vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );
			vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );
			vec2 st0 = dFdx( myUv .st ); //CHANGE THESE
			vec2 st1 = dFdy( myUv .st );

			float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude

			vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );
			vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );
			vec3 N = normalize( surf_norm );
			mat3 tsn = mat3( S, T, N );

			vec3 mapN = texture2D( normalMap, myUv ).xyz * 2.0 - 1.0; //CHANGE THIS ONE

			mapN.xy *= normalScale;
			mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );

			return normalize( tsn * mapN );

		}

	#endif

#endif

where the uniform myTransformMatrix come from? u_normalMapTransform?
and there is an error when mat3 * vec2:
image

edit

myUv = (u_normalMapTransform * vec3( myUv , 1.)).xy;

it works

edit

var onBeforeCompile = function ( shader ) {
    var prependUniforms = '';
    var _this = this;
    function replaceMaps( string ){
        function replace( match, mapName ) {
            var uniformName = `u_${mapName}Transform`;
            if(!validMaps[mapName] || shader.uniforms[uniformName]) return match;   //add another check              
            prependUniforms += `uniform mat3 ${uniformName};\n`;
            shader.uniforms[uniformName] = _this.userData.extraUniforms[uniformName];
            shader.uniforms[uniformName].name = uniformName;
            var replace = `texture2D( ${mapName}, ( ${uniformName} * vec3( vUv, 1. ) ).xy )`;
            return replaceMaps( replace ) ;
        }
        return string.replace( mapRegex, replace );
    }
    shader.fragmentShader = parseIncludes(shader.fragmentShader) ;//"unroll" the entire shader
    shader.fragmentShader = replaceMaps(shader.fragmentShader); //patch in the mapping stuff
    shader.fragmentShader = prependUniforms + shader.fragmentShader;
};

also works

This looks so messy lol, but it’s the onBeforeCompile

check this out

its possible to rewrite the entire material interface on top of ShaderMaterial, i plan to rearrange the chunks a bit

1 Like

interesting