Why is a pixel missing from my rect outline?

Monkey Targets Forums/Desktop/Why is a pixel missing from my rect outline?

Grey Alien(Posted 2012) [#1]
Check it out, run this and notice the top left pixel is missing in GLFW, but not when in HTML5!

Import mojo

Function Main:Int()

	New MyApp

	Return 1
End

Class MyApp Extends App

	Method OnCreate:Int()
		'Set frame rate
		SetUpdateRate 60
	
		Return 1
	End Method
		
	Method OnUpdate:Int()
		
		Return 1
	End Method

	Method OnRender:Int()
	   Cls(0,0,0)
	   Local x1=100
	   Local x2=200
	   Local y1=100
	   Local y2=200
	   DrawLine(x1,y1,x2,y1)
	   DrawLine(x2,y1,x2,y2)
	   DrawLine(x2,y2,x1,y2)
	   DrawLine(x1,y2,x1,y1)
		
	   Return 1
	End Method

End Class



therevills(Posted 2012) [#2]
Works fine here Jake, might be a driver issue:



Edit: Added zoomed in section, where you can see the missing bottom-left (Ta muddy!)


muddy_shoes(Posted 2012) [#3]
Your bottom left pixel is missing.


therevills(Posted 2012) [#4]
Oh yeah... I was just checking the top-left :/


muddy_shoes(Posted 2012) [#5]
I imagine it's the same issue as in Grey Alien's other thread. The OpenGL line renderer doesn't work with pixel boundary positions. Change the values to be floats with half pixel values:

[monkeycode]
Local x1:Float=100.5
Local x2:Float=200.5
Local y1:Float=100.5
Local y2:Float=200.5
[/monkeycode]

...and see if that works.


therevills(Posted 2012) [#6]
Yep that did the trick.


Grey Alien(Posted 2012) [#7]
Mine was on Mac btw, looks like therevills was on PC.

Anyway, adding 0.5 fixed it thanks. However, does anyone think that maybe that should be handled inside monkey instead as most users will be expecting it to be drawing on pixel 0 not on the -1/0 boundary...I know I did!

I'm going to have to add 0.5 for the GLFW target to all drawing code, or should it also be applied to HTML5 and Flash etc I wonder?

e.g.

Function ccDrawRectOutline2:Void(x1:Float, y1:Float, x2:Float, y2:Float)
	#If TARGET="glfw" Then
		x1+=0.5
		x2+=0.5
		y1+=0.5
		y2+=0.5
	#End
	DrawLine(x1,y1,x2,y1)
	DrawLine(x2,y1,x2,y2)
	DrawLine(x2,y2,x1,y2)
	DrawLine(x1,y2,x1,y1)
End Function



muddy_shoes(Posted 2012) [#8]
Seems like a target inconsistency bug that needs ironing out in mojo.


therevills(Posted 2012) [#9]
Yep, mines on Windows.

I think I would raise a bug in the Bug forum.

When I tested Flash it worked fine the first time (I doubled checked after Muddy pointed out the bottom-left).


Grey Alien(Posted 2012) [#10]
OK will probably raise as a bug then. Remind me if I forget. It's late here!

Hmm, I'm thinking it also needs to be applied to HTML5 as well because the right hand line at x=640 is visible on HTML5 unless I add 0.5. And the box has better corners with 0.5 added so I think HTML5 is drawing at pixel borders too, not in the centre of pixels.


Grey Alien(Posted 2012) [#11]
I haven't test Flash yet as I'm still on Mac, but will test in Flash when on my PC tomorrow.


Uncle(Posted 2012) [#12]
This is a known opengl issue rather than a monkey issue. I came across the same thing a few days back. Its also graphics driver dependent as well, as I have the same program running on two machines and the missing pixel is in different places. The solution is as said above to move the object 0.5 before drawing. I have a simple translate at the top of the render routine to move the whole rendering by 0.5.


muddy_shoes(Posted 2012) [#13]
I don't think it's that simple. Firstly this only applies to line rendering, as far as I'm aware, so universally shifting by 0.5 isn't what people should be doing. Secondly, although I've just said "add 0.5" here it's more like "make sure that the line exits the centre of the pixel".

In order to resolve the problem more generally you'd have to take into account the direction of the line and create boundary values that ensure the line exits centre points at both ends. Alternatively mojo could avoid using GL_LINES and use different primitives but that's possibly just as involved.

I doubt there are many release version uses for the basic line rendering that mojo provides but I still think this is something that needs addressing. Even if the decision is to not make the input consistent there still needs to be clarification on what values are expected.


Grey Alien(Posted 2012) [#14]
Yeah I was using it to display hitbox rects in debug mode and couldn't understand why they were wrong. I'm wondering if DrawRect has the same issue...


muddy_shoes(Posted 2012) [#15]
Below is some code that tries to ensure that the line exits the pixel centres of both the start and end coordinates. Seems to work okay for me, but I don't know how variable the GL implementations are in this stuff.

[monkeycode]
Import mojo

Function Main:Int()

New MyApp

Return 1
End

Function DrawLineGL:Void( x1:Float, y1:Float, x2:Float, y2:Float)
'Set co-ords to centres
x1 += 0.5
y1 += 0.5
x2 += 0.5
y2 += 0.5

'calc line equation
Local ydiff:Float = (y2-y1)
Local xdiff:Float = (x2-x1)

'calc exit boundary values
If ydiff = 0.0
'line is flat
x2 += Sgn(xdiff) * 0.5
ElseIf xdiff = 0.0
'line is vertical
y2 += Sgn(ydiff) * 0.5
Else
'line is diagonal
Local m:Float = ydiff/xdiff
Local c:Float = y1 - m*x1

If ydiff > xdiff
y2 += Sgn(ydiff) * 0.5
x2 = (y2 - c)/m
Else
x2 += Sgn(xdiff) * 0.5
y2 = m*x2 + c
End
End

DrawLine(x1,y1,x2,y2)
End

Class MyApp Extends App

Method OnCreate:Int()
'Set frame rate
SetUpdateRate 1

Return 1
End Method

Method OnUpdate:Int()

Return 1
End Method


Method OnRender:Int()
Cls(0,0,0)
Local x1:Float = 100
Local x2:Float = 200
Local y1:Float = 100
Local y2:Float = 200

'should render a pink box surrounded with white 1px border
SetColor(255, 255, 255)
DrawLineGL(x1, y1, x2, y1)
DrawLineGL(x2, y1, x2, y2)
DrawLineGL(x2, y2, x1, y2)
DrawLineGL(x1, y2, x1, y1)
SetColor(255, 64, 64)
DrawRect(x1+1, y1+1, x2-x1-1, y2-y1-1)

x1 = 300
x2 = 400
y1 = 100
y2 = 200

'should render a pink box crossed with white lines that
'extend 1px out on the corners
DrawRect(x1+1, y1+1, x2-x1-1, y2-y1-1)
SetColor(255, 255, 255)
DrawLineGL(x1, y1, x2, y2)
DrawLineGL(x1, y2, x2, y1)

Return 1
End Method

End Class
[/monkeycode]


Grey Alien(Posted 2012) [#16]
Wow cool. Can I use this in my code please?


muddy_shoes(Posted 2012) [#17]
Sure. I wouldn't post something if it wasn't free for anyone to use.

Edit: Turns out I was being optimistic just extending the lines out past the destination point. It was still missing pixels from the source going in certain directions. The code below extends the line both ways and seems to resolve this.




Grey Alien(Posted 2013) [#18]
Have you tried your new code in V066b? I get a white pixel outside the top right of the box on GLFW. It's fine in Flash and HTML5.