Jump to content


pixel-perfect drawing


10 replies to this topic

#1 AticAtac

    Member

  • Members
  • PipPip
  • 78 posts

Posted 09 March 2006 - 09:12 PM

It seems to me that its almost impossible to do pixel-perfect 2D drawings in 3D engines. Obviously the UV-mapping causes errors.
While its ok for scaling, there are situation where one just want to draw a bitmap with the exact size on the screen. Is there a way to do a "pixel-pefect" drawing ?
In my case i have all my gui-imagesin 1 or 2 "big" bitmaps and i want to draw them exactly as they are in the bitmap.

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 10 March 2006 - 12:17 AM

OpenGL offers a rasterizing interface, look up the glDrawPixels function. Presumably D3D has something similiar. And it's not that hard to achieve a one-one texel-to-pixel mapping - you just have to set identity matrices for the projection, view, etc, turn off bilinear filtering, and be a bit careful with how you set your texture coordinates.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 Neken

    New Member

  • Members
  • Pip
  • 7 posts

Posted 10 March 2006 - 02:48 AM

DrawPrimitiveUp in Directx ... with transformed and lit vertices ... there is absoluetely no problem in drawing pixel-perfect 2d Textures to the screen ...

there is certainly a somewhat similar function in opengl ...

#4 Mattias Gustavsson

    Senior Member

  • Members
  • PipPipPipPip
  • 413 posts

Posted 10 March 2006 - 10:59 AM

subtract 0.5 pixel from each uv-coordinate (so for a 256x256 texture you subtract 0.5/256)

It is to do with sampling being done on the centre of the pixel (http://msdn.microsof...s_to_Pixels.asp)

If you do this, you don't have to turn off bilinear filtering.

#5 AticAtac

    Member

  • Members
  • PipPip
  • 78 posts

Posted 10 March 2006 - 06:54 PM

Substracting 0.5 is a common mistake many people do !
It fixes some errors and produce new ones !

Update: I just read the article and i am not sure if i understood correctly:
lets say my bitmap has size of w x h
the sub-image in the bitmap i want to draw from is at (x1,y1)->(x2,y2),
so right now i do this:

u1 = x1 / w
v1 = y1 / h
u2 = x2 / w
v2 = y2 / h

according to the article i should do this:

u1 = (x1-0.5f) / w
v1 = (y1-0.5f) / h
u2 = (x2-0.5f) / w
v2 = (y2-0.5f) / h

is that correct ?

#6 Mattias Gustavsson

    Senior Member

  • Members
  • PipPipPipPip
  • 413 posts

Posted 10 March 2006 - 08:59 PM

yes, that's correct. What sort of problems have you noticed with this? I'm using it myself, and I get a consistent 1 to 1 mapping of texels to pixels.

#7 AticAtac

    Member

  • Members
  • PipPip
  • 78 posts

Posted 10 March 2006 - 09:05 PM

While the drawn bitmap has the right size (of course) the drawn texture on it is missing the right and bottom row.

Could this be a driver issue ? (I got ATI 9600 Pro)

#8 Mattias Gustavsson

    Senior Member

  • Members
  • PipPipPipPip
  • 413 posts

Posted 10 March 2006 - 09:14 PM

That's most likely the correct behaviour, as the rasterization convention for directx is to not draw the last pixel. just increase your bitmap size by one on each axis

#9 AticAtac

    Member

  • Members
  • PipPip
  • 78 posts

Posted 10 March 2006 - 09:45 PM

It still doesn't work :(
I try to sum it up here again:

I want to draw a bitmap (x1,y1->x2,y2) stored in a bigger bitmap (w x h) to screen at (sx1,sy1 -> sx2,sy2) w/o scaling which means:
sx2-sx1 = x2-x1 and sy2-sy1=y2-y1

So i first calculate the U/V by
u1 = (x1-0.5f) / w
v1 = (y1-0.5f) / h
u2 = (x2-0.5f) / w
v2 = (y2-0.5f) / h

then i draw my bitmap to: (sx1,sy1 -> sx2+1, sy2+1)

is that correct ?

#10 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 10 March 2006 - 10:13 PM

If you're adding one to sx2 and sy2, you should also add one to x2 and y2, i.e. u2 = (x2 + 0.5f) / w and (y2 + 0.5f) / h.
reedbeta.com - developer blog, OpenGL demos, and other projects

#11 AticAtac

    Member

  • Members
  • PipPip
  • 78 posts

Posted 10 March 2006 - 10:23 PM

Reedbeta:
"u2 = (x2 + 0.5f) / w and (y2 + 0.5f) / h" solved the problem !

Thanks to all the helpers here !





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users