About Monkey 2 › Forums › Monkey 2 Development › Rotation and Draw Primitives at Virtual Resolutions using native res?
This topic contains 4 replies, has 4 voices, and was last updated by
cocon 1 year, 4 months ago.
-
AuthorPosts
-
November 30, 2017 at 8:23 am #12029
When rotation and drawing primatives (eg Oval) using a virtual resolution there are rotated and draw as the native resolution.
Monkey12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849Namespace myapp#Import "<std>"#Import "<mojo>"Using std..Using mojo..Class MyWindow Extends WindowField x:Int, y:Int, w:Int, h:Int, r:FloatField timer:TimerField vSize := New Vec2i(320, 200)Method New()Super.New("My Window", 1280, 800, WindowFlags.Resizable)Layout = "letterbox-int"w = 100h = 60x = (vSize.x / 2) - (w / 2)y = (vSize.y / 2) - (h / 2)timer = New Timer(60, OnUpdate)EndMethod OnUpdate()r += 0.001EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()canvas.TextureFilteringEnabled = FalseLocal matrix := canvas.Matrixcanvas.Matrix = matrix.Translate(x, y).Rotate(r)canvas.DrawOval(0, 0, w, h)canvas.Matrix = matrixEndMethod OnMeasure:Vec2i() OverrideReturn vSizeEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndI’ve got around this by rendering to texture, but is there a better way or fix?
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354Namespace myapp#Import "<std>"#Import "<mojo>"Using std..Using mojo..Class MyWindow Extends WindowField x:Int, y:Int, w:Int, h:Int, r:FloatField timer:TimerField vSize := New Vec2i(320, 200)Field gameImage:ImageField gameCanvas:CanvasMethod New()Super.New("My Window", 1280, 800, WindowFlags.Resizable)Layout = "letterbox-int"w = 100h = 60x = (vSize.x / 2) - (w / 2)y = (vSize.y / 2) - (h / 2)gameImage = New Image(vSize.x, vSize.y, PixelFormat.RGBA8, TextureFlags.Dynamic)gameCanvas = New Canvas(gameImage)timer = New Timer(60, OnUpdate)EndMethod OnUpdate()r += 0.001EndMethod OnRender( canvas:Canvas ) OverrideApp.RequestRender()gameCanvas.Clear(Color.Black)gameCanvas.TextureFilteringEnabled = FalseLocal matrix := gameCanvas.MatrixgameCanvas.Matrix = matrix.Translate(x, y).Rotate(r)gameCanvas.DrawOval(0, 0, w, h)gameCanvas.Matrix = matrixgameCanvas.Flush()canvas.DrawImage(gameImage, 0, 0)EndMethod OnMeasure:Vec2i() OverrideReturn vSizeEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndNovember 30, 2017 at 7:28 pm #12042Can’t think of anything off hand. Possibly a shader could be used to ‘snap’ vertices, but then you’d end up with a lot of overdraw and it would be likely to be considerably slower.
I think the ‘draw stuff offscreen’ approach is pretty much the way HW expects things to be done these days. I have also recently found a ‘blit framebuffer’ GL extension that should make this even faster in some cases, not that I’ve ever found it to be too slow or anything so far.
December 1, 2017 at 4:03 am #12049The current behavior seems correct to me!
Virtual resolution is about relative sizes (and aspect ratio), not about the resolution itself. Doing the two step, “render to texture then draw texture” seems to be the correct path to draw “actual” low res images at a high resolution monitor, I think.
If you really don’t want to deal with it, you can extend the Window class into a window that does the texture rendering “behind the scenes”. You can even switch between low res and high res on the fly while maintaining the framing and size of everything, which is neat!
Cheers!
December 1, 2017 at 7:54 pm #12062Actually, my idea is bollocks anyway, it’d just ‘pointilize’ everything.
December 2, 2017 at 2:28 pm #12071This render to texture effect is nice for various purposes, such as pixel art etc.
However for the real deal there should be another much better way. Many others have tried to tackle the problem of virtual resolutions, I remember Diddy Framework (previous monkey-x) had quite a cool way to handle virtual resolutions, that handles scaling, nicely.
My take on the subject so far is to convert values form a range to another.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131Namespace myapp#Import "<std>"#Import "<mojo>"Using std..Using mojo..Class VirtualResolution AbstractGlobal Width:Int, Height:IntFunction Set(width:Int, height:Int)Width = widthHeight = heightEnd#rem monkeydoc Convert an X screen value to virtual.#end remFunction GetVirtualX:Float(screenX:Int)Return Remap(screenX, 0, App.ActiveWindow.Width, 0, Width)End#rem monkeydoc Convert a Y screen value to virtual.#end remFunction GetVirtualY:Float(screenY:Int)Return Remap(screenY, 0, App.ActiveWindow.Height, 0, Height)End#rem monkeydoc Convert an X virtual value to screen.#end remFunction GetScreenX:Float(virtualX:Int)Return Remap(virtualX, 0, Width, 0, App.ActiveWindow.Width)End#rem monkeydoc Convert an X virtual value to screen.#end remFunction GetScreenY:Float(virtualY:Int)Return Remap(virtualY, 0, Height, 0, App.ActiveWindow.Height)End#rem monkeydoc Remap a value from a source range to a target range.#end remFunction Remap:Float(value:Float, firstStart:Float, firstStop:Float, secondStart:Float, secondStop:Float)Return secondStart + (secondStop - secondStart) * ((value - firstStart) / (firstStop - firstStart))EndEndClass Entity AbstractGlobal Position := New Vec2fGlobal TargetPosition := New Vec2fEndClass MyWindow Extends WindowMethod New()Super.New("My Window", 800, 800)VirtualResolution.Set(400, 400)EndMethod OnRender( canvas:Canvas ) Override' game update takes place in the virtual resolutionIf (Mouse.ButtonHit(MouseButton.Left))' the user enters some coordinates that will have to be converted into virtualEntity.TargetPosition.X = VirtualResolution.GetVirtualX(Mouse.X)Entity.TargetPosition.Y = VirtualResolution.GetVirtualY(Mouse.Y)End' the rest is updated normallyEntity.Position.X = Lerp(Entity.Position.X, Entity.TargetPosition.X, 0.05)Entity.Position.Y = Lerp(Entity.Position.Y, Entity.TargetPosition.Y, 0.05)' -------------------------------------------------' on game rendering virtual values must be converted to screen valuesApp.RequestRender()' draw the targetIf True ' <-- sugar to keep method scope cleaner...Local x := VirtualResolution.GetScreenX(Entity.TargetPosition.X)Local y := VirtualResolution.GetScreenY(Entity.TargetPosition.Y)canvas.Color = Color.Redcanvas.DrawLine(0, y, Width, y)canvas.DrawLine(x, 0, x, Height)End' draw the playerIf TrueLocal x := VirtualResolution.GetScreenX(Entity.Position.X)Local y := VirtualResolution.GetScreenY(Entity.Position.Y)canvas.Color = Color.Whitecanvas.DrawRect(x, y, 10, 10)End' -------------------------------------------------' for fun see how the virtual world behavesLocal seeVirtualSpace := TrueIf seeVirtualSpacecanvas.Color = Color.Whitecanvas.DrawRect(Entity.Position.X, Entity.Position.Y, 10, 10)canvas.Color = Color.Bluecanvas.DrawRect(Entity.TargetPosition.X, Entity.TargetPosition.Y, 5, 5)End' -------------------------------------------------EndEndFunction Main()New AppInstanceNew MyWindowApp.Run()End#rem monkeydoc Performs a linear interpolation between two values based on blending value.@param a The original value.@param b The target value.@param blend The blending percentage factor (normalized between 0.0 and 1.0).#endFunction Lerp:Float(a:Float, b:Float, blend:Float)Return blend * (b - a) + aEnd -
AuthorPosts
You must be logged in to reply to this topic.