You're scaling the square by approximately 4 (1 / 0,27 = 3.7 ~ 4), but you always draw the same amount of vertices, this way the distance between two pixels becomes 4 instead of one.
Instead of drawing width * height vertices and scaling their positions accordingly, scale the width, height and position of the square, then go through the pixels in that area, in pseudo code:
// xPos, yPos and zPos are the position, width and height are the sizes // Calculate new position and size newXPos = (int)(xPos / zPos) newYPos = (yPos / zPos) newWidth = (width / zPos) newHeight = (height / zPos) // Loop through pixels for (integer x from newXPos to newXPos + width) { for (integer y from newYPos to newYPos + width) { setPixel(x, y, "#ffffff") } } Working demo in javascript:
let xPos = -30, yPos = -30, zPos = 0.25, width = 60, height = 60; let c = document.getElementById("canvas"); let ctx = c.getContext("2d"); ctx.fillStyle = "black"; function change() { zPos = parseFloat(document.getElementById("z").value); console.log(document.getElementById("z").value) } function draw() { ctx.clearRect(0, 0, 300, 300); let newXPos = Math.floor(xPos / zPos) + 150; // The + 150 part centers the (0; 0) coordinate let newYPos = Math.floor(yPos / zPos) + 150; let newWidth = Math.floor(width / zPos); let newHeight = Math.floor(height / zPos); for (let x = newXPos; x < newXPos + newWidth; x++) { for (let y = newYPos; y < newYPos + newHeight; y++) { ctx.fillRect(x, y, 1, 1); // Draw pixel } } console.log(newXPos, newYPos, width, height) } setInterval(draw, 33) <canvas id="canvas" width="300px" height="300px" style="border: 1px solid black"></canvas><br /> <span>Z coordinate:</span> <input id="z" type="number" value="0.25" onchange="change()"/>