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
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