I am stuck in a issue with generating textures.
query : grouts and layouts are being generated as per the selection, but have white dashes in between the grout lines being drawn. also layout type is not getting applied on the floor. I have tested that layout type 2 was passed for wall and floor but generated different outputs as following.
fshader
export default `
uniform sampler2D tileTexture;
uniform float tileWidth;
uniform float tileHeight;
uniform float planeWidth;
uniform float planeHeight;
uniform float scaleFactor;
uniform int layoutType; // 0 for grid, 1 for brick, 2 for brick2
varying vec2 vUv;
void main() {
float repeatX = (planeWidth / tileWidth) * scaleFactor;
float repeatY = (planeHeight / tileHeight) * scaleFactor;
vec2 uv = vUv;
if (layoutType == 1) {
// Brick layout
uv.x += mod(floor(vUv.y * repeatY), 2.0) * 0.5;
} else if (layoutType == 2) {
// Brick2 layout
uv.y += mod(floor(vUv.x * repeatX), 2.0) * 0.5;
}
uv = mod(uv * vec2(repeatX, repeatY), 1.0);
gl_FragColor = texture2D(tileTexture, uv);
}
`;
vshader
export default `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
script.js
// Function to load an image
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
img.onload = () => resolve(img);
img.onerror = reject;
img.src = url;
});
}
// Function to find the next power of 2
function nextPowerOf2(x) {
return Math.pow(2, Math.ceil(Math.log2(x)));
}
// Function to draw grout lines on a tile image
function drawGroutLines(image, groutColor = "red", groutWidth = 10, groutAlpha = 1) {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.width = nextPowerOf2(image.width);
canvas.height = nextPowerOf2(image.height);
// Draw the tile image on the canvas
context.drawImage(image, 0, 0, canvas.width, canvas.height);
// Draw grout lines
context.strokeStyle = groutColor;
context.globalAlpha = groutAlpha;
context.lineWidth = groutWidth;
context.strokeRect(0, 0, canvas.width, canvas.height);
context.globalAlpha = 1;
return canvas;
}
async function loadTextureAndSetRepeat({ element, rotateAngle = 0, layout = 'brick2' }) {
let surfaceData = element.userData;
let randomIndex = Math.floor(Math.random() * tilesData.length);
let currentTexture = tilesData[randomIndex];
const imageUrls = currentTexture.imgUrl;
loadImage(imageUrls[0])
.then((firstImage) => {
const tiWidthMM = firstImage.width; // Tile width in mm
const tiHeightMM = firstImage.height; // Tile height in mm
const tiWidthM = tiWidthMM / 1000; // Convert to meters
const tiHeightM = tiHeightMM / 1000; // Convert to meters
const planeHeightM = surfaceData.height; // Plane height in meters
const planeWidthM = surfaceData.width; // Plane width in meters
// Determine scale factor based on surface type
const scaleFactor = surfaceData.type === 'wall' ? 0.025 : 0.012;
Promise.all(imageUrls.map(loadImage))
.then((images) => {
const processedImages = images.map(img => drawGroutLines(img));
const texture = new THREE.Texture(processedImages[0]);
texture.needsUpdate = true;
// Determine layout type
let layoutType = 0; // Default to grid
if (layout === 'brick') {
layoutType = 1;
} else if (layout === 'brick2') {
layoutType = 2;
}
// Create a shader material to handle repetition
const shaderMaterial = new THREE.ShaderMaterial({
uniforms: {
tileTexture: { value: texture },
tileWidth: { value: tiWidthM },
tileHeight: { value: tiHeightM },
planeWidth: { value: planeWidthM },
planeHeight: { value: planeHeightM },
scaleFactor: { value: scaleFactor },
layoutType: { value: layoutType }
},
vertexShader,
fragmentShader,
side: THREE.DoubleSide // Make the shader material double-sided
});
// Ensure the element has the necessary material properties for the shader
element.material = shaderMaterial;
element.material.needsUpdate = true;
// Render the scene to reflect the texture change
renderer.render(scene, camera);
})
.catch((error) => {
console.error("Error loading images:", error);
});
})
.catch((error) => {
console.error("Error loading first image:", error);
});
}