How to enable CEL super clipping

 A very basic feature that for some reason is disabled by default, is that of additional CEL clipping hardware functions. The 3DO will clip the rendering against the framebuffer (or a smaller clipping area if you define it with certain functions) so pixels will never be rendered outside the screen and corrupt memory. However, it does so by continuing the costly interpolation and checking pixel after pixel, finally discarding the rendering of it if it falls out of screen borders. This is called Normal Clipping in the documentation.

But little did I know as I was coding some homebrew stuff that very big CEL quads that fall partially or fully outside the screen, like a 3D stars zooming effect with big blobs would sometimes sharply drop down the frame rate as some of the stars came too close even if they were projected outside of the screen (and I was lazy to check that with the CPU back then). By the time I managed to enable the super clipping functionality, everything became much smoother with an always stable 60fps framerate.

I found a similar lack of this feature even in commercial games like Doom on the 3DO. In most cases of course, because of the performance bottleneck on the CPU, enabling this feature wouldn't give much. Except when the player moved extremely close to some very tall walls. The wall columns weren't clipped against the vertical borders of the screen to avoid more CPU calculations, only left for the 3DO hardware to clip the rendering. By enabling this feature, moving close to the tall walls would saw a big difference. I made an experimental map with the highest wall height I could do (a bit less than 1024 I think, as this would hit the maximum CEL bitmap width) and going close to this wall would yield 5fps without superclipping and maybe reach 30fps or more with it (I don't remember the exact numbers, but I remember the low 5fps and the vast difference). Of course not very useful for the majority of player views that hit the bottleneck, but a very easy feature to have that many 3DO programmers might miss.

And they might miss the feature as I initially did, because unlike other CEL features that can be enabled by simply setting some flags on your CCB structure, this one needs one additional step.

You have to set after screen initialization the ASCALL flags in the CEL engine control. Below I am doing it for each of my two bitmap items created for double buffering.

for (i=0; i<2; ++i) {
    SetCEControl(BitmapItems[i], 0xffffffff, ASCALL);
}

And only now it will work when you enable the bit flags in all of your CCBs.

for (i=0; i<celNum; ++i) {
    myCel[i]->ccb_Flags |= (CCB_ACSC | CCB_ALSC);
}

When you used CreateCel to initialize a new CCB, assuming you don't do it manually on your own, the default flags where missing those two. And neither the CEControl was set to enable the whole feature. It's a simple thing that can save performance if you mindlessly render huge CELs that are partially or wholy outside your frame buffer. In some cases it's not even lazy, but necessary, like in a 3D engine where some big polygons close up will cover a big area outside (and clipping the polygon to smaller ones would need some CPU and because of lack of texture coordinates would lead to several problems anyway). So why not just enable this feature and let the 3DO handle this for you and save you from all the hassle (of course I am not talking here being lazy with world visibility, don't just send every polygon of the whole game world!).

The way the super clipping works btw is interesting and weird. We have enabled two types of super clipping, the CEL Super Clipping and the Line Super Clipping. The LSC can early terminate interpolating and rendering the rest of a bitmap line if it can predict there is no point to continue. It doesn't know much spatially, except of the current position and direction of the bitmap line vector scaler. So, if the vector points to the right and it just reached the right edge of the screen, it knows that no matter how much you move you have escaped from the screen. It will terminate and move to the next bitmap line. The CSC will determine this for the whole CEL. That depends on the CEL vectors and the position against the borders of the screen. It's very invariable, so you could have sprites that are on the left side of the screen but vectors pointing right and they wouldn't gain any performance by superclipping. One could even flip the vectors and bitmaps of numerous sprites depending on the quadrant of the screen. But that's only if you know your sprites will move in and outside the screen frequently and if they are enough and carry big sized bitmaps to matter. A better overview of the whole process depending on the side of the screen your CEL is can be found in a chapter here.

I did some experiments with a lot of small sprites to determine if the process of super clipping can reduce performance in the cases where you are sure that your sprites will never be outside the screen and the answer is no. 1024 sprites of size 16*16*8bpp, 35fps (with vsync disabled of course) in both cases. I tested disabled ASCALL or each of the flags or both. This feature seems to be free and you should enable it.

Comments