[4.0.0] Orthographic Projection Sampling Issues

Problems building or running the engine, queries about how to use features etc.
User avatar
haloman30
Halfling
Posts: 40
Joined: Mon Aug 29, 2022 2:53 pm
x 3

[4.0.0] Orthographic Projection Sampling Issues

Post by haloman30 »

Ogre Version: 4.0.0 (commit 8b7b3d17310c0243c264706cfb9f66424fbaf877)
Operating System: Windows 7 x64
Render System: Direct3D11

Hello!

So, this seems to be a pretty fundamental issue I'm running into - part of what I'm aiming for my project to do is support 2D rendering, with particular consideration made for pixel art assets. Thus far, I've been using an orthographic camera for 2D UI, which has worked fine - but it seems that using a similar setup for more traditional 2D assets isn't working as well.

After digging around a bit, it seems to be some sort of sampling issue - the screenshots below use 4 quads, each sampling a 16x16 section of a 32x32 texture, as a very primitive tilemap implementation (hence only 4 tiles). The issue is that the texture doesn't get rendered correctly onscreen, with a sort of distortion - which seems to be due to how the texture is being sampled. Despite attempting to correct for half-pixel alignments and such (going off of info I found online), I've been unable to get this to work properly and also continue doing so with differing zoom levels (which is done by dividing the size of the viewport based on zoom level, only using whole integers so no 1.5x zoom or anything).

Further, I've also been poking around with bgfx, as there's been a few particularly troublesome issues I've run into and I've potentially considered building my own graphics engine on top of it to work around them - but I'm trying to avoid this if at all possible, seems more likely that I'd be better off using something developed by more knowledgeable folk. However, when getting a basic setup that replicates the setup I had in OGRE (more minimally of course), the issue didn't occur. No zooming, or zooming in at different steps, no issue.

I did also try this under OpenGL (in OGRE) and got the same result, as some info I was finding online suggested this could be a D3D11 quirk.

Any pointers or things to try on my end? I've tried various approaches, including adjusting things by a half-pixel (by translating the projection matrix itself, just moving the camera position, adjusting vertex positions in the tilemap shader), and I've tried changing how the texture gets sampled (using normal UVs or passing direct pixel coords in the UVs and using equivalents to texelFetch) - and given that a basic stripped-down renderer just works without any special consideration, I'm unsure what else to try. I did also try to use bgfx's function for creating the orthographic projection matrix, but not knowing much about the deeper stuff at that point (and the info I found online going over my head a bit), I was unable to get a usable result out of it.

Any information or help is greatly appreciated! I've got a couple images below:

Expected result:
Image

Actual result:
Image

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5533
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1391

Re: [4.0.0] Orthographic Projection Sampling Issues

Post by dark_sylinc »

  1. Is mipmapping disabled? This sounds like a mipmapping issue.
  2. Why is expected and actual result in different resolutions and not aligned?
User avatar
haloman30
Halfling
Posts: 40
Joined: Mon Aug 29, 2022 2:53 pm
x 3

Re: [4.0.0] Orthographic Projection Sampling Issues

Post by haloman30 »

dark_sylinc wrote: Wed Nov 05, 2025 8:34 pm
  1. Is mipmapping disabled? This sounds like a mipmapping issue.
  2. Why is expected and actual result in different resolutions and not aligned?

Yes, mipmapping is off. As for the screenshots, they're small screencaptures (using Gyazo) of the full screenshots in order to make the issue easier to see.

