processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.45k stars 3.29k forks source link

Instance mode resizeCanvas doesn't change pixels array? #4390

Closed vanyamil closed 4 years ago

vanyamil commented 4 years ago

Most appropriate sub-area of p5.js?

Details about the bug:

Main file:

let s = new p5((sketch) => {
    sketch.preload = () => {
        sketch.json = sketch.loadJSON("/raytracer/scenes/boxStacks.json");
    };

    sketch.setup = () => {
        sketch.scene = (new SceneLoader(sketch.json)).scene;
        console.log(sketch.scene);

        // P5 settings
        sketch.startTime = sketch.millis();
        sketch.createCanvas(sketch.scene.cam.width, sketch.scene.cam.height);
        sketch.frameRate(30);

        // Load the pixels into the back buffer
        sketch.loadPixels();
    };

    sketch.draw = () => {
        if(sketch.scene.draw(1000/40, sketch)) { // Roughly 40 FPS limit on ray-tracing, around 30 with overheads
            console.log("Completed drawing in " + (sketch.millis() - sketch.startTime) + " ms.");
            sketch.noLoop();
        }
    };

    sketch.drawFrom = (json) => {
        sketch.noLoop();
        // delete sketch.scene;
        sketch.scene = (new SceneLoader(json)).scene;
        sketch.startTime = sketch.millis();
        sketch.resizeCanvas(sketch.scene.cam.width, sketch.scene.cam.height, false);
        sketch.loop();
    };
});

Scene.js

    draw(timeLimit, sketch) {
        const ray = new Ray();
        const IR = new IntersectionResult();

        // Load the pixels into the back buffer
        sketch.loadPixels();
        console.log("Space for " + sketch.pixels.length + " pixels");
        // console.log("Current dims: " + this.cam.width + "x" + this.cam.height + " pixels");

        // Prepare the interactive loop
        const deadline = sketch.millis() + timeLimit;
        let x = this.lastX;
        let y = this.lastY;

        // Interactive loop - can only go until time limit
        while(sketch.millis() < deadline) {
            sketch.set(x, y, sketch.color(this.getPixel(x, y, ray, IR)));
            x++;
            if(x == this.cam.width) {
                x = 0;
                y++;
                if(y == this.cam.height) {
                    // Put those pixels into main buffer/canvas
                    sketch.updatePixels();
                    // We finished drawing
                    return true;
                }
            }
        }
        // Put those pixels into main buffer/canvas
        sketch.updatePixels();
        // Not yet finished drawing, save state
        this.lastX = x;
        this.lastY = y;
        return false;
    }

It looks like when s.drawFrom is launched, the resize does everything correctly w.r.t. my code as well as modifies the HTML element of the canvas. However, it does not change the length of the pixels array of the sketch (the console.log returns identical messages after calling drawFrom with a setup with different camera w/h), and the render still looks broken (image below; you can see that right size is left untouched after canvas resize). Perhaps it's something I don't understand about use of loadPixels and resizeCanvas? download (1)

vanyamil commented 4 years ago

Looks like it could be an issue with exact timing - possibly updatePixels and loadPixels could be in a race condition. Modifying a couple of lines fixed it for now.