Perhaps this might be useful to someone:
I often have a large texture or RenderTarget I want to scale down, but just setting the scale of a Sprite doesn't do any anti-aliasing/smoothing. If you're downsizing by 50%, you just get a pixel from where every other row meets every other column, so you're only including one of every 4 pixels, and the result looks blocky. If the image is of something with fine detail, like a bushy fishing fly made of wrapped feathers, the pixelated result it can look pretty rough.
I wrote a function to blend all the pixels from the source texture into the reduced one, pixel by pixel. It works fine, but of course that's really slow. Then it dawned on me that there's a much faster way to do it, letting the GPU do the work. Just draw the scaled down texture several times with decreasing alpha so all the layers get the same total weight, using a TextureRegion that's offset for each layer. That offset means if you're getting only every Nth pixel from the source, one layer gets every Nth pixel starting at 1, the next gets every Nth pixel starting at 2, etc. So the final pixel in the reduced texture is a blend of the corresponding pixels from the larger original texture.
Anyway, if you want to scale down a texture with smoothing, the following function will take a texture or RenderTarget and downsize it that way:
function smoothedDownsize(rt, width)
-- Ignores height, preserves aspect ratio
local rtw, rth = rt:getWidth(), rt:getHeight()
local scale = width / rtw
local dest_rt = RenderTarget.new(width, rth * scale)
local range = 1 / scale -- If going down 50%, range is 2, meaning 2 rows of source make 1 row of dest
local b = Bitmap.new(rt)
b:setScale(scale)
dest_rt:draw(b)
local layers_drawn = 1
for step = 1, range do
for ox = -1, 1, 2 do
for oy = -1, 1, 2 do
local tr = TextureRegion.new(rt, ox * step, oy * step, rtw, rth)
local b = Bitmap.new(tr)
b:setScale(scale)
b:setAlpha(1 / (layers_drawn + 1))
dest_rt:draw(b)
layers_drawn += 1
end
end
end
return dest_rt
end |
Comments
Typical use:
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Fragmenter - animated loop machine and IKONOMIKON - the memory game
i use imgui:scaledImageButton using a texture that i get from a textureregion without filtering. i've attached the original texture (transparent boundary) and a screenshot of the button that is rendered from it.
Fragmenter - animated loop machine and IKONOMIKON - the memory game
Likes: keszegh, pie