OpenGL sprite script using z-buffer with perspective projection and no distortion. Possible?
I am working on some sprite based games. For z-order sprites, there are mostly alternatives to 1) draw in the correct order - can be troublesome to dose
2) use spelling projection and depth testing - can be problematic with translucency
I prefer 2) however I would like to keep the perspective projection to allow some simple 3D animations. The cards are flipped to 3d, etc. If I do this, differences in z-buffer can / result in scaling of the sprites, since the objects are at different distances from the camera.
I was thinking about scaling the sprites based on their distance to cancel the projection. But then I will get interference with 3D animated objects on top of the "non-planar" 2nd scene.
I guess the sane way is to go to a 2d spelling scene and do sparse 3D animations in the second step with "cloned" objects on top of it. But maybe someone else has a different idea?
Mikkokoos answer led to a solution. Through an additional depth value, the vertex shader can adjust the z-coordinates of all vertices in clip space to push them to different depth levels. Real 3d coordinates can remain at z = 0. Changing the clip space eliminates perspective issues, so perspective projection can be used in the scene.
To allow different camera angles than perpendicular to the plane of the sprite, instead of pushing the vertices of the sprite to fixed layers, they should be adjusted with the layerOffset * layerIdx. Therefore, for each layer, the vertex is nudged one step closer to the camera. Note. With fixed layers, it can be very difficult to find the correct clip space coordinates, since the xy plane is not necessarily in the center. Open Questions: Clip Space Resolution? The smallest difference in a clip? Potential interference between pushed sprites and real 3D elements? To prevent 3D objects from overdriving plane sprites, all non-sprite objects must be offset using the maximum layer offset used. Calculating layer offset from available space in front of the camera is probablywould be a good idea.
Achieved: The sprites are organized on the 2nd plane in the perspective projection of the 3d scene. The sprites are closed based on the fragment depth calculated in the shaders. Painting can be done in texture packs. Note2: I still believe you are doing two rounds of draws. 1st for 2 sprites with a given depth, 2nd for sprites or objects that are not "attached" to the sprite plane. Clears the depth buffer between them and adds an invisible clipping sprite plane. (unless objects behind the scene are allowed)
source to share
You can use perspective projection to render all sprites and have a uniform float "depth" for each, which will replace gl_Position.z at the end of the vertex shader:
This will "flatten" the mesh, so if your meshes are more complex and depending on the DepthFunc used, you may want to have a range. (visible range -1 to 1):
Where u_zRange is 2f / (number_of_layers) and u_zOffset is u_zRange * layer_id. Layer 0 is the closest.
EDIT: Summary. Place everything through the MVP matrix at the same distance from the camera and then change the Z value in the vertex shader to order them on screen.
source to share
I don't know what kind of game you are developing and how the next one might fit into your system, but have you considered using both perspectives?
If the object you want to render well isn't the same object you want to animate in 3D, why not use orthographic projection for the former and perspective projection for the latter?
In fact, even if they overlap, you can probably pull off some kind of trick (if not a simple linear transition ...) where the orthographic projection is replaced with a perspective just before the animation, using the appropriate parameters (your mileage may, however, change me and I confess I didn't do math ...).
Maybe this is a crazy idea, nevertheless I hope this helps
source to share