Might also add, that (when setup is such that gives the 'actual result' output), rendering the same object with a perspective camera, things look fine there (and I've added a third screenshot demonstrating as such).

To get the "expected result" output, I was going off of advice which suggested to use a half-pixel offset in the shader - which did actually correct the problem when using no zoom level in orthographic camera, but resulted in the outer half pixel of the texture being cut off (which is most apparent in 3D view, and I've attached a screenshot showing this as well).

I've attached the original screenshots below, if you believe they can be helpful:

Expected result:
Image

Expected result in 3D, no issue:
Image

Actual result:
Image

Actual result in 3D, note the outer half-pixel being cut off:
Image

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5533
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1391

Re: [4.0.0] Orthographic Projection Sampling Issues

Post by dark_sylinc »

I've been thinking about it, the only thing I can think of is that your half offset is poorly implemented.

Let's review how it should be done: Your texture is 32x32.

To get pixel-perfect sampling, the UVs (not the position) should be offset by 0.5 (and have point filtering, no mipmapping). You want to address [0.5 / 32; 31.5 / 32]

You are using 4 quads.

The UVs for the quads should go:

  1. From [0.5 / 32; 0.5 / 32] to [15.5 / 32; 15.5 / 32]
  2. From [15.5 / 32; 0.5 / 32] to [31.5 / 32; 31.5 / 32]
  3. From [0.5 / 32; 15.5 / 32] to [15.5 / 32; 31.5 / 32]
  4. From [15.5 / 32; 15.5 / 32] to [31.5 / 32; 31.5 / 32]

If you make the UVs go from [0; 1] and then simply add 0.5 / 32, it will be off because it will go from 0.015625 (correct) to 1.015625 (incorrect), because it should go from 0.015625 to 0.984375.

Cheers

User avatar
haloman30
Halfling
Posts: 40
Joined: Mon Aug 29, 2022 2:53 pm
x 3

Re: [4.0.0] Orthographic Projection Sampling Issues

Post by haloman30 »

dark_sylinc wrote: Thu Nov 06, 2025 4:25 pm

I've been thinking about it, the only thing I can think of is that your half offset is poorly implemented.

Let's review how it should be done: Your texture is 32x32.

To get pixel-perfect sampling, the UVs (not the position) should be offset by 0.5 (and have point filtering, no mipmapping). You want to address [0.5 / 32; 31.5 / 32]

You are using 4 quads.

The UVs for the quads should go:

  1. From [0.5 / 32; 0.5 / 32] to [15.5 / 32; 15.5 / 32]
  2. From [15.5 / 32; 0.5 / 32] to [31.5 / 32; 31.5 / 32]
  3. From [0.5 / 32; 15.5 / 32] to [15.5 / 32; 31.5 / 32]
  4. From [15.5 / 32; 15.5 / 32] to [31.5 / 32; 31.5 / 32]

If you make the UVs go from [0; 1] and then simply add 0.5 / 32, it will be off because it will go from 0.015625 (correct) to 1.015625 (incorrect), because it should go from 0.015625 to 0.984375.

Cheers

So, doing this for one of the four tiles (manually overriding the UVs for it to avoid any mess-ups), just results in the same behavior I ran into before with the half-pixel offset, where the outer half-pixel was just cut off, while displaying correctly at 1:1 scale (same as before again).

I've attached a couple screenshots again, one at 1:1 scale (no zoom-in) and one that's more zoomed in. The #1 red/white tile is the one that's had its UVs adjusted, with the rest just being the default (no offset or anything, just normal UVs):

Image

Image

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5533
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1391

Re: [4.0.0] Orthographic Projection Sampling Issues

Post by dark_sylinc »

AAAHHH I get what's going on now.

You need to snap the vertex positions to pixels.

Let's say your ortho projection goes from -16 to 16 and -9 to 9 and your render window resolution is 1920x1080 (it's often not if there is a title bar!).

Then your vertices must be snapped like this:

Code: Select all

pos.x = floor( ((pos.x / 32.0f) * 0.5f + 0.5f) * 1920.0f ) / 1920.0f - 0.5f * 2.0f;
pos.y = floor( ((pos.y / 18.0f) * 0.5f + 0.5f) * 1080.0f ) / 1080.0f - 0.5f * 2.0f;

Note that floor() is not the same as truncation for negative numbers. In floor(-1.2) returns -2.0 which is what we want.

Of course if the camera is not centered around 0 (i.e. your ortho projection goes from 20 to 52 instead of -16 to 16) you need to modify the math to account for this center (though I'm not sure if it's even necessary, all we care is the relative size of the pixels).

EDIT: Once you've snapped the vertices to pixels, it's possible you may have to revisit the UVs by +/- (0.5 / resolution). But snapping to pixels is definitely required.