October 22, 2024
Chicago 12, Melborne City, USA
javascript

Weird bug when drawing on Canvas with THREE.js


I have this weird bug on my website when I try to draw on a canvas. I’m using cameras to "take a picture" of walls and draw them on canvases. I have 4 of these, but for some reason only this canvas is acting weird and I have no idea why. This is how it would look normally. I recently started learning three.js, pls help guys…

Here is the code of how I draw them:

const wallDirections = [
    { position: { x: 0, y: 495, z: 500 }, lookAt: { x: 0, y: 495, z: -1 } },  
    { position: { x: -500, y: 495, z: 0 }, lookAt: { x: 1, y: 495, z: 0 } },   
    { position: { x: 0, y: 495, z: -500 }, lookAt: { x: 0, y: 495, z: 1 } }, 
    { position: { x: 500, y: 495, z: 0 }, lookAt: { x: -1, y: 495, z: 0 } } 
];

wallDirections.forEach(direction => {
    const distanceFromWall = roomSize;
    const verticalFOV = 2 * Math.atan((roomSize / 2) / distanceFromWall) * (180 / Math.PI);
    const wallCamera = new THREE.PerspectiveCamera(verticalFOV, 1, 0.1, 1800);
    wallCamera.position.set(direction.position.x, direction.position.y, direction.position.z);
    wallCamera.lookAt(direction.lookAt.x, direction.lookAt.y, direction.lookAt.z);

    const renderTarget = new THREE.WebGLRenderTarget(1000, 1000);
    wallCameras.push(wallCamera);
    wallTextures.push(renderTarget.texture);
    wallRenderTargets.push(renderTarget);
});

function renderWallPreviews() {
    wallCameras.forEach((camera, index) => {
        renderer.setRenderTarget(wallRenderTargets[index]);
        renderer.render(scene, camera);
        renderer.setRenderTarget(null);
    });
}

function updateWallPreviews() {
    const previewCanvases = getPreviewCanvases();
    const letters = ['A','B','C','D'];
    previewCanvases.forEach((canvas, index) => {
        if (canvas) {
            const context = canvas.getContext("2d");
            const canvasWidth = canvas.width;
            const canvasHeight = canvas.height;

            const width = wallRenderTargets[index].width;
            const height = wallRenderTargets[index].height;
            const pixels = new Uint8Array(width * height * 4); // RGBA format

            // Read the pixels from the render target
            renderer.readRenderTargetPixels(wallRenderTargets[index], 0, 0, width, height, pixels);

            // Manually flip the image data
            const flippedPixels = new Uint8Array(width * height * 4);
            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const srcIndex = (y * width + x) * 4;
                    const destIndex = ((height - y - 1) * width + x) * 4;

                    flippedPixels[destIndex] = pixels[srcIndex];
                    flippedPixels[destIndex + 1] = pixels[srcIndex + 1];
                    flippedPixels[destIndex + 2] = pixels[srcIndex + 2];
                    flippedPixels[destIndex + 3] = pixels[srcIndex + 3];
                }
            }

            // Create ImageData from the flipped pixel buffer
            const imageData = new ImageData(new Uint8ClampedArray(flippedPixels), width, height);

            // Create an off-screen canvas to resize the image data
            const offScreenCanvas = document.createElement('canvas');
            offScreenCanvas.width = width;
            offScreenCanvas.height = height;
            const offScreenContext = offScreenCanvas.getContext('2d');

            // Draw ImageData onto the off-screen canvas
            offScreenContext.putImageData(imageData, 0, 0);

            // Calculate aspect ratios for resizing
            const imgAspectRatio = width / height;
            const canvasAspectRatio = canvasWidth / canvasHeight;

            let renderWidth, renderHeight;
            if (imgAspectRatio > canvasAspectRatio) {
                renderWidth = canvasWidth;
                renderHeight = canvasWidth / imgAspectRatio;
            } else {
                renderHeight = canvasHeight;
                renderWidth = canvasHeight * imgAspectRatio;
            }

            // Clear the canvas before drawing
            context.clearRect(0, 0, canvasWidth, canvasHeight);

            // Center the resized image on the canvas
            const offsetX = (canvasWidth - renderWidth) / 2;
            const offsetY = (canvasHeight - renderHeight) / 2;

            // Draw the resized image from the off-screen canvas onto the main canvas
            context.drawImage(offScreenCanvas, 0, 0, width, height, offsetX, offsetY, renderWidth, renderHeight);
            context.font = "bold 30px Arial";
            context.fillStyle = "white";
            context.fillText(letters[index], 10, 40);
        }
    });
}



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video