Code Monkey home page Code Monkey logo

Comments (19)

GoodBoyDigital avatar GoodBoyDigital commented on March 28, 2024

Nice idea 👍 I will add the feature to my list. Would be useful for pixel art / retro games!

from pixijs.

ateoto avatar ateoto commented on March 28, 2024

I was experiencing this as well, not only blurring but strange artifacts on the sprites as well. I implemented the solution in the article and it seems to fix the issue for me.

This is a version of Pixi.js built with that fix in there, see if that works for you. https://github.com/Ateoto/pixi.js/blob/feature-pixelsnap/bin/pixi.dev.js

This is where I implemented the fix:
ateoto@3d0cb99

from pixijs.

GoodBoyDigital avatar GoodBoyDigital commented on March 28, 2024

Excellent, will give it a whirl!

from pixijs.

englercj avatar englercj commented on March 28, 2024

You can achieve this easily on the user-land side, I don't think it is something we want to force into the core.

from pixijs.

bartvanheukelom avatar bartvanheukelom commented on March 28, 2024

I'd appreciate support for this in Pixi itself (currently patching it in). How do you envision arranging it in user-land? It's doable if all display objects are in a single, pixel-aligned container, but it becomes highly impractical when nested objects are used, where the misalignment may occur at any level in the tree.

from pixijs.

englercj avatar englercj commented on March 28, 2024

The short answer is to just take care not to assign floating values to your positions, if something is a delta change round/floor/ceil it before assigning.

You're right, this isn't an easy problem to solve, but I don't think the solution is to make objects everywhere have a potentially expensive branching path and math operation to catch mistakes a situation that only exists when doing certain types of applications. Canvas renderer currently has a roundPixels option that increases rendering speed by flooring positions as images are drawn, but it doesn't work like that on WebGL. We would have to round/floor/ceil positions in js which would negatively effect the renderer's performance.

There is also the issue that some applications want to round positions as the move, some want to floor, and some want to ceil, some want to let the browser interpolate normally. It depends on the application. If the answer is "it depends on the application" it probably doesn't belong in the core.

I'm not convinced that this belongs in pixi core because it means adding a branch to every update transform call at best, or many branches at worst. I'm still of the opinion that you should just round/floor/ceil your values you assign to positions as you do it in your application, if it makes sense to do so in your application. I've done this in quite a few apps now, usually there is only a couple (or just one) physics integration point where positions are actually being set. Generally when syncing the body positions to the sprite I just floor it, and it works well (sometimes round, depending).

from pixijs.

bartvanheukelom avatar bartvanheukelom commented on March 28, 2024

Take for example a spaceship moving slowly around a space. You don't want to round its x and y, because then you can't achieve the slow motion. The spaceship has lots of elements, rotating turrets, etc. Also, there is zooming and rotation of the view going on.
You only want the leaves in the display tree, the actual sprites, to snap to the pixel grid. The only practical place to apply this would be somewhere between updateTransform and the actual rendering.

I fully sympathize with not wanting to add code to fix a very specific problem in such a general location. I'm all for separation of concerns. (Why does BaseTexture deal with loading/caching images from urls? :-] )
So would you consider adding an optional callback inside/after DisplayObject.transform? It would receive the updated matrix, allowing it to modify it further, e.g. applying rounding/flooring/whatever to the translation values.

If you're worried about branching, you might implement it somewhat like this:

DisplayObject.prototype.setTransformCallback = function(cb) {
    if (cb != null) {
        this.updateTransform = function() {
            DisplayObject.prototype.updateTransform.call(this);
            cb(this.worldTransform);
        };
    } else {
        delete this.updateTransform; // revert to using the prototype version
    }
}

from pixijs.

englercj avatar englercj commented on March 28, 2024

(Why does BaseTexture deal with loading/caching images from urls? :-] )

