PDA

View Full Version : Comparing different filtering algorithms



Petr Schreiber
31-10-2017, 19:36
Hello fellow vertex wrestlers,


Primo's example (http://www.thinbasic.com/community/showthread.php?12806-Deformed-pictures&p=93930#post93930) inspired me to revisit the basics and compare the different filtering algorithms.


After all those years, we take mip map filtering as granted to be our friend in most cases... but is it really the best one?


See for yourself in this interactive demo:


uses "TBGL"


function tbMain()

dWord hWnd = tbgl_createWindowEx("Comparison of texture sampling: [SPACE] to stop time, [PageUp/PageDown] to alter deformation, [ESC] to quit", 768, 768, 32, %tbgl_WS_WINDOWED or %tbgl_WS_CLOSEBOX)
tbgl_showWindow


' -- Load textures
tbgl_loadTexture app_path + "\SampleScripts\TBGL\Basic\Textures\tbgl_font.bmp", 1, %TBGL_TEX_nearest
tbgl_loadTexture app_path + "\SampleScripts\TBGL\Basic\Textures\tbgl_font.bmp", 2, %TBGL_TEX_linear
tbgl_loadTexture app_path + "\SampleScripts\TBGL\Basic\Textures\tbgl_font.bmp", 3, %TBGL_TEX_mipmap
tbgl_loadTexture app_path + "\SampleScripts\TBGL\Basic\Textures\tbgl_font.bmp", 4, %TBGL_TEX_aniso

' -- Instantiate objects and link them to textures
dim nearest as new DancingSquare(1)
dim linear as new DancingSquare(2)
dim mipmap as new DancingSquare(3)
dim aniso as new DancingSquare(4)


' -- Create font to write with
dWord hFont = tbgl_fontHandle("Courier New", 9)
tbgl_buildFont(hFont)


double frameRate
double animTime
single cornerRadius = 0.5
long stopTime

' -- Main loop
tbgl_resetKeyState()
while tbgl_isWindow(hWnd)

frameRate = tbgl_GetFrameRate

if not stopTime then
animTime += 1/frameRate
end if


' -- Update radiuses
nearest.setCornerRadius(cornerRadius)
linear.setCornerRadius(cornerRadius)
mipmap.setCornerRadius(cornerRadius)
aniso.setCornerRadius(cornerRadius)

' -- Update animation times
nearest.setAnimTime(animTime)
linear.setAnimTime(animTime)
mipmap.setAnimTime(animTime)
aniso.setAnimTime(animTime)

tbgl_clearFrame
tbgl_camera(0, 0, 10, 0, 0, 0)

' -- Print descriptions

tbgl_printFont "Nearest", -2.25, 3.5, 0
tbgl_printFont "Linear", 1.75, 3.5, 0
tbgl_printFont "MipMap", -2.15,-0.5, 0
tbgl_printFont "Aniso", 1.85,-0.5, 0

' -- Render objects
tbgl_pushMatrix
tbgl_translate -2, 2
nearest.render()
tbgl_popMatrix


tbgl_pushMatrix
tbgl_translate 2, 2
linear.render()
tbgl_popMatrix


tbgl_pushMatrix
tbgl_translate -2, -2
mipmap.render()
tbgl_popMatrix


tbgl_pushMatrix
tbgl_translate 2, -2
aniso.render()
tbgl_popMatrix


tbgl_drawFrame


' -- Keyboard input

If tbgl_getWindowKeyOnce(hWnd, %VK_space) then stopTime = not stopTime

If tbgl_getWindowKeyState(hWnd, %VK_pgUp) then cornerRadius = minMax(cornerRadius+0.1/frameRate, 0, 0.75)
If tbgl_getWindowKeyState(hWnd, %VK_pgDn) then cornerRadius = minMax(cornerRadius-0.1/frameRate, 0, 0.75)

If tbgl_getWindowKeyState(hWnd, %VK_escape) then exit while


wend


tbgl_destroyWindow

end function


' -- Object representing "Dancing Square"
' -- Classic square with animated vertices copying round shapes
type DancingSquare
private
texture as long

animTime as double
cornerRadius as single


public
function _Create(texture as long)
me.texture = texture
end function

function setAnimTime(animTime as single)
me.animTime = animTime
end function

function setCornerRadius(cornerRadius as single)
me.cornerRadius = cornerRadius
end function

function render()
tbgl_pushState %TBGL_TEXTURING
tbgl_bindTexture me.texture

' -- COS & SIN, your friends for circular movement...
tbgl_beginPoly %GL_Quads
tbgl_texCoord2D 0, 0
tbgl_vertex -1 + cos(me.animTime) * me.cornerRadius,
-1 + sin(me.animTime) * me.cornerRadius

tbgl_texCoord2D 1,0
tbgl_vertex 1 + cos(me.animTime + m_pi) * me.cornerRadius,
-1 + sin(me.animTime + m_pi) * me.cornerRadius

tbgl_texCoord2D 1, 1
tbgl_vertex 1 + cos(me.animTime + m_pi * 2) * me.cornerRadius,
1 + sin(me.animTime + m_pi * 2) * me.cornerRadius

tbgl_texCoord2D 0, 1
tbgl_vertex -1 + cos(me.animTime + m_pi * 3) * me.cornerRadius,
1 + sin(me.animTime + m_pi * 3) * me.cornerRadius
tbgl_endPoly

tbgl_popState

tbgl_pushPolygonlook %GL_LINE
tbgl_ngon(-1, -1, me.cornerRadius, 64)
tbgl_ngon( 1, -1, me.cornerRadius, 64)
tbgl_ngon( 1, 1, me.cornerRadius, 64)
tbgl_ngon(-1, 1, me.cornerRadius, 64)
tbgl_popPolygonLook

end function
end type






Petr

Kuron
31-10-2017, 19:54
Very nice and helpful, thank you Petr.

primo
31-10-2017, 20:58
i can see the Polygon with aniso is the best, stable, sharp and no flicker, i haven't tried it before, the Polygon with MipMap have a some fuzzy appearance. thanks Petr for the example, as always have many new ideas

ErosOlmi
31-10-2017, 21:44
What about an image?

9758

primo
31-10-2017, 22:04
Hi Eros
the nearest and linear have some flicker when the polygons rotating while aniso does not flicker (but a very little), MipMap have some fuzziness. but it is may be depends on the VGA card. my card is Nvidia Geforce GT 640

Petr Schreiber
31-10-2017, 22:56
Hi Primo,

what you describe occurs on any hardware supporting these filtering algorithms.

Nearest seems to be horrible, but it is invaluable for pixel-art like rendering.

Linear does its job for 2D as well, especially when you render at different-than-original sizes and do not want the image pixelated.

Mip mapping (which is basically linear with different versions for different distances from camera) reduces the flicker at cost of diminishing the crispness.

Aniso is the thing for sharp 3D imaginery, but it also has the biggest memory and computional requirements.


Petr