From 5a85fabfa618168a809d306ce67d43ec85efcdc4 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 12 Feb 2017 01:27:26 +0100 Subject: [PATCH] Add true color support to voxel renderer --- src/r_data/voxels.cpp | 46 ++++++++++++++++++++++ src/r_data/voxels.h | 10 +++++ src/swrenderer/r_swrenderer.cpp | 1 + src/swrenderer/things/r_voxel.cpp | 14 ++++++- src/swrenderer/viewport/r_spritedrawer.cpp | 15 ++++++- 5 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/r_data/voxels.cpp b/src/r_data/voxels.cpp index d81220ea8..4b8081288 100644 --- a/src/r_data/voxels.cpp +++ b/src/r_data/voxels.cpp @@ -392,6 +392,52 @@ FVoxel::~FVoxel() if (Palette != NULL) delete [] Palette; } +//========================================================================== +// +// Create true color version of the slab data +// +//========================================================================== + +void FVoxel::CreateBgraSlabData() +{ + assert(Palette != NULL); + + for (int i = 0; i < NumMips; ++i) + { + int size = Mips[i].OffsetX[Mips[i].SizeX]; + if (size <= 0) continue; + + Mips[i].SlabDataBgra.Resize(size); + + kvxslab_t *src = (kvxslab_t*)Mips[i].SlabData; + kvxslab_bgra_t *dest = (kvxslab_bgra_t*)&Mips[i].SlabDataBgra[0]; + + while (size >= 3) + { + dest->backfacecull = src->backfacecull; + dest->ztop = src->ztop; + dest->zleng = src->zleng; + + int slabzleng = src->zleng; + for (int j = 0; j < slabzleng; ++j) + { + int colorIndex = src->col[j]; + + uint32_t red = (Palette[colorIndex * 3 + 0] << 2) | (Palette[colorIndex * 3 + 0] >> 4); + uint32_t green = (Palette[colorIndex * 3 + 1] << 2) | (Palette[colorIndex * 3 + 1] >> 4); + uint32_t blue = (Palette[colorIndex * 3 + 2] << 2) | (Palette[colorIndex * 3 + 2] >> 4); + + dest->col[j] = 0xff000000 | (red << 16) | (green << 8) | blue; + } + slabzleng += 3; + + dest = (kvxslab_bgra_t *)((uint32_t *)dest + slabzleng); + src = (kvxslab_t *)((BYTE *)src + slabzleng); + size -= slabzleng; + } + } +} + //========================================================================== // // Remap the voxel to the game palette diff --git a/src/r_data/voxels.h b/src/r_data/voxels.h index 85095c52f..df5839836 100644 --- a/src/r_data/voxels.h +++ b/src/r_data/voxels.h @@ -15,6 +15,14 @@ struct kvxslab_t BYTE col[1/*zleng*/];// color data from top to bottom }; +struct kvxslab_bgra_t +{ + uint32_t ztop; // starting z coordinate of top of slab + uint32_t zleng; // # of bytes in the color array - slab height + uint32_t backfacecull; // low 6 bits tell which of 6 faces are exposed + uint32_t col[1/*zleng*/];// color data from top to bottom +}; + struct FVoxelMipLevel { FVoxelMipLevel(); @@ -27,6 +35,7 @@ struct FVoxelMipLevel int *OffsetX; short *OffsetXY; BYTE *SlabData; + TArray SlabDataBgra; }; struct FVoxel @@ -39,6 +48,7 @@ struct FVoxel FVoxel(); ~FVoxel(); + void CreateBgraSlabData(); void Remap(); void RemovePalette(); }; diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 561f0de43..0366886ce 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -187,6 +187,7 @@ void FSoftwareRenderer::RemapVoxels() { for (unsigned i=0; iCreateBgraSlabData(); Voxels[i]->Remap(); } } diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index ddb8d52c7..33e889c3f 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -538,6 +538,18 @@ namespace swrenderer } z2a[xxx] = MIN(z2, dadmost[lxt + xxx]); } + + const uint8_t *columnColors = col; + bool bgra = viewport->RenderTarget->IsBgra(); + if (bgra) + { + // The true color slab data array is identical, except its using uint32 instead of uint8. + // + // We can find the same slab column by calculating the offset from the start of SlabData + // and use that to offset into the BGRA version of the same data. + columnColors = (const uint8_t *)(&mip->SlabDataBgra[0] + (ptrdiff_t)(col - mip->SlabData)); + } + // Find top and bottom pixels that match and draw them as one strip for (int xxl = 0, xxr; xxl < stripwidth; ) { @@ -559,7 +571,7 @@ namespace swrenderer { drawerargs.SetDest(lxt + x, z1); drawerargs.SetCount(z2 - z1); - drawerargs.DrawVoxelColumn(thread, yplc[xxl], yinc, col, zleng); + drawerargs.DrawVoxelColumn(thread, yplc[xxl], yinc, columnColors, zleng); } /* diff --git a/src/swrenderer/viewport/r_spritedrawer.cpp b/src/swrenderer/viewport/r_spritedrawer.cpp index 0634bff70..cfcd3f285 100644 --- a/src/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/swrenderer/viewport/r_spritedrawer.cpp @@ -499,8 +499,19 @@ namespace swrenderer void SpriteDrawerArgs::DrawVoxelColumn(RenderThread *thread, fixed_t vPos, fixed_t vStep, const uint8_t *voxels, int voxelsCount) { - dc_iscale = vStep; - dc_texturefrac = vPos; + if (RenderViewport::Instance()->RenderTarget->IsBgra()) + { + double v = vPos / (double)voxelsCount / FRACUNIT; + double vstep = vStep / (double)voxelsCount / FRACUNIT; + dc_texturefrac = (int)(v * (1 << 30)); + dc_iscale = (int)(vstep * (1 << 30)); + } + else + { + dc_texturefrac = vPos; + dc_iscale = vStep; + } + dc_texturefracx = 0; dc_source = voxels; dc_source2 = 0;