What is the Best Way to Repeat the Same Animated Material on a Single Plane?

I have a subroutine that creates an animated displacement map and a normal map. I have used these maps to create a couple of MeshPhysicalMaterials - one that includes both maps (along with a texture map) and one that includes only the normal map (and no texture map, only a color). I have created two different types of plane geometries to hold these materials: one that will hold the first material and another that is 4X larger that will hold the second material. To make things consistent, I need to repeat the second material 4X on the second geometry.

What is the best way to repeat materials on the second geometry? Here is what things look like right now:

4X

You can see the clear line of demarcation where the materials get larger again.

I have seen a lot about repeating textures, but very little about repeating materials. Here, if I make the textures repeat, then they will repeat for both geometries (and that may also mess up the computation of those textures).

I have tried the following material shader extension that will change the UVs for a diffuseColor:

onBeforeCompile: shader => {
	shader.fragmentShader = `
	${shader.fragmentShader}
	`
	.replace(
		`#include <color_fragment>`,
		`#include <color_fragment>
			vec2 uv2 = fract(vUv * 2.0);
			diffuseColor.a = 1.0 - (uv2.x * uv2.y);
		`
	);
}

But it appears to have no effect on the normalColor.

I could define the geometry of the second plane to include 4 segments, but is there a way to insert a material in each segment?

I have tried something like this:

	let geometry2 = new THREE.PlaneGeometry(size,size,2,2);
	let materials2 = [material2,material2,material2,material2];
	let mesh2 = new THREE.Mesh(geometry2,materials2);

But that does not seem to work.

I have also tried:

	let geometry2 = new THREE.PlaneGeometry(size,size,2,2);
	let materials2 = [material2,material2,material2,material2];
		geometry2.groups=[];
		var triangles=2;
		var vertices=triangles*3;
		for(let n=0;n<4;n++){
			geometry2.groups.push({start:n*vertices,count:vertices,materialIndex:n});
		}
	let mesh2 = new THREE.Mesh(geometry2,materials2);

Again, no joy.

Also, since I am merely repeating the same material 4X, I would like to minimize the number of draw calls for each plane, if that is possible.

EDIT
My initial assumption may have been wrong. The problem seems to disappear when I use repeat.set(2,2) on the normal texture before it is used to construct material2.
However, the problem then reappears at higher altitudes - perhaps mipmaps are playing a role here?

Looking at the code, it appears you multiply the UV coordinates by (2,2) only when calculating diffusionColor.a. I’d expect that other places in the shader, where UV is used, are not adjusted and this causes the disruption in appearance. Using repeat.set(2,2) adjusts these other places.

You should not need 4 materials, 4 plane segments or 4 planes to make what you want. One plane and one material should be sufficient.

1 Like

Yes, that appears to be the case.

The problem arose because I switched from having a 27X27 grid of inner 2 mile squares and an outer grid of 27X27 6 mile squares to having a 16X16 grid of 2 mile squares and an outer grid of 16X16 8 mile squares. In the former, the split between resolutions was at 27 miles while, in the latter, it was at only 16 miles - visible at 10k feet.

When I wrote the EDIT above, I had forgotten that, since I am using 3 square sizes (which both share material2), I needed to increase the repeat to 4,4 for square size 3. At 25k feet, I was starting to see the split between square sizes 2 and 3 (at 64 miles).

It works fine now (here).

I am using 2 materials for 3 geometries.

Thanks for taking the time to address all my questions.

1 Like