Finally it renders something! This took me quite a while to get working. Apparently the 3DS expects some vectors in WZYX ordering… The wrong ordering caused the projection and view matrix to be incorrect and the result was a blank screen.
However, on a real 3DS it looks like this:
In the emulator I could get quite a bit more working. I added the ability to load 3D models. It doesn’t download from the object path yet so I copied a pre-filled cache folder to the emulator’s virtual SD card as a test:
There it is, VP with 3D models loading on the 3DS emulator 🙂 Of course it is still missing textures, lighting and probably more.
Unfortunately I’m not sure how to fix it so it runs on a real 3DS. It doesn’t just have distorted rendering, with the model loading it hangs a few seconds after starting. Unless I get it working, this will be the last part in the series.
In part 1 I was able to build most of VP’s code for the Nintendo 3DS target using the homebrew SDK, but only a small part of it was running: just enough to make it log in.
At the end of the previous article I mentioned that other parts of the code need a functioning renderer. Actually, it just needs to have a renderer that pretends to be functioning. For situations like this VP has a fake renderer. It doesn’t render anything, it just tell the rest of the code that it did and that everything is fine. Let’s use that and see what happens when running it in a 3DS emulator.
It enters the world! You can tell from the screenshot above that the user count for testworld went from 2 to 3. And on the PC the avatar can be seen as well:
Unfortunately, when I tried this on the real 3DS it just crashed. After some online searching I found out that it is possible to enable a remote debugger on the (softmodded) 3DS through the Rosalina menu, which can be accessed by pressing L + Down + Select. I enabled the debugger attached to it using GDB:
(gdb) target remote 192.168.1.51:4003
Remote debugging using 192.168.1.51:4003
0x00100000 in _start ()
[New Thread 216]
[New Thread 219]
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00320328 in strlen ()
#0 0x00320328 in strlen ()
#1 0x001bd75c in ObjectPath::getCachePath[abi:cxx11]() ()
... more stack frames
Something appears to be going wrong when trying to find where to put cache files. It’s running the code path that is also used on Linux systems. This code path uses getenv("HOME") to find the home directory and because the 3DS most likely doesn’t have this it returns a null pointer. Adding some 3DS-specific code to determine the cache location fixed this.
There were also some easier to fix issues before it would work. Here it is running on a real 3DS:
After this I started working on a renderer implementation for the 3DS. I managed to make it clear the screen with a color, but it’s not rendering anything yet.
Since I made my old 3DS capable of running homebrew software yesterday, I decided it would be an fun project to try porting VP to the 3DS. Considering I only have an old 3DS instead of the “New 3DS” it’s probably not going to be very fast 😅
This port is just an experiment and it might not even be released. I’ve done similar things before, such as a port to the Wii and a port to DOS. Those ports were very incomplete and were never released.
For building the software I’m using the devkitARM toolchain from devkitPro. It turns out that quite a few of VP’s dependencies such as Bullet Physics, zlib, and mbedtls are already available as packages from the devkitPro pacman repository. Not having to build them myself will save some time.
After a few hours of cleaning up the causes of build errors, adding stubs in various places and implementing some system specific functions for the new platform, I have at least the network functionality working:
It logs in and shows the world list, but it doesn’t enter a world yet. While the networking code for entering a world would probably work, other parts of VP expect to have a functioning renderer available. So it will take some more effort to get that working.
This version does lighting using a ‘clustered shading’ approach. Behavior and performance might be different compared to the previous version.
Starting with this version lights will also have a finite range of 3x the radius= specified in the light command. An object with the following command:
create light color=red radius=20
Will result in a light with the first 20m having the same intensity as in previous versions, but reduce its intensity linearly over the next 40m beyond that. This is added on top of the existing intensity curve, instead of replacing it.
Fix specular maps on opaque objects in Direct3D 11 mode
Fix sound volume settings not being applied to new sounds (streaming sources like MP3, Ogg Vorbis and Opus only, WAV was unaffected)
Multi-sample anti-alias needs to be disabled or VP won’t function properly in Direct3D 11 mode
New lighting approach only available in Direct3D 11 mode
Names above avatars don’t appear
Web commands and overlays don’t work
Some scenes with many lights may be slower, even on very capable graphics hardware, because the light clusters are calculated on the CPU
Objects with transparent surfaces are still limited to a maximum of 32 active lights for the whole scene
I started working on a Vulkan renderer for Virtual Paradise back in 2016. Halfway through 2017 it could render most static models without any materials or lighting. Until recently I didn’t really put a lot of effort into actually getting it to work. Over the last few weeks I’ve been working on it some more and have actually made some progress! ?
Materials, world light and positional lights are working now:
Lighting working with Vulkan renderer
And this is how it is supposed to look:
The same scene using the Direct3D 11 renderer
So, there is still some work to do! A few things that are missing: textures, spot lights, sky rendering, anti-aliasing, normal mapping, particle systems, 2D elements like avatar name tags, shader based skeletal animation, selection bounding boxes, and probably more.
I’m still getting used to how things work compared to APIs like OpenGL or Direct3D. It’s definitely a lot more difficult to get started (so I took two years to do so ?, although I rarely even looked at it during this time). To take better advantage of this API and use multiple threads for rendering, the main (non-Vulkan-specific) code will also need to be changed, but I think I will focus on functionality first.