The BRender Technical Reference Manual wrote:The Shade Table
For performance reasons (with the added benefit of lower memory requirements) textures, rendering or both can be performed using colour indices instead of colour values. Each colour index is converted into a colour value using a colour look up table (CLUT), often called a palette. When textures are made up of indices there is no straightforward way of lighting them. The brute force way would be to look up each texture index in the colour table, apply lighting to it to see what shade it should be, and then search through the colour table for the index of the colour value most closely matching this shade (which may not be very close at all). Because there isn't any processing power to waste, BRender implements a scheme using a shade table which for a given colour index and proportion of light, will give a colour index corresponding to the shaded colour of the original index.
Being two dimensional and storing pixel values, the shade table is quite suitably represented in the form of a pixel map. It has as many columns as there are colour indices and as many rows as there are distinct shades (from unlit to fully lit).
The BRender graphics engine behind Carmageddon takes care of three effects via 'tables': depthcue (darkness/fog), shading, and pixel blending.
These tables are nothing else but BRender pixelmap files with a .tab extension and are always as wide as there are colours in the palette: 256 pixels.
Going left to right, pixels correspond to each colour taken sequentially from the palette from index 0 to index 255. From top to bottom, pixels define along the table's height the beheaviour of each colour according to the table's purpose.
This was a good scheme used by early graphics engine in the mid 90s to quickly achieve these effects at low performance cost. BRender also came with tools to generate palettes and shade tables, MKRANGES and MKSHADES.
While one that would have been very interesting to customize, a race's fog table can't be changed easily. The race TXT file only allows you to set it to dark (black fog), fog (white fog), or none (disabled). 'dark' uses DEPTHCUE.TAB, 'fog' uses FOG.TAB, and unless you directly change these files, there is no way to customize a track's depthcue color. A couple of other fog tables are present and loaded by the game, ACIDFOG.TAB (yellow) and BLUEGIT.TAB (blue), but they remain unused.
Fog tables are also generated (stXXXXXX.TAB) for the dirt cloud behind wheels when driving through grass or on chalky roads etc. The color is defined by the number right before the skidmark material in the material modifiers part of the race TXT file. There seems to be only 8 hardcoded colors but I don't know the details yet. If anything this shows the game could have handled coloured depthcue easily.
Fog tables are usually 256x16. Some older BRender demos seem to be able to load it through the material script like so:
But this is something I couldn't find how to do for the material binary file. All of the above flags might be implemented in C1 and C2 but the fog related ones remain unreachable. I wouldn't be surprised that room for these exists in the binary form but as I've been using Plaything1 to convert material scripts to their binary counterpart and that PT1 didn't support these flags yet, there's currently no way to figure this out. AFAIK. What's more, the version of the BRender Technical Reference Manual we have (v1.2) doesn't cover fog tables.
The BRender Technical Reference Manual wrote:br_pixelmap * index_shade
Materials with indexed colour texture maps can only be lit if they are accompanied by an appropriate shade table. The shade table is simply a way of tabulating the output pixel given a particular texel and a particular lighting level. The texel generally indexes the column and the lighting level, the row. The shade table must therefore have the full complement of columns necessary for the pixel size of the texture map. The shade table may have any number of rows, as the lighting level directly selects the row.
Thus an 8 bit indexed colour texture map requires a shade table with 256 columns and two or more rows (one being redundant). A selection of shade table types for use with 8 bit textures are described below.
BR_PMT_INDEX_8 shade table to BR_PMT_INDEX_8 output
The shade table converts 8 bit texels into 8 bit lit pixel values, by using the pixel in the shade table at the column given by the texel and the row given by the monochrome lighting level.
BR_PMT_RGB_555 shade table to BR_PMT_RGB_555 output
The shade table converts 8 bit texels into 15 bit lit pixel values, by using the pixel in the shade table at the column given by the texel and the row given by the monochrome lighting level.
BR_PMT_RGBX_888 shade table to BR_PMT_INDEX_8 output
The shade table converts 8 bit texels into 8 bit lit pixel values, by using a single 256 column wide table, but with 24 bit colour values in order that true colour lighting can be applied. The red and green components of each value are actually column indices used to obtain a blue component which is produced as the output pixel. The table is thus read three times.
X1=Red component of pixel in shade table at column(Texel), row(Red light level)
X2=Green component of pixel in shade table at column(X1), row(Green light level)
X3=Blue component of pixel in shade table at column(X2), row(Blue light level)
Ouput pixel is X3
2. SHADE TABLES
Somehow the most known one even though it went completely unused! The shade table is a 256x4 table that aims to enable shading/highlighting on objects - be it cars, accessories or even the track itself - following the smoothing groups and their exposition to the main light vector. It is loaded throughout the game materials as DRRENDER.TAB as the default one. However, upon loading race and car assets the game also entirely dismisses the shade table and the lighting settings to end up rendering a fullbright scene. Only materials already loaded via the registry (REG folder) remain unaffected (possibly thanks to registry preprocessing).
This means that moving the .PIX and .MAT of either a car or a track to the registry (and then removing them from the txt file as the game will load the resources regardless) will enable DRRENDER.TAB shading or a custom one specified in the materials (and also located in the registry). The lighting settings defined per material are also taken into account to apply the shading.
However there are some setbacks. By moving the .MAT file to the registry, the materials become unreachable for funkadelics. Also while stable on cars, the shading sometimes disappears (for good) on some track geometry as the camera gets close to it. Finally as the resources located in the registry are loaded at ay time by the game, abusing this trick might lead to eating a lot of memory.
Still this is a very good way to get creative and create effects on some materials or even only on some colours. Like subtle bodypaints on cars, or slight orange-ish highlights applied on building windows in a track set at sunset.
This can also be used to reassign colors differently on a set of textures without duplicating them. Especially useful to create darker materials for shady areas: you only have to duplicate these materials and make them load a single custom darker and gradientless shadetable. In a similar fashion, the coloured Eagles could have all used the same red textures and only used a different shadetable each to reassign the red colours to either yellow, blue, white, black, etc.
The BRender Technical Reference Manual wrote:br_pixelmap * index_blend
Blending is a way of making the destination pixel depend upon the existing contents of the output buffer. The blend table like the shade table tabulates the output pixel given a particular texel and the pixel already in the output buffer. The texel indexes the column and the existing output pixel the row. The shade table must therefore have the full complement of rows as well as columns necessary for the pixel size of the texture map.
Thus an 8 bit indexed colour texture map blend table needs 256 columns and 256 rows. The blend table is only used if BR_MATF_BLEND is set, and if set this member should not be Null.
Given that the blend table tabulates an output for every possible pair of input pixels, any function can be represented, e.g. exclusive-or, inverse, inclusive-or, mask, average, etc.
The blend table is typically used for translucence effects, e.g. ghosts, flames, frosted glass, etc.
Note that in the case of the depth buffer renderer, while the output pixel will only be written if it is nearer than the existing pixel, it will never modify the depth buffer value. This is because it is assumed to be an intangible surface. Therefore, it may be necessary to render such materials in a separate stage.
Note that if both a blend table and shade table is used (the material has an indexed texture which is lit and blended), the shade table is applied first, followed by the blend table.
Blend tables, as with shade tables, also need to be added to the registry before use.
3. BLEND TABLES
The lesser known and most interesting one. The three main blend tables BLEND25.TAB, BLEND50.TAB and BLEND75.TAB were first made use of in the Splat Pack expansion to achieve 25% 50% and 75% transparency on materials featuring '\25' '\50' and '\75' in their identifier. But it's possible to load custom ones within materials of track geometry, accessories, and somehow cars.
The trick is easier to achieve than with shade tables: you have to create a new blend table (256x256), store it Data\SHADETAB, make it load from within the car/track txt file and finally edit the .MAT file with an hex editor to add a the blend table within the materials.
To do this, you have to insert a bit of data very similar to the chunks that load the pixelmap and the shadetab:
The 1E byte in the example above is the important bit as it specifically tells the game to load and use the blend table. If you have a good eye, you'll notice there's no chunk starting with the 1D type byte and you're probably thinking "here's your index_fog!" Well I tried and didn't get any result, so I don't know :(
As previously mentionned, blend tables are 256x256 pixels, both width and height corresponding to the colour palette this time as they're meant to define the result of any possible colour blending within the palette. You can see it like that: the range represented by the width are the colours closer to the camera, while the height covers the colours behind. I guess the visuals below will be easier to understand. Once again it's possible to get very creative once you grasp how it works.
There seem to be some limitations ofcourse. Firstly the blending effect don't seem to apply properly to some actor types depending on the one holding it. For example, blending materials on cars won't blend with track materials. Some blending materials loaded on materials will also not blend with materials from another noncar. Secondly it seems like there is a total amount of blendtables that the game can load before it starts to display the effects sporadically (the materials might flicker). Keep in mind the game might want to try and load the main BLEND25.TAB, BLEND50.TAB and BLEND75.TAB. Not renaming Plaything2's generated main track actor identifier (as we do precisely to enable the transparent blend tables) helps in that regard.
Finally, some kind of conflict prevents blending car materials against the track's materials and instead render them fully transparent. It appears like the blending material must always be applied against another textured component behind it. I'm still investigating this. You can check the Subaru Impreza for an example in the reflections material.
Informative read there Tosh. I never knew exactly what the tabs were for, but now I get a much better idea. It's fun to realise that all this was a necessity back in the days, just to get 'simple' things to work.
Also reading your posts I realise that so many visual tricks in C1 and C2 were present but never really got to their full potential or are just simply broken. Pretty sad really.
Yes, this is a very interesting subject and I'm not done with it yet
Harm: you read the article while I wasn't done yet, you ninja. I've edited some stuff and added excerpts from the BRender tech ref manual as well as pictures.
It would be nice to figure that 1D byte type entry in the material structure. Recently thought it might also be a palette? Still haven't given up on it being the fogtable and thought local fogtables might have to be a different height (BRender manual hints at 64 instead of 16).
Harm: you read the article while I wasn't done yet, you ninja.
Hah, I already thought I was a little too quick as there were some image references that I didn't see yet. :)
I'v never seen that blend table test map before and must have completely missed that one. In general, the whole research you have done and the presentation you gave here is impressive. It's like digital archeology :)
I'm surprised you figured out the 1E part to begin with. Did you try adding other lines below 1F?
The 1E type was easy to get as I was sure PT1 would keep the info while converting the material script into the binary format.
However the fog table seemed like a novelty thing somehow. PT1 doesn't want to hear about it. PT2 can't load material scripts.
To be frank I have doubts that the game would allow a per material fog table. It certainly includes the bit of BRender code that would handle that but might not make any use of it.
I indeed tried to add other types beyond 1F and 20 but to no avail. One of these types might turn out to be the correct one and I wouldn't know as the game wouldn't use it.
I also tried to look for other BRender games with 8bit graphics mode but that didn't help so far (though I thought Croc does but I can't run it anymore for some reason).
I could try to mess with 3DS2BR but the version I have dates back to 1995 and is for OS/2.
Fog table can be loaded in a material via the 3Bh chunk ID. I haven't worked out too well how they work, but the game does load and use them. It seems to me like the pixelmap for the fog table has to be generated in a specific way.
"local fog table" flag might be for RGB mode, haven't tested.
1Dh was the chunk ID for BRender opacity map but it's completely unused by the graphics engine.
The engine seems to treat screen door masks as tables, and load them via the chunk ID 20h.
Blend tables do work on cars, though IIRC, you can only load up to 2 tables per car. The material doesn't have to be in the REG folder (unlike custom shade tables). However it won't be applied to anything that's above the model holding it in the world hierarchy (that means other parts of the car above it in the car ACT file, but also the track as it is loaded before the cars), and thus will be completely transparent. It is still very useful to create effects for windows etc, just remember that at all times there must be a mesh behind it.
In the following screenshot, I've actually duplicated the glass dome and flipped the triangles of the clone so that it is two sided. The outside material is the blended and environment mapped material, while the inside material is solid. This way the blending is applied at all times against a car mesh and the transparent window aspect is there even though not perfect (can't see the track through thanks to the solid material on the inside).
Set a blend table to only work against one colour that acts as a mask:
The skybox material also makes use of the "force front" flag to be rendered in front of the mask, and somehow doesn't go in front of the vehicle materials (it should), I suspect it is because of the groove or the > prefix I used on the skybox material to make it nonsolid.