Historical and usability reasons, it was written like that a long time ago before we had a loader and unfortunately people started using it and expect it to be that way :( I hate it.

So would you consider adding an optional callback inside/after DisplayObject.transform? It would receive the updated matrix, allowing it to modify it further, e.g. applying rounding/flooring/whatever to the translation values.

I have thought so long and hard about this one. The challenge is making it happen in a way that is performant, and I haven't found a method with low enough overhead to make it acceptable, yet.

If you're worried about branching, you might implement it somewhat like this:

Well we definitely can't do that since that will change the hidden class of the object. But I understand what you are going for. I'll try to think about this problem more and see if we can't get a good solution.

from pixijs.

bartvanheukelom avatar bartvanheukelom commented on March 28, 2024

It would change the hidden class, but only for users who explicitly want to have that callback and are ready to take the performance hit. One then wouldn't apply it to thousands of bunnies (in my case the number of objects using it is in the 100 order of magnitude).
Also, if the new updateTransform were not to be a closure but a function defined once (with the callback stored as a property), it would add only one hidden class.

Anyway, I've looked around the source a bit and found things like displayObjectUpdateTransform and _originalUpdateTransform. I'm sure you're able to find a way to work this in :)

from pixijs.

englercj avatar englercj commented on March 28, 2024

@bartvanheukelom Yeah it is possible, those aren't adding/removing properties though just chaning them. And displayObjectUpdateTransform is just a shortcut to calling up the prototype chain to reduce the call stack in hot methods.

In other words, those examples add speed but yours reduces it :P let me think on this a bit.

from pixijs.

endel avatar endel commented on March 28, 2024

Also I noticed that PIXI.Text gets blurry when not using roundPixels. It's very difficult to not use floating numbers on the final position since the anchor/pivot usually are float values (0.5 for center), so this is not on the user control anymore - using integers on x/y will not ensure that the evaluated position is actually an integer.

Maybe just PIXI.Text should round it's position in this case, and not the entire core.

from pixijs.

GoodBoyDigital avatar GoodBoyDigital commented on March 28, 2024

Hello! With v3 you can snap to using renderer.roundPixels = true

from pixijs.

skaraman avatar skaraman commented on March 28, 2024

@GoodBoyDigital This issue still exists when rotation/angle is used unfortunately. Can the same algorithm that is used by CSS3 rotateZ, etc, be used here?

from pixijs.

GoodBoyDigital avatar GoodBoyDigital commented on March 28, 2024

@skaraman im not sure i follow i'm afraid? If you provide an example of the issue and what needs solving that would be ace. Thanks!

from pixijs.

skaraman avatar skaraman commented on March 28, 2024

@GoodBoyDigital actually it was to do with retina resolution - http://www.html5gamedevs.com/topic/20776-pixel-percision-on-rotation-for-renderer/

from pixijs.

sketch34 avatar sketch34 commented on March 28, 2024

I'm trying to avoid this pixel snapping functionality. I want to have a lot of slow moving sprites and the motion doesn't look nice when they snap to each pixel. I've tried renderer.roundPixels = false but it has no effect (Pixi.js 4.5.1 - Canvas / Chrome 58.0.3029.96 (64-bit) / OSX).

Is there any way to fix this? It's a deal breaker for me at the moment :(

I can easily repro it in the "tinting" demo with these line modifications:
//dude.scale.set(0.8 + Math.random() * 0.3); // Comment out this line
//dude.rotation = -dude.direction - Math.PI / 2; // Comment out this line
dude.speed = 0.1; // Make them move slowly

from pixijs.

sketch34 avatar sketch34 commented on March 28, 2024

Hi all, any ideas as to why renderer.roundPixels = false seems to have no effect in my case above? Thanks for any suggestions.

from pixijs.

ivanpopelyshev avatar ivanpopelyshev commented on March 28, 2024

RoundPixels is off by default. How big coordinates are you working with? May be its precision problem.

from pixijs.

lock avatar lock commented on March 28, 2024

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

from pixijs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.