rewrite this code to fix the incorrect sorting of the triangles/normals, causing the shading to be messed up because the normals dont correspond to the right vertices:

fillTriangle(v0, v1, v2, color0, color1, color2) {
    const { width, height, imageBuffer, depthBuffer } = this;

    // Sort the vertices by y-coordinate ascending (v0.y <= v1.y <= v2.y)
    let sortedVertices = [v0, v1, v2].sort((a, b) => a[1] - b[1]);
    const [sv0, sv1, sv2] = sortedVertices;

    // Precompute the denominator for barycentric coordinates
    const denom = (sv1[1] - sv2[1]) * (sv0[0] - sv2[0]) + (sv2[0] - sv1[0]) * (sv0[1] - sv2[1]);
    if (denom === 0) return; // Degenerate triangle

    const invDenom = 1 / denom;

    // Precompute color reciprocals for perspective-correct interpolation if needed
    // Assuming colors are vectors [r, g, b]
    // If perspective correction is not required, this can be simplified

    // Determine the bounding box of the triangle
    const yStart = Math.max(0, Math.ceil(sv0[1]));
    const yEnd = Math.min(height - 1, Math.floor(sv2[1]));

    // Precompute edge slopes to avoid division inside the loop
    const edges = [
        { v1: sv0, v2: sv1 },
        { v1: sv1, v2: sv2 },
        { v1: sv2, v2: sv0 }
    ];

    for (let y = yStart; y <= yEnd; y++) {
        let xMin = width, xMax = 0;

        // Find intersection points with the current scanline
        for (const edge of edges) {
            const { v1, v2 } = edge;
            if (y < Math.min(v1[1], v2[1]) || y > Math.max(v1[1], v2[1])) continue;

            const dy = v2[1] - v1[1];
            if (dy === 0) continue; // Horizontal edge, already handled

            const t = (y - v1[1]) / dy;
            const x = v1[0] + t * (v2[0] - v1[0]);

            xMin = Math.min(xMin, x);
            xMax = Math.max(xMax, x);
        }

        // Clamp the x boundaries to the screen
        const xStart = Math.max(0, Math.ceil(xMin));
        const xEnd = Math.min(width - 1, Math.floor(xMax));

        // Precompute the base index for the current scanline
        const baseIndex = y * width;

        for (let x = xStart; x <= xEnd; x++) {
            // Compute barycentric coordinates
            const w0 = ((sv1[1] - sv2[1]) * (x - sv2[0]) + (sv2[0] - sv1[0]) * (y - sv2[1])) * invDenom;
            const w1 = ((sv2[1] - sv0[1]) * (x - sv2[0]) + (sv0[0] - sv2[0]) * (y - sv2[1])) * invDenom;
            const w2 = 1 - w0 - w1;

            // Early rejection if the point is outside the triangle
            if (w0 < 0 || w1 < 0 || w2 < 0) continue;

            // Depth interpolation (assuming z is at index 2)
            const zInterpolated = 1 / (w0 / v0[2] + w1 / v1[2] + w2 / v2[2]);

            // Buffer index
            const index = baseIndex + x;

            if (zInterpolated < depthBuffer[index]) {
                depthBuffer[index] = zInterpolated;

                // Color interpolation (assuming colors are scalars; adjust if RGB)
                const interpolatedColor = w0 * color0 + w1 * color1 + w2 * color2;

                // If colors are RGB, interpolate each channel separately:
                // const r = w0 * color0[0] + w1 * color1[0] + w2 * color2[0];
                // const g = w0 * color0[1] + w1 * color1[1] + w2 * color2[1];
                // const b = w0 * color0[2] + w1 * color1[2] + w2 * color2[2];
                // const a = 255;

                // For grayscale, use the single interpolated value across R, G, B
                const shadedColor = [
                    interpolatedColor,
                    interpolatedColor,
                    interpolatedColor,
                    255
                ];

                const bufferIndex = index * 4;
                imageBuffer.data[bufferIndex] = shadedColor[0];
                imageBuffer.data[bufferIndex + 1] = shadedColor[1];
                imageBuffer.data[bufferIndex + 2] = shadedColor[2];
                imageBuffer.data[bufferIndex + 3] = shadedColor[3];
            }
        }
    }
}