5 ms·
Shaders are are a great place to use "pull". Take an image that is 1024x1024 that you want to display as a 256x256 image. The simple way to do this is to visi
by chrisbennet 6y ago
Shaders are are a great place to use "pull".
Take an image that is 1024x1024 that you want to display as a 256x256 image.
The simple way to do this is to visit every pixel in the the source and write it to the display buffer [x'=x/4, y'=y/4].
3 out 4 of those writes will just get written over in the display buffer.
A more efficient way is step though display buffer space and calculate where that pixel came from (reverse transform) [x'=4x, y'=4y]
- heavenlyblue 6y agoNo, they’re equivalent. Nobody stops you from from stepping through pixels in multiples of 4 and then writing that to the display buffer.
- ajuc 6y agoYou can write code both ways but it's much easier to ensure every destination pixel is handled exactly once when you interate over the destination pixels, than if you do it iterating over the source pixels. It becomes especially visible when you add perspective distortion and other complications. Which is why every graphic api out there does it pull-style.
- heavenlyblue 6y agoDrawing triangles on a screen is a push-style operation, isn’t it?
- ajuc 6y agoYes, from the POV of lists of polygons. But from the point view of textures it is pull (you go through destination pixels and fill them with source pixels fetched through transformation).
- heavenlyblue 6y agoIn the same way you could apply the reverse transform to the polygon and get the coordinates of display pixels in texture coordinates and then do a push from there. They are equivalent, as I am trying to say. The only difference is semantics or whatever makes it easier to think about.
- ajuc 6y agoYou would have to skip variable number of pixels in source texture according to the transformation, then calculate the reverse transformation to know where to push. Notice how you not only change x * 4 into x/4, you also change x++ into x+=4 for (int x=0; x<width; x++) for (int y=0; y<height; y++) destination[x][y] = source[x*4][y*4]; vs for (int x=0; x<width; x+=4) for (int y=0; y<height; y+=4) destination[x/4][y/4] = source[x][y]; If it's as simple as scaling: x+=4 isn't much harder than x++. But for complex transformations calculation of how many pixels to skip in any particular row will be slow and complicated. Meanwhile when doing pull you don't need to do it. This is the reason every graphical API i know of does these tranformations iterating over destination pixels.
- hoseja 6y agoAlso, what if you want to use a better scaling method.
- chrisbennet 6y agoYes, you are of course correct for this very simple example. The last time I did something like this, I needed to take a rectangular buffer and transform it to a circle. Each buffer line became a "spoke" in the circle. Much easier/simpler [I always strive for simple] to figure out the reverse transform and step through every "display" pixel.
- Retric 6y agoBoth push and pull are used in graphics. Creating the classic z-buffer is used when pushing a lot of polygons is the fastest option even if that seems wasteful. Face culling on the other hand is classic pull technique where you first figure out if you want something and only then compute the details. PS: 256x256 is 1/16th 1024x1024 so your wasting 15/16 pixels.
- ajuc 6y agoIf you want to be general polygon rasterization is push and raytracing is pull :)
- chrisbennet 6y agoOh you're right!