Extend lighting model to floors and ceilings

This commit is contained in:
jndean
2023-12-04 16:40:42 +00:00
parent 60f450c57b
commit 16b21dd656
6 changed files with 61 additions and 27 deletions
+15 -13
View File
@@ -16,42 +16,44 @@ wget https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad
```
Vanilla Doom runs on the CPU, have started offloading subsystems to IPU Tile 0.
Activity Log:
### Progress Log:
Started with vanilla Doom running on the CPU, began started offloading subsystems to the IPU (just Tile 0 at first):
- [x] Create IPU hooks for key methods like G_Ticker, G_Responder so IPU can step game time and respond to keypresses in real time. (Also setviewsize etc)
- [x] Create IPU hooks for key methods like G_Ticker and G_Responder so IPU can step game time and respond to keypresses in real time. IPU uses callbacks on the host to load and unpack all level geometry from disk whenever the player starts a new level.
- [x] Implement IPU memory allocator for level state, i.e., anything with lifetime PU_LEVEL
- [x] IPU interacts with host to load and unpack all level geometry from disk whenever a level is loaded
- [x] Implement an IPU-specific memory allocator with seperate memory pools for different lifetimes: static lifetime, level lifetime, frame lifetime. Makes fragmanetation easy to avoid => reduces SRAM footprint.
- [x] Implement all methods used by the automap (vector rendering, sprite rendering, AM event responder). Automap is now disabled on CPU, renders entirely on IPU.
![Automap](README_imgs/Automap.gif)
- [x] Implement BinarySpacePartion search (stackless recursion version for IPU), solidseg occlusion and floor/ceiling clipping to get (untextured) rendering of vertical walls running on the IPU.
- [x] Implement BinarySpacePartion search (stackless recursion version for IPU), solidseg occlusion and floor/ceiling clipping to get (untextured) rendering of vertical walls running on a sinlge IPU tile.
![Gameplay with untextured walls](README_imgs/BlankWalls_noCPU.gif)
- [x] Split rendering across 32 render tiles. Reformat textures into a big buffer that can be striped over dedicated texture tiles, and accessed by the render tiles using JIT-patched exchange programs to enable fetches based on dynamic indices. So now IPU can texture walls.
- [x] Split rendering across 32 render tiles. Reformat textures into a big buffer that can be striped over other dedicated texture tiles, and accessed by the render tiles using JIT-patched exchange programs to enable fetches based on dynamic indices. So now the IPU can texture walls in real time.
![Gameplay with textured walls (but nothing else)](README_imgs/WallsTextured_noCPU.gif) ![Gameplay showing rendering striped across 32 tiles](README_imgs/WallsTileGrey_noCPU.gif )
- [x] Implement lighting model (add shadows to walls): texture tiles translate the colours during texture column fetch requests to save memory on the render tiles.
- [x] Implement lighting model (add shadows to walls): the texture tiles translate the colours during texture column fetch requests to save SRAM on the render tiles.
![Side-by-side of room with and without shadows](README_imgs/WallsLighting.PNG)
- [x] Port the visplane system to the render tiles, so IPU can render floors and ceilings, (untextured for now, instead coloured to show the visplane subdivision). Also implement skybox.
- [x] Port the visplane system to the render tiles, so IPU can render floors and ceilings, (untextured for now - instead coloured to show the visplane subdivision). Also implement skybox.
![Gameplay with visplanes and skybox visible](README_imgs/VisplanesSkybox_noCPU.gif)
- [x] Extend the JIT-patching texture exchange to support span textures and zlighting, so IPU can texture and shade floors + ceilings.
[GIF TODO]
Immediate next steps:
- [ ] Port 'flats' and zlight so IPU can texture and light floors + ceilings.
- [ ] Implement system to notify IPU of map state changes, so that doors open and close properly.
- [ ] Implement temporary(?) system to notify IPU of map state changes, so that doors open and close properly. Perhaps the same could work for enemys and projectiles.
- [ ] Implement vissprite system and masked col rendering to add objects / enemies to levels.
Longer term next steps:
- [ ] Render other things in the level (sprites and masked components, HUD (using dedicated HUD tiles))
- [ ] Render HUD (probably using dedicated HUD tiles)
- [ ] Move beyond just the rendering?
...
+26 -2
View File
@@ -30,6 +30,7 @@ const int* tileLocalTextureOffsets;
static pixel_t colourMap_TT[COLOURMAPSIZE];
static pixel_t* scalelight_TT[LIGHTLEVELS][MAXLIGHTSCALE];
static pixel_t* zlight_TT[LIGHTLEVELS][MAXLIGHTZ];
extern "C"
__SUPER__
@@ -80,6 +81,7 @@ void IPU_R_InitTextureTile(unsigned* progBuf, int progBufSize, const pixel_t* co
// Next, precompute light scales from the colourmap. This normally happens in R_ExecuteSetViewSize
memcpy(colourMap_TT, colourMapBuf, sizeof(colourMap_TT));
// Firstly do scalelight_TT, which is used for cols
for (int i = 0; i < LIGHTLEVELS; i++) {
int startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS;
for (int j = 0; j < MAXLIGHTSCALE; j++) {
@@ -94,6 +96,23 @@ void IPU_R_InitTextureTile(unsigned* progBuf, int progBufSize, const pixel_t* co
scalelight_TT[i][j] = colourMap_TT + level * 256;
}
}
// Next do zlight_TT, which is used for spans
for (int i = 0; i < LIGHTLEVELS; i++) {
int startmap = ((LIGHTLEVELS - 1 - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS;
for (int j = 0; j < MAXLIGHTZ; j++) {
int scale = FixedDiv((SCREENWIDTH / 2 * FRACUNIT), (j + 1) << LIGHTZSHIFT);
scale >>= LIGHTSCALESHIFT;
int level = startmap - scale / DISTMAP;
if (level < 0)
level = 0;
if (level >= NUMCOLORMAPS)
level = NUMCOLORMAPS - 1;
zlight_TT[i][j] = colourMap_TT + level * 256;
}
}
}
extern "C"
@@ -135,19 +154,24 @@ void IPU_R_FulfilColumnRequest(unsigned* progBuf, unsigned char* textureBuf, uns
unsigned position = req->position;
unsigned step = req->step;
unsigned count = req->count;
unsigned lightNum = req->lightNum;
unsigned lightScale = req->lightScale;
ds_colormap = zlight_TT[lightNum][lightScale];
// Do the render loop for this line of pixels
do {
// Does 6 levels of indentation count as code smell?
unsigned ytemp = (position >> 4) & 0x0fc0;
unsigned xtemp = (position >> 26);
int spot = xtemp | ytemp;
*dest++ = texture[spot]; // LATER: ds_colormap[texture[spot]];
*dest++ = ds_colormap[texture[spot]];
position += step;
} while (count--);
}
} else {
// Is a Column request
unsigned lightNum = incomingRequest->colRequest.lightNum;
unsigned columnOffset = incomingRequest->colRequest.columnOffset;
unsigned lightNum = incomingRequest->colRequest.lightNum;
unsigned lightScale = incomingRequest->colRequest.lightScale;
byte* src = &texture[columnOffset];
pixel_t* dc_colourmap = scalelight_TT[lightNum][lightScale];
+1 -1
View File
@@ -22,7 +22,7 @@ typedef struct {
typedef struct {
unsigned position, step;
unsigned char count, lightNum;
unsigned char count, lightNum, lightScale;
} IPUSpanRequest_t;
typedef struct {
+7 -1
View File
@@ -615,29 +615,35 @@ void IPURequest_R_DrawSpan(void) {
return;
}
// All requests in batch should share a texture
// If not, dispatch old batch first
if (requestBatch.numSpanRequests > 0 && requestBatch.texture != flatnum) {
IPURequest_R_DrawSpan_FulfillBatch();
}
requestBatch.texture = flatnum;
// The response is fixed size, so send the existing batch if there's
// no space to fulfil the next request
// no space to fulfil this next request in the same response.
int count = ds_x2 - ds_x1;
if (spanBatchTotalCount + count > IPUTEXTURECACHELINESIZE * sizeof(int)) {
IPURequest_R_DrawSpan_FulfillBatch();
}
// Serialise request
IPUSpanRequest_t* spanRequest = &requestBatch.spanRequests[requestBatch.numSpanRequests];
spanRequest->position = ((ds_xfrac << 10) & 0xffff0000) | ((ds_yfrac >> 6) & 0x0000ffff);
spanRequest->step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0x0000ffff);
spanRequest->count = count;
spanRequest->lightNum = lightnum;
spanRequest->lightScale = walllightindex;
// Record where the response should be written to when it is fulfilled
spanDests[requestBatch.numSpanRequests] = ylookup[ds_y] + columnofs[ds_x1];
spanBatchTotalCount += count;
requestBatch.numSpanRequests += 1;
// Send full batches
if (requestBatch.numSpanRequests >= IPUMAXSPANREQUESTBATCHSIZE) {
IPURequest_R_DrawSpan_FulfillBatch();
}
+5 -2
View File
@@ -102,9 +102,10 @@ int viewangletox[FINEANGLES / 2];
// from clipangle to -clipangle.
angle_t xtoviewangle[SCREENWIDTH + 1];
// lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];// JOSEF: This lives on texture tile instead
// JOSEF: These live on the texture tiles now
// lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
// lighttable_t *scalelightfixed[MAXLIGHTSCALE];
lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // JOSEF: TODO (on texture/flats tile?)
// lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
// bumped light from gun blasts
int extralight;
@@ -757,6 +758,8 @@ void R_SetupFrame(player_t *player) {
if (player->fixedcolormap) {
printf("JOSEF: Warning: Fixed colourmap being used, need to implement that on texture tiles (send them a special value?)");
fixedcolormap = 0; // JOSEF
// fixedcolormap = colormaps + player->fixedcolormap * 256; // LATER
// walllights = scalelightfixed; // LATER
+7 -8
View File
@@ -131,7 +131,7 @@ void R_MapPlane(int y, int x1, int x2) {
angle_t angle;
fixed_t distance;
fixed_t length;
unsigned index;
// unsigned index; // JOSEF: store in walllightindex instead
if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) {
printf("ERROR: R_MapPlane: %d, %d at %d", x1, x2, y);
@@ -153,18 +153,16 @@ void R_MapPlane(int y, int x1, int x2) {
ds_xfrac = viewx + FixedMul(finecosine[angle], length);
ds_yfrac = -viewy - FixedMul(finesine[angle], length);
/* LATER
if (fixedcolormap)
ds_colormap = fixedcolormap;
else {
index = distance >> LIGHTZSHIFT;
walllightindex = distance >> LIGHTZSHIFT;
if (index >= MAXLIGHTZ)
index = MAXLIGHTZ - 1;
if (walllightindex >= MAXLIGHTZ)
walllightindex = MAXLIGHTZ - 1;
ds_colormap = planezlight[index];
// ds_colormap = planezlight[index]; // JOSEF: LATER, store this in lightscale
}
*/
ds_y = y;
ds_x1 = x1;
@@ -393,7 +391,8 @@ void R_DrawPlanes(void) {
if (lightnum < 0)
lightnum = 0;
// // planezlight = zlight[light]; // Texture tiles are in charge of scaling by light
// JOSEF: Texture tiles are in charge of scaling by lightnum now
// planezlight = zlight[lightnum];
pl->top[pl->maxx + 1] = 0xff;
pl->top[pl->minx - 1] = 0xff;