[[UN?]fixed] Opengl accurate draw2DLine

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
tuXXX (guest)

[[UN?]fixed] Opengl accurate draw2DLine

Post by tuXXX (guest) »

Hi,

I'm currently using Irrlicht to create a small game, and I'm trying do design a small GUI by hand.
For this purpose I'm using draw2DLine, draw2DRectangle and font->draw(), but with the OpenGLDriver, the output isn't the same than the other ones.
I've seen that draw2DImage used by font->draw() is now fixed in 1.3, and draw2DRectangle is fine, but draw2DLine show some differences.

This patch fixes the issue for me *:

Code: Select all

--- irrlicht-1.3/source/Irrlicht/COpenGLDriver.cpp	2007-03-10 09:51:30.000000000 +0100
+++ irrlicht-1.3-mod/source/Irrlicht/COpenGLDriver.cpp	2007-04-24 19:25:10.000000000 +0200
@@ -1406,12 +1406,12 @@
 	const f32 yFact = 1.0f / (renderTargetSize.Height>>1);
 
 	core::position2d<f32> npos_start;
-	npos_start.X  = (f32)(start.X - xPlus) * xFact;
-	npos_start.Y  = (f32)(yPlus - start.Y) * yFact;
+	npos_start.X  = (f32)(start.X - xPlus + 0.5f) * xFact;
+	npos_start.Y  = (f32)(yPlus - start.Y - 0.5f) * yFact;
 
 	core::position2d<f32> npos_end;
-	npos_end.X  = (f32)(end.X - xPlus) * xFact;
-	npos_end.Y  = (f32)(yPlus - end.Y) * yFact;
+	npos_end.X  = (f32)(end.X - xPlus + 0.5f) * xFact;
+	npos_end.Y  = (f32)(yPlus - end.Y - 0.5f) * yFact;
 
 	setRenderStates2DMode(color.getAlpha() < 255, false, false);
 	disableTextures();
* with an nvidia card (6600GT and 7600Go) under GNU/Linux, but I think that this is not related (the draw2DImage fix was the same)
Don06
Posts: 4
Joined: Sun Jun 24, 2007 11:18 am

Post by Don06 »

Hi,

I've downloaded Irrlicht 1.3.1 today and thought you would have eliminated this bug. But when I looked it up in the source I found the old buggy Code.
Please correct this bug, because I am unable to recompile Irrlicht on my own, for some reasons.

