For the Graphics 2 competition a while ago I built a concept 3D engine which plotted 2D tiles, read from a tile map in 3D space. This was made possible by the new feature that allowed us to warp textures.
https://www.youtube.com/watch?v=X52EKFIeKhY
Unfortunately it was very CPU intensive and had the usual 3D issues of polygons / textures warping when points go behind the camera and also artefacts where the textures doesn’t line up exactly. On an iPhone 6 it would hold about 30fps, 60fps if the tiles in view were pre-calculated. On my iPod Touch 5 ( cpu one before A7 ) it would sit around 20fps with a lookup table.
Just a few days ago, after some very quick support from the Corona devs, we were given canvases. This would allow me to render a texture, say a segment of a racing track, as in the first demo, and then pass that data to an OpenGL shader to convert into 3D.
https://www.youtube.com/watch?v=qD6OLH8t0Aw
What you are seeing above are 2 seperate textures being rendered into 2 separate shaders. The ground shader is set to repeat and it is fed an animated texture, moving for effect. The background layer can also accept a tiled layer of 128 x 128 tiles.
The track layer is another tiled layer of 128 x 128 tiles, the background layer is shifted down for a 3D effect. I also render a shadow of the track onto the background layer.
The yellow dots however are not rendered by the shader. These are superimposed afterwards, with Corona using my original 3D engine to plot the corners of the tiles in the 3D space. Just as you would with sprites of the other cars, work out their position on the tile map, pass that to the 3D engine and it returns x , y and scale for each sprite in screen space.
At the moment though the 3D code in the shader and the 3D code in Corona is quite different. I tried to write the fastest code for each with means its more voodoo code that just kinda works because.
Aligning the output from the shader to Corona space took a lot more voodoo and some weird values in the 3D engine, but it all now works and matches up. Voodoo!
Issues -
- I really could use some fast, 3D code, that I can use in both Corona and the Shader and give it the same values to achieve the same viewing angle. At the moment it took a lot of tweaking to get both to match up which means I can only do rotation around the Y axis. It’s enough and matches what I wanted to achieve, but better, easier to understand code would be much great. It would allow me to setup a screen for each device, rather than the 1024 screen shared across all.
The pink grid is iPhone 4 / 5 / 6 / 6+ and the simulator is running at 1024 x 1024 at the moment. Each device crops to the right borders, meaning everything is the same size on each device.
- To achieve the same view across different devices I have to render to a 1024 x 1024 texture. If I make the texture the size of the screen then the 3D goes wonky at the aspect ration changes and I can’t seem to account for that.
This needs work as a lower end device still ends up rendering the 1024 texture ( scaled x 1/4 for pixellated effect ), but its still a waste of GPU time. Even if I am not actually drawing those pixels on the devices ( OpenGL shader discard for out of bounds ) it still takes time, though not as much at the texture lookups.
- After that I’m going to make each tile animate, such as the lights flashing and the 2D track collision data will be generated from the tile map.
This is how it looks at the correct resolution on device.