The shoutbox is currently out of service. Join us on Discord instead.
You can help CodeWalrus stay online by donating here.

X3D - A 3D engine for TI68k & Nspire Calculators

Started by catastropher, June 27, 2015, 02:37:43 am

Previous topic - Next topic

0 Members and 4 Guests are viewing this topic.

catastropher

Quote from: 123outerme on July 02, 2017, 07:33:00 pm
So you need beta testers, right? I would love to test! I have a monochrome Nspire, if that is helpful information for you.

Quote from: gameblabla on July 03, 2017, 01:45:54 am
I have a TI-Nspire CX and i would love to try it !
How fast is it ?

Awesome!!! Thank you guys! At the moment, it's still just PC because it's much easier to develop on (though I will soon produce builds for the calcs as well). Do either of you run Linux by any chance? My goal is to have a new testable release every 1-2 weeks to get things moving along.
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

gameblabla

Quote from: catastropher on July 03, 2017, 11:15:15 pm
Do either of you run Linux by any chance? My goal is to have a new testable release every 1-2 weeks to get things moving along.

I'm currently using Devuan linux (a Debian fork) and i can compile stuff.
Should i compile myself or should i try out your binaries?

catastropher

Quote from: gameblabla on July 04, 2017, 12:03:16 am
I'm currently using Devuan linux (a Debian fork) and i can compile stuff.
Should i compile myself or should i try out your binaries?

Awesome! Truth be told I don't have any binaries, so if you could compile it yourself that'd be great XD It's not quite ready for the first test though, I'll need a few more days to finish the current the sprint. I'll let you know when I'm ready! Thanks! :)
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

catastropher

Hey guys! I have many exciting updates to announce:

  • I implemented code for Quake's potential visibility set, so only BSP nodes that are potentially visible are sent down the rendering pipeline. Since Quake levels have thousands of polygons, this means huge speedups

  • I got support for the Nspire up and running

  • I added a custom implementation of Sorted Spans so that the level can be drawn with 0 overdraw and without Z-Buffering
  • I implemented flat shading

  • I added a memory manager to prevent memory leaks


Here's an animated screenshot:
X3D Quake E1M1: ShowHide


Here's what the level looks like in Quake for comparison:

Regular Quake E1M1: ShowHide


Also, I have a question that I hope someone may know the answer to. Ndless provides lcd_init(), which I use to put the calculator in 8-bit palette mode. If I do this, I get nearly double the framerate compared to using nSDL's palette mode (looking at the source, I saw that it just uses a color table to convert to 16-bit color). However, Ndless doesn't seem to provided any way to change the calculator's palette colors. Anyone know if this is possible? I need to change the color palette to reflect Quake's palette.
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

Vogtinator

Looks impressive!

Now just textures, shadows, anti-aliasing and shaders are missing :P

Out of curiosity, did you try it on hardware as well? I noticed that there are some unexpected bottlenecks there, especially memory speed (simple blit is already much slower).

QuoteHowever, Ndless doesn't seem to provided any way to change the calculator's palette colors. Anyone know if this is possible?


Not with the public API, in fact ndless does not even know that SCR_320x240_8 is paletted. I didn't even want to add it, but did so as some programs that needed to be ported to HW-W used it, I had no choice...

I could add a new bool lcd_set_prop(enum type, union value) syscall for some more flexibility though and extend the definition of  SCR_320x240_8 to mean 8 bit with palette. This would of course require a yet unreleased version of ndless_resources.
What do you think?

For now you could hack around by writing to REAL_SCREEN_BASE_ADDRESS and specifying "--uses-lcd-blit=false --240x320-support=true" to genzehn.

catastropher

Quote from: Vogtinator on July 11, 2017, 06:17:22 pm
Looks impressive!

Now just textures, shadows, anti-aliasing and shaders are missing :P

Thanks! :) At least half of those are on the way! Guess which ones?  :P

Quote from: Vogtinator on July 11, 2017, 06:17:22 pm
Out of curiosity, did you try it on hardware as well? I noticed that there are some unexpected bottlenecks there, especially memory speed (simple blit is already much slower).

I did indeed try it on the actual hardware using different screen update methods. Though first, I noticed in the nSDL repo that nsp_palette is a global variable:

static Uint16 nsp_palette[256] = {0};

I also noticed that the code to convert the screen to 16 bit color looks like this:

/* 8 bpp SW, 16 bpp HW */
NSP_DRAW_LOOP(
for ( j = 0, k = 0; k < row_bytes; j += 2, ++k )
*(Uint16 *)(dst_addr + j) = nsp_palette[src_addr[k]];
);


I noticed that every iteration of the loop is reading from nsp_palette, which is a global variable. Is the compiler smart enough to put the address of nsp_palette into a register? Otherwise, it may keep loading the absolute address of nsp_palette each time (or at least each row). If this is the case, it may help to put the address into a local variable.

I did some testing of different methods for displaying an 8-bit buffer to the screen. The first two assume the calculator is in 16-bit color mode, the last one assumes 8-bit color. To do so, I disabled all rendering in my engine (except for showing the frame rate). Here's version 1, which is similar to the code in nSDL:

unsigned int sdlColors[256];    // Color palette

unsigned char* pixel = screen->pixels;
unsigned char* pixelEnd = screen->pixels + 320 * 240;

unsigned short* pixelDest = REAL_SCREEN_BASE_ADDRESS;