For those who do not know this error, I made two Screenshots. You can see two Lines which are supposed to be white (SColor(255, 255, 255, 255). Using the OpenGl Driver they become fat and Gray.

Here are the Lines drawn with the Software Driver Burningsvideo:
Image

And here are the lines drawn with OpenGl:
Image


Is it really such a big deal to change those 4 lines in the source code?


-- Sorry for my bad English :roll:
aruametello
Posts: 2
Joined: Sun Jun 24, 2007 12:57 pm

Post by aruametello »

(warning, bad english!)

Thanks for the solution Don, i am having a problem with opengl and colored lines too. i have created a "spark emiter" that uses colored lines and as you has mentioned, the lines are full black regarless the selected color in opengl.

(i think this screens might help other people to show better the problem)

software (works correctly)
Image

opengl (the black lines problem)
Image


i couldnt aply your patch, could you please give me some help? i would greatly apreciate if u could share us a already patched file for irrlicht 1.3.1.
(something like rapidshare, for other people pick it up too)
Don06
Posts: 4
Joined: Sun Jun 24, 2007 11:18 am

Post by Don06 »

aruametello wrote:Thanks for the solution Don, [...]
Sorry, but I'm not tuXXX. So you have to thank tuXXX not me.

These are 3D Lines, right? I used 2D Lines for my example.
The OpenGL Driver seems to be more buggy than I thought.

You can correct the file on your own. It is in the Irrlicht/source directory.
The filename is in the tuXXX's Code. You have to replace the lines marked with a minus('-') with the lines marked with an plus('+').
In order to make things work you have to recompile the Irrlicht source on your own. Otherwise the changes would have no effect.
But this will affect only the draw2DLine method.

I cannot compile the libjpg package so I cannot compile Irrlicht correctly.
So I have to wait for a bugfix.


Don06
aruametello
Posts: 2
Joined: Sun Jun 24, 2007 12:57 pm

Post by aruametello »

Thanks for the quick response, but soon after i had posted the problem, i begin thinkering and i found on another thread that the EDT_BURNINGSVIDEO dont use lightning for 3D lines, the opengl uses, and i hadnt put any lights on the scene yet.

the thread i had found the solution:
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=21891

i just had set EMF_LIGHTING flag to false and it worked exactly like the software renderer.
(in opengl, with the fix)
Image


sorry for the "nobbish" mistake, but i hadnt thinked that actualy the software renderer was "wrong".
Don06
Posts: 4
Joined: Sun Jun 24, 2007 11:18 am

Post by Don06 »

Okay, no problem.
But the problem with the 2D-lines still remains.

I am working with GCC so there is no DirectX compiled in the distribution. If I want to use Hardware-Rendering, I have to use OpenGL. But, if the OpenGL driver cannot even draw 2D lines correctly, that is a problem.

When I realized the bug I searched for the problem and found this thread. But there were no responses to tuXXX's post.
It would be nice, when someone could tell me wether this will be fixed sooner or later.


Don06
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Don06 wrote:Is it really such a big deal to change those 4 lines in the source code?
Yes, because the fix does not make sense. I could put thousands of hacks into the core because someone can live better with it, but I guess that this would be worse formost of us.
So the thing is that no one could ever explain what goes wrong, show some code to get a sensible example, or tell why this pixel position tweaking would help. And until this happens the patch won't be applied.
Don06
Posts: 4
Joined: Sun Jun 24, 2007 11:18 am

Post by Don06 »

Thanks hybrid. Now I understand your point of view.
I've got an idea what's wrong about, but I've never programmed in OpenGL.

EDIT: I've heard that OpenGL starts counting the screen coordinates at 0.5f. so 0->0.5f and 1->1.5f.
If you put a pixel at position 1.0f it is exactly between those two pixels. So alpha blending is used for both pixels. If you want a white pixel you will get two gray pixels instead.
This would mean adding 0.5f to every coordinate/point would be the solution.

EDIT2: Okay found this one:
If exact pixelization is required, you might want to put a small translation in the ModelView matrix, as shown below:
glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatef (0.375, 0.375, 0.);
found here http://www.opengl.org/resources/faq/tec ... m#tran0030.

So maybe the solution is to add 0.375f to everything, but I've to highlight that I'm not an OpenGL-Programmer.


Don06[/url]
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Interesting point. Could you please try to add this line (the glTranslatef) in setRenderMode2D in COpenGLDriver.cpp? This would be a rather simple fix which would make the GUI only slightly slower.
tuXXX
Posts: 6
Joined: Fri May 11, 2007 3:22 pm

Post by tuXXX »

Sorry for the late reply, I've been busy on other projects and "real life" stuff.

The patch was a quick fix, involving just 4 lines, usually small patches are easier to review and are included faster.
Here is a more invasive patch, it's faster because the CPU doesn't have to process anything, and there is less code. But every function calling setRenderStates2DMode() is modified : draw2DImage() (3 functions), draw2DRectangle() (2 functions) and draw2DLine().
I don't know if the glScissor are handled correctly, it should be good but a test program would be handy.

Code: Select all

--- source/Irrlicht/COpenGLDriver.cpp.ori	2007-06-13 09:43:32.000000000 +0200
+++ source/Irrlicht/COpenGLDriver.cpp	2007-08-11 16:46:31.000000000 +0200
@@ -730,14 +730,6 @@ void COpenGLDriver::draw2DImage(video::I
 	tcoords.LowerRightCorner.Y = ((f32)sourcePos.Y + (f32)sourceSize.Height) / (f32)ss.Height;
 
 	core::rect<s32> poss(targetPos, sourceSize);
-	core::rect<f32> npos;
-	f32 xFact = 2.0f / ( renderTargetSize.Width );
-	f32 yFact = 2.0f / ( renderTargetSize.Height );
-
-	npos.UpperLeftCorner.X = ( poss.UpperLeftCorner.X * xFact ) - 1.0f;
-	npos.UpperLeftCorner.Y = 1.0f - ( poss.UpperLeftCorner.Y * yFact );
-	npos.LowerRightCorner.X = ( poss.LowerRightCorner.X * xFact ) - 1.0f;
-	npos.LowerRightCorner.Y = 1.0f - ( poss.LowerRightCorner.Y * yFact );
 
 	setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
 	disableTextures(1);
@@ -748,16 +740,16 @@ void COpenGLDriver::draw2DImage(video::I
 	glBegin(GL_QUADS);
 
 	glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
-	glVertex2f(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y);
+	glVertex2f(poss.UpperLeftCorner.X, poss.UpperLeftCorner.Y);
 
 	glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
-	glVertex2f(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y);
+	glVertex2f(poss.LowerRightCorner.X, poss.UpperLeftCorner.Y);
 
 	glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
-	glVertex2f(npos.LowerRightCorner.X, npos.LowerRightCorner.Y);
+	glVertex2f(poss.LowerRightCorner.X, poss.LowerRightCorner.Y);
 
 	glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
-	glVertex2f(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y);
+	glVertex2f(poss.UpperLeftCorner.X, poss.LowerRightCorner.Y);
 
 	glEnd();
 }
@@ -779,7 +771,6 @@ void COpenGLDriver::draw2DImage(video::I
 	if (!texture)
 		return;
 
-	const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
 	setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture);
 	disableTextures(1);
 	if (!setTexture(0, texture))
@@ -789,7 +780,7 @@ void COpenGLDriver::draw2DImage(video::I
 	if (clipRect)
 	{
 		glEnable(GL_SCISSOR_TEST);
-		glScissor(clipRect->UpperLeftCorner.X,renderTargetSize.Height-clipRect->LowerRightCorner.Y,
+		glScissor(clipRect->UpperLeftCorner.X,clipRect->LowerRightCorner.Y,
 			clipRect->getWidth(),clipRect->getHeight());
 	}
 
@@ -798,8 +789,6 @@ void COpenGLDriver::draw2DImage(video::I
 	core::position2d<s32> sourcePos;
 	core::dimension2d<s32> sourceSize;
 	core::rect<f32> tcoords;
-	f32 xFact = 2.0f / ( renderTargetSize.Width );
-	f32 yFact = 2.0f / ( renderTargetSize.Height );
 
 	for (u32 i=0; i<indices.size(); ++i)
 	{
@@ -815,27 +804,20 @@ void COpenGLDriver::draw2DImage(video::I
 		tcoords.LowerRightCorner.Y = (f32)sourceRects[currentIndex].LowerRightCorner.Y / (f32)ss.Height;
 
 		core::rect<s32> poss(targetPos, sourceSize);
-		core::rect<f32> npos;
-
-		npos.UpperLeftCorner.X = ( poss.UpperLeftCorner.X * xFact ) - 1.0f;
-		npos.UpperLeftCorner.Y = 1.0f - ( poss.UpperLeftCorner.Y * yFact );
-
-		npos.LowerRightCorner.X = ( poss.LowerRightCorner.X * xFact ) - 1.0f;
-		npos.LowerRightCorner.Y = 1.0f - ( poss.LowerRightCorner.Y * yFact ); 
 
 		glBegin(GL_QUADS);
 
 		glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
-		glVertex2f(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y);
+		glVertex2f(poss.UpperLeftCorner.X, poss.UpperLeftCorner.Y);
 
 		glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
-		glVertex2f(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y);
+		glVertex2f(poss.LowerRightCorner.X, poss.UpperLeftCorner.Y);
 
 		glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
-		glVertex2f(npos.LowerRightCorner.X, npos.LowerRightCorner.Y);
+		glVertex2f(poss.LowerRightCorner.X, poss.LowerRightCorner.Y);
 
 		glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
-		glVertex2f(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y);
+		glVertex2f(poss.UpperLeftCorner.X, poss.LowerRightCorner.Y);
 
 		glEnd();
 		targetPos.X += sourceRects[currentIndex].getWidth();
@@ -860,15 +842,6 @@ void COpenGLDriver::draw2DImage(video::I
 	tcoords.LowerRightCorner.X = (f32)sourceRect.LowerRightCorner.X / (f32)ss.Width;
 	tcoords.LowerRightCorner.Y = (f32)sourceRect.LowerRightCorner.Y / (f32)ss.Height;
 
-	const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
-	core::rect<f32> npos;
-	f32 xFact = 2.0f / ( renderTargetSize.Width );
-	f32 yFact = 2.0f / ( renderTargetSize.Height );
-	npos.UpperLeftCorner.X = ( destRect.UpperLeftCorner.X * xFact ) - 1.0f;
-	npos.UpperLeftCorner.Y = 1.0f - ( destRect.UpperLeftCorner.Y * yFact );
-	npos.LowerRightCorner.X = ( destRect.LowerRightCorner.X * xFact ) - 1.0f;
-	npos.LowerRightCorner.Y = 1.0f - ( destRect.LowerRightCorner.Y * yFact ); 
-
 	video::SColor temp[4] =
 	{
 		0xFFFFFFFF,
@@ -887,7 +860,7 @@ void COpenGLDriver::draw2DImage(video::I
 	if (clipRect)
 	{
 		glEnable(GL_SCISSOR_TEST);
-		glScissor(clipRect->UpperLeftCorner.X,renderTargetSize.Height-clipRect->LowerRightCorner.Y,
+		glScissor(clipRect->UpperLeftCorner.X,clipRect->LowerRightCorner.Y,
 			clipRect->getWidth(),clipRect->getHeight());
 	}
 
@@ -895,19 +868,19 @@ void COpenGLDriver::draw2DImage(video::I
 
 	glColor4ub(useColor[0].getRed(), useColor[0].getGreen(), useColor[0].getBlue(), useColor[0].getAlpha());
 	glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);
-	glVertex2f(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y);
+	glVertex2f(destRect.UpperLeftCorner.X, destRect.UpperLeftCorner.Y);
 
 	glColor4ub(useColor[3].getRed(), useColor[3].getGreen(), useColor[3].getBlue(), useColor[3].getAlpha());
 	glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);
-	glVertex2f(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y);
+	glVertex2f(destRect.LowerRightCorner.X, destRect.UpperLeftCorner.Y);
 
 	glColor4ub(useColor[2].getRed(), useColor[2].getGreen(), useColor[2].getBlue(), useColor[2].getAlpha());
 	glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);
-	glVertex2f(npos.LowerRightCorner.X, npos.LowerRightCorner.Y);
+	glVertex2f(destRect.LowerRightCorner.X, destRect.LowerRightCorner.Y);
 
 	glColor4ub(useColor[1].getRed(), useColor[1].getGreen(), useColor[1].getBlue(), useColor[1].getAlpha());
 	glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);
-	glVertex2f(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y);
+	glVertex2f(destRect.UpperLeftCorner.X, destRect.LowerRightCorner.Y);
 
 	glEnd();
 
@@ -932,18 +905,9 @@ void COpenGLDriver::draw2DRectangle(SCol
 	if (!pos.isValid())
 		return;
 
-	const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
-	s32 xPlus = renderTargetSize.Width>>1;
-	f32 xFact = 1.0f / (renderTargetSize.Width>>1);
-
-	s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1);
-	f32 yFact = 1.0f / (renderTargetSize.Height>>1);
-
 	glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
-	glRectf((pos.UpperLeftCorner.X-xPlus) * xFact,
-		(yPlus-pos.UpperLeftCorner.Y) * yFact,
-		(pos.LowerRightCorner.X-xPlus) * xFact,
-		(yPlus-pos.LowerRightCorner.Y) * yFact);
+	glRectf(pos.UpperLeftCorner.X,pos.UpperLeftCorner.Y,
+		pos.LowerRightCorner.X,pos.LowerRightCorner.Y);
 }
 
 
@@ -961,19 +925,6 @@ void COpenGLDriver::draw2DRectangle(cons
 	if (!pos.isValid())
 		return;
 
-	const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
-	s32 xPlus = renderTargetSize.Width>>1;
-	f32 xFact = 1.0f / (renderTargetSize.Width>>1);
-
-	s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1);
-	f32 yFact = 1.0f / (renderTargetSize.Height>>1);
-
-	core::rect<f32> npos;
-	npos.UpperLeftCorner.X = (f32)(pos.UpperLeftCorner.X-xPlus) * xFact;
-	npos.UpperLeftCorner.Y = (f32)(yPlus-pos.UpperLeftCorner.Y) * yFact;
-	npos.LowerRightCorner.X = (f32)(pos.LowerRightCorner.X-xPlus) * xFact;
-	npos.LowerRightCorner.Y = (f32)(yPlus-pos.LowerRightCorner.Y) * yFact;
-
 	setRenderStates2DMode(colorLeftUp.getAlpha() < 255 ||
 		colorRightUp.getAlpha() < 255 ||
 		colorLeftDown.getAlpha() < 255 ||
@@ -984,19 +935,19 @@ void COpenGLDriver::draw2DRectangle(cons
 	glBegin(GL_QUADS);
 	glColor4ub(colorLeftUp.getRed(), colorLeftUp.getGreen(),
 		colorLeftUp.getBlue(), colorLeftUp.getAlpha());
-	glVertex2f(npos.UpperLeftCorner.X, npos.UpperLeftCorner.Y);
+	glVertex2f(pos.UpperLeftCorner.X, pos.UpperLeftCorner.Y);
 
 	glColor4ub(colorRightUp.getRed(), colorRightUp.getGreen(),
 		colorRightUp.getBlue(), colorRightUp.getAlpha());
-	glVertex2f(npos.LowerRightCorner.X, npos.UpperLeftCorner.Y);
+	glVertex2f(pos.LowerRightCorner.X, pos.UpperLeftCorner.Y);
 
 	glColor4ub(colorRightDown.getRed(), colorRightDown.getGreen(),
 		colorRightDown.getBlue(), colorRightDown.getAlpha());
-	glVertex2f(npos.LowerRightCorner.X, npos.LowerRightCorner.Y);
+	glVertex2f(pos.LowerRightCorner.X, pos.LowerRightCorner.Y);
 
 	glColor4ub(colorLeftDown.getRed(), colorLeftDown.getGreen(),
 		colorLeftDown.getBlue(), colorLeftDown.getAlpha());
-	glVertex2f(npos.UpperLeftCorner.X, npos.LowerRightCorner.Y);
+	glVertex2f(pos.UpperLeftCorner.X, pos.LowerRightCorner.Y);
 
 	glEnd();
 }
@@ -1008,31 +959,13 @@ void COpenGLDriver::draw2DLine(const cor
 				const core::position2d<s32>& end,
 				SColor color)
 {
-	// thanks to Vash TheStampede who sent in his implementation
-
-	const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
-	const s32 xPlus = renderTargetSize.Width>>1;
-	const f32 xFact = 1.0f / (renderTargetSize.Width>>1);
-
-	const s32 yPlus =
-	renderTargetSize.Height-(renderTargetSize.Height>>1);
-	const f32 yFact = 1.0f / (renderTargetSize.Height>>1);
-
-	core::position2d<f32> npos_start;
-	npos_start.X  = (f32)(start.X - xPlus) * xFact;
-	npos_start.Y  = (f32)(yPlus - start.Y) * yFact;
-
-	core::position2d<f32> npos_end;
-	npos_end.X  = (f32)(end.X - xPlus) * xFact;
-	npos_end.Y  = (f32)(yPlus - end.Y) * yFact;
-
 	setRenderStates2DMode(color.getAlpha() < 255, false, false);
 	disableTextures();
 
 	glBegin(GL_LINES);
 	glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
-	glVertex2f(npos_start.X, npos_start.Y);
-	glVertex2f(npos_end.X,   npos_end.Y);
+	glVertex2f(start.X, start.Y);
+	glVertex2f(end.X,   end.Y);
 	glEnd();
 }
 
@@ -1485,6 +1418,10 @@ void COpenGLDriver::setRenderStates2DMod
 
 		glMatrixMode(GL_MODELVIEW);
 		glLoadIdentity();
+		// see http://www.opengl.org/resources/faq/technical/transformations.htm#tran0030
+		const core::dimension2d<s32>& renderTargetSize = getCurrentRenderTargetSize();
+		gluOrtho2D(0, renderTargetSize.Width, renderTargetSize.Height, 0);
+		glTranslatef (0.375, 0.375, 0.);
 
 		glMatrixMode(GL_TEXTURE);
 		glLoadIdentity();
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

Other than the scissor test stuff this works great, thanks :)
Committed as of revision 850.. Now OpenGL 2D is accurate with odd-sized windows :)
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
tuXXX
Posts: 6
Joined: Fri May 11, 2007 3:22 pm

Post by tuXXX »

Thanks!
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Patch in haste, debug at leisure. ;)

I think this patch is the cause of this bug which causes all OpenGL 2D content to scale itself with the window. This is inconsistent with the other drivers, and is a show stopper for 1.5.

Anyone with any opinions to share should air them now, before I attempt to revert this patch.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Post Reply