Thursday, November 19, 2015

Improved 2D and other fixes


As you may see, the blog had no updates for several month. The reason is simple: works for Indiegogo campaign have been finished; attempts to get additional funding for project development failed. Now I have a job and as result have almost no free time for my hobbies. This does not mean that the project development is stopped. The project is open sources and in a good shape thanks to rapid development period. New features and fixes implemented not only by me, and in the last time mostly not by me.

2D improvment

Firstly I want to present you new feature, which I started to develop yet in summer but was unable to finish until now due to lack of time. It addresses 2D images quality. As you may notice, all N64 graphics plugins with hardware rendering have problems with large 2D images. 2D images look very misaligned, like this:

Software graphics plugin renders this picture with no issues:

Why this happens? N64 has only 4 kilobytes of texture memory. 320x240 background image takes 150 kilobytes. The hardware can't render large images as one piece. So, to draw the image it need to be split on hundred narrow stripes with height of 2 pixels. Here how it looks in wireframe mode:

Strips are not the problem. The problem is that each stripe of the image is filtered with bilinear filter to get more smooth result. Filtering has no negative effect when native resolution is used. You may run hardware graphics plugin in native 320x240 resolution and find that it works as good as software plugin; no texture misalignment. It is because texture strip and corresponding polygon have the same size and there is one-to-one pixel to texel correspondence. However, nobody uses native N64 resolution with hardware plugins (there is a request to support rendering in native resolution and then scale it to screen resolution, but it is different story). When resolution increased, polygon size increased accordingly, but texture remains the same. Each strip filtered separately and that causes misalignment on bounds between strips. Of course, it is possible to disable texture filtering and get aligned but pixilated image:

some people like sharp unfiltered images.

I implemented new method of drawing 2D images. We know that it is impossible to render stripped low-res 2D image in high-res and get aligned filtered result. Thus the idea is to render 2D in native resolution. The plugin detects that adjacent parts of a 2D image are drawn and renders all parts of the image in an auxiliary buffer using native resolution. When all parts of the image are drawn the whole image is rendered to the main buffer. Since filtering applied to the whole image, not to its parts, the image has no alignment problems:

It sounds simple, but as usual the devil hides in details. I spent many hours on debugging and even wrote my own bilinear filtering shader because standard one causes glitches. Also, the new method is not universal. It works well in most games. There are one-two games, which are incompatible with it. And there are several games where it makes some 2D images look better and other look worse. Mobile version also may suffer from performance issues.

I put the code into a feature branch fix_2D. The new method should be optional, but currently it always enabled. I'll add config settings when it will be ready to merge to master branch. Right now I want it to be tested. Please download the binaries and leave feedback in that ticket.

Other fixes

Here the incomplete list of fixes made since the latest Public Release:
  • xBRZ texture filter updated to version 1.4 Up to 6X texture scaling is now supported.
  • Implemented Shaders Storage feature. Compiled shaders can now be saved and loaded on next start of the game. Performance increased.
  • Fixed camera in Zelda MM
  • purplemarshmallow made lots of fixes in Frame Buffer Emulation code.
  • matto fixed and optimized texture cache work.
  • Francisco Zurita fixed plugin work on Adreno GLES 3 devices.
  • gizmo98 added Raspberry Pi support.