do
{
    *pixelDest++ = sdlColors[*pixel++];
} while(pixel < pixelEnd);


Using this method, I got 27 FPS (without rendering anything, just updating the screen). However, by changing the code to pack two 16-bit pixels into an int, I got 41 fps:

unsigned int sdlColors[256];    // Color palette

unsigned char* pixel = screen->pixels;
unsigned char* pixelEnd = screen->pixels + 320 * 240;

unsigned int* pixelDest = REAL_SCREEN_BASE_ADDRESS;

do
{
    *pixelDest++ = (sdlColors[pixel[0]]) + (sdlColors[pixel[1]] << 16);
    pixel += 2;
} while(pixel < pixelEnd);


Even better, if I set the calculator to be in 8-bit mode and just use a direct memcpy, I get 66 FPS:

memcpy(REAL_SCREEN_BASE_ADDRESS, screen->pixels, 320 * 240);

The only problem using this method is that I can't change the palette colors and it probably wouldn't work for 240*320 screen.  Speaking of which, I may need to setup X3D to render sideways for those calcs XD Internally, I store all of my textures as 8-bit pixels because 1. that's what Quake did and 2. I can fit twice as many pixels into cache (which is a pathetic 4KB). As for current rendering speed, the average scene renders at ~15 FPS using method 2, and 25 FPS using method 3. Of course, I haven't put that much effort into optimizing it yet.

Quote from: Vogtinator on July 11, 2017, 06:17:22 pm
I could add a new bool lcd_set_prop(enum type, union value) syscall for some more flexibility though and extend the definition of  SCR_320x240_8 to mean 8 bit with palette. This would of course require a yet unreleased version of ndless_resources.
What do you think?

That would be awesome! Would it also be possible to provide a way to change the palette colors in hardware? Also, would it be possible to read the palette colors so we can restore them when the program exits?

Thank you so much! :3
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC


catastropher

Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

Legimet

July 13, 2017, 12:19:39 am #263 Last Edit: July 13, 2017, 01:26:44 am by Legimet
The palette registers are at at 0xC0000200 (0xC0000000 is the base address). These pages on Hackspire are a good reference: https://hackspire.org/index.php/Memory-mapped_I/O_ports.
You have to write one (32-bit) word at a time, and the structure is as given in the page I linked:











BitNameDescription
[31]IUnused
[30:26]R[4:0]Red palette data
[25:21]G[4:0]Green palette data
[20:16]B[4:0]Blue palette data
[15]IUnused
[14:10]R[4:0]Red palette data
[9:5]G[4:0]Green palette data
[4:0]B[4:0]Blue palette data


For classic Nspires I believe only [25:22] and [4:1] are used but you should make sure.

Oh, and I forgot to say: you should do the usual lcd_init(SCR_TYPE_INVALID); before exiting to restore the mode and free any memory that was allocated (like on classic).

catastropher

@Legimet Thank you very much! I'll implement this as soon as I get the chance! :)
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

TheMachine02

Definitly awesome.  :)  How will you handle lightning with custom palette ?

catastropher

Quote from: TheMachine02 on July 15, 2017, 02:30:00 pm
Definitly awesome.  :)

Thank you very much! I think your 3D stuff is really awesome too! :3

Quote from: TheMachine02 on July 15, 2017, 02:30:00 pm
How will you handle lightning with custom palette ?

So for X3D I'm using Quake's color palette, which looks like this:
Quake Color Palette: ShowHide


This is used to build a 256x64 (I'll probably make it smaller for cache reasons) table that for a given palette color and light intensity, it will tell you the palette color that it maps to. The table when visualized looks like this:

Quake Light Colormap: ShowHide


Looking up into a large table like that is expensive, especially for every texel, which is why textures and lightmaps are combined and cached into what are called surfaces. Michael Abrash, one of the devs for Quake described it really well in his book, Graphics Programming Black Book (http://www.drdobbs.com/parallel/graphics-programming-black-book/184404919) Check out chapter 68, "Quake's Lighting Model". Also, checkout chapter 66 and chapter 67 to see how Quake drew the world geometry without any overdraw. I've modified their algorithm to be very cache friendly (still a WIP though).
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

catastropher

I got perspective-corrective texture mapping working! It currently runs at 5 fps on the calc, but I have several optimizations planned:

  • Instead of doing the perspective correction (which requires a division) every pixel, I'll do it every 16 or 32 pixels and use linear interpolation

  • I'll use mip-mapping so that we won't get so many cache misses with textures that are far away

  • I'll make it so the active edge table will share edges between adjacent polygons so we only have to scan half as many edges


Of course, I'll probably write an assembly version of the span renderer eventually. Here's what the results look like so far:

Textured First Quake Level: ShowHide


On to optimizing! :3
Creator of X3D, a 3D portal rendering game engine for Nspire, 68k, and PC

gameblabla

July 17, 2017, 07:19:58 pm #268 Last Edit: July 17, 2017, 07:21:29 pm by gameblabla
Erm, catastropher ~~~ !
I compiled your program again but... it forces shutdown my computer !
That, without even needing root access !
If you want to try it in a vm, here :
https://gameblabla.nl/files/make_linux_crash.zip

It f***ed up my keyboard too :(

Legimet

By the way, there's no need to define your own __nspire__ macro. nspire-gcc already defines _TINSPIRE.

Powered by EzPortal