@manthrax I took reference from this post.
I tried by changing different images, it almost works correctly.
demo : Glitch :・゚✧
EDIT : it works for square tile textures
can you please guide how can we implement that texture repetition in following function with grouts ?
function loadTextureAndSetRepeat({ element, rotateAngle = 0 }) {
let surfaceData = element.userData;
let randomIndex = Math.floor(Math.random() * tilesData.length);
let currentTexture = tilesData[randomIndex];
const imageUrls = currentTexture.imgUrl;
// Convert surfaceData width and height from feet to meters
const feetToMeters = 0.3048;
const wallWidthMeters = surfaceData.width * feetToMeters;
const wallHeightMeters = surfaceData.height * feetToMeters;
const createTextureWithGrout = (images, widthMeters, heightMeters) => {
const tileWidthMeters = 6; // Tile width in meters (600mm)
const tileHeightMeters = 6; // Tile height in meters (600mm)
const groutThicknessMeters = 0.2; // Grout thickness in meters (5mm)
const columns = Math.ceil(widthMeters / tileWidthMeters);
const rows = Math.ceil(heightMeters / tileHeightMeters);
// Create a canvas to draw the combined texture
const canvas = document.createElement('canvas');
canvas.width = Math.ceil((tileWidthMeters * columns) * 100); // Convert to pixels
canvas.height = Math.ceil((tileHeightMeters * rows) * 100); // Convert to pixels
const context = canvas.getContext('2d');
// Check if images are loaded before proceeding
if (images.some(image => !image.complete || image.naturalWidth === 0)) {
throw new Error('One or more images failed to load.');
}
// Draw each image with grout lines
for (let col = 0; col < columns; col++) {
for (let row = 0; row < rows; row++) {
const x = col * tileWidthMeters * 100;
const y = row * tileHeightMeters * 100;
const image = images[(row * columns + col) % images.length];
// Create a temporary canvas to draw the tile with grout
const tileCanvas = document.createElement('canvas');
tileCanvas.width = tileWidthMeters * 100;
tileCanvas.height = tileHeightMeters * 100;
const tileContext = tileCanvas.getContext('2d');
// Draw the tile image on the temporary canvas
tileContext.drawImage(image, 0, 0, tileCanvas.width, tileCanvas.height);
// Draw the grout lines on the tile image
tileContext.fillStyle = 'rgb(255, 0, 0)'; // Red grout color
// Draw vertical grout lines
tileContext.fillRect(tileCanvas.width - groutThicknessMeters * 100, 0, groutThicknessMeters * 100, tileCanvas.height);
// Draw horizontal grout lines
tileContext.fillRect(0, tileCanvas.height - groutThicknessMeters * 100, tileCanvas.width, groutThicknessMeters * 100);
// Draw the modified tile image on the main canvas
context.drawImage(tileCanvas, x, y);
}
}
// Create the Three.js texture from the canvas
const texture = new THREE.CanvasTexture(canvas);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.rotation = Math.PI * tileTextureRotation;
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
return texture;
};
const loadImages = (urls) => {
return Promise.all(urls.map((url) => {
return new Promise((resolve, reject) => {
const image = new Image();
image.crossOrigin = "anonymous"; // To handle CORS issues
image.onload = () => resolve(image);
image.onerror = (error) => reject(error);
image.src = url;
});
}));
};
loadImages(imageUrls)
.then((images) => {
const combinedTexture = createTextureWithGrout(images, wallWidthMeters, wallHeightMeters);
// Assign texture to element material in Three.js
element.material.map = combinedTexture;
element.material.needsUpdate = true;
// Render scene
renderer.render(scene, camera);
})
.catch((error) => {
console.error('Error loading images:', error);
});
}