Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm currently working on a 3Dish game; it's on a grid, with 3D props and the camera looking down on the grid at about 45º, but I want to use 2D sprites for the player and NPCs.

Currently, I'm using a quad as a canvas, but I've run into some problems. If the quad is coming up vertically from the floor, foreshortening squashes the player. If I tilt the quad to the same angle as the camera (manual billboarding), the player looks fine but will clip through 3D objects to the "north" from the camera on the grid. I've looked into point sprites but it seems like these would have the same problem.

So, tilting the canvas is out. I need the player to be able to go in front and behind things.

My latest and most promising attempt was to turn the vertical-oriented square canvas into a trapezoid, to compensate for the perspective change. (The canvas is 32x32; at a 45º angle it ended up having a top length of 28.14 and a height of 39.68.) This gets me a square canvas again, but the texture isn't right. It ends up slightly squashed; on nearest-neighbour sampling it loses a row of pixels in the middle (on the character where it's noticeable) and gains one somewhere at the top (above the character's head...)

My maths on the trapezoid might not be exact, but this doesn't really seem like the right answer for keeping things pixel-perfect. Is there a way to use that canvas quad as, I don't know, like a window onto another rendering context which would be pixel-perfect?

Context: This is in Python, PyOpenGL and Pygame; the maximum GLSL version my computer can handle is 120 so it's openGL 3-ish but not quite.

share|improve this question
    
Create a scene in a 3D editor like you describe here, using a camera and viewport set up just like your program. Take that scene and try to create 3D player geometry in that scene that renders how you like and then recreate it in your game. If it won't work in an editor then it won't work in your game, plus it will save you a ton of coding time either way. –  Patrick Hughes Apr 14 '13 at 16:35
    
@PatrickHughes I gave this a try, but setting it up like this ended up being pretty difficult (given that I only really have access to Blender and it's a pain). However it did spur me to experiment a bit more so I bound some keys to alter the trapezoid shape and texture coords, and learned that there's really no combination of the two that will make the texture pixel-perfect. –  bonzairob Apr 14 '13 at 20:51
    
How about moving the billboard closer to the camera to eliminate the penetration with the far wall? It should still be obscured by closer walls and ceilings. This can be done in many ways: by moving where you construct the actual billboard, a hack in the vertex shader or perhaps by using "polygon offset". –  DaleyPaley Apr 18 '13 at 3:56
    
@DaleyPaley I can move the billboard a little physically, but then it starts to be too far away from where it needs to be; however, i think the polygonoffset has this more or less solved! The only problem is that it applies to the whole, angled billboard, so it sort of delays when the character's head starts to slide through things, but, if there were a way to do it smoothly so the top edge was offset and the bottom wasn't, That would be perfect. And that sounds like a vertex shader hack? That's my trouble with OpenGL, I know what I want but not how to ask for it... –  bonzairob Apr 18 '13 at 20:40
add comment

1 Answer

up vote 0 down vote accepted

For the sake of anyone stumbling across this later, here is what I did.

In the GLSL Fragment shader, it outputs a constant after main() called gl_FragDepth, which will be set to gl_FragCoord.z unless you change it.

So, with some trial and error, I discovered the magic number was 0.0006, and set it per-vertex, so the top two had this and the bottom two had 0. So now in my fragment shader under the texture coord is this line:

gl_FragDepth=gl_FragCoord.z-depth;

The fragment shader smoothly interpolates this from the values set in the vertex shader, and my polygon appears straight. However the 0.0006 system only works if the camera's depth is always the same, so is the camera ever moves closer to the player I need to work out how to make it relative to gl_FragCoord.z, rather than absolute.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.