...and loading the first 4 miplevels of a BSP texture from the internally stored miplevels, rather than generating them with GL_MipMap.
I don't know if any other engine does this, but it's something that every other GL engine should do.
BSP Textures
BSP Textures
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
Because they were an approximation of the truecolor mipmaps ID wished they could have used... like the ones glquake generates.MDave wrote:Amen! I always wondered why ID never used them for glquake.
I don't see any advantage to using the palettized mipmaps.
DarkPlaces' only changes compared to glquake in mipmap loading are:
- uses a higher quality resampling algorithm, which makes scaled up textures look a lot better (r_lerpimages 0 can disable this).
- uses the GL_ARB_texture_non_power_of_two extension - which avoids the need to resample entirely on GF6/Radeon HD - giving a nice improvement to menu art quality as well as certain ingame textures, and especially model skins.
- disables mipmapping on model skins (r_lerpskins 1 can enable this).
- use GL_SGIS_texture_lod if supported to limit the mipmapping to only use the first 4 levels.
- add an option to force each surface to a single LOD based on distance, using GL_TEXTURE_MIN_LOD_SGIS and GL_TEXTURE_MAX_LOD_SGIS (same extension). This would allow people to use GL_NEAREST_MIPMAP_NEAREST, 4 mipmaps (from the bsp), GL_ARB_texture_non_power_of_two, and only one mipmap level per surface, thus giving an identical look to software Quake.
I'm not sure about the "identical look to software Quake" bit ( ) (why not just run software Quake if that's the objective?) but it does make a (fairly subtle) difference. Where I'm coming from is the colour balance that software Quake had, but which is totally missing from GLQuake. Fixing up lighting gets you part way there, this just brings you further along the road.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
I've tried to implement your example code it into glquake, but I'm not having much luck. I don't get any compiler warnings or errors, but it crashes when loading a map.
Sorry to sound like a pain
Here is what I've got:
added to the top of GL_Upload32, and the rest below it here:
Sorry to sound like a pain
Here is what I've got:
Code: Select all
static unsigned upload[1024*512];
Code: Select all
/*
if (mipmap)
{
int miplevel;
miplevel = 0;
while (scaled_width > 1 || scaled_height > 1)
{
GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
scaled_width >>= 1;
scaled_height >>= 1;
if (scaled_width < 1)
scaled_width = 1;
if (scaled_height < 1)
scaled_height = 1;
miplevel++;
glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
}
}
*/
if (mipmap)
{
int miplevel = 1;
// if it's an 8 bit texture coming from a BSP we handle it differently, as we want to take the first 4 (i.e.
// (next 3) miplevels from the BSP... this ensures that the colour balance correctly matches software quake
// if ((flags & TEX_BSP) && !(flags & TEX_32BIT))
// {
// BSP textures are ensured to be large enough to survive this...
for (; miplevel < 4; miplevel++)
{
// advance to next stored BSP mipmap
data += width * height;
// take down width and height
width >>= 1;
height >>= 1;
// take down scaled_width and scaled_height
scaled_width >>= 1;
scaled_height >>= 1;
// deal with texture resizing
if (width == scaled_width && height == scaled_height)
{
int i;
int size = width * height;
// upload is already set and valid, so we can copy it right in
for (i = 0; i < size; i++) upload[i] = d_8to24table[data[i]];
}
else
{
// resample the new data into upload (already set and valid here too), never a 32 bpp base
GL_ResampleTexture (data, width, height, upload, scaled_width, scaled_height);
}
// upload (don't increment miplevel for this one as the for loop does it for us)
glTexImage2D (GL_TEXTURE_2D, miplevel, GL_RGBA, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, upload);
}
// }
// BSP mipmapping sets up so that it will fall through correctly to here...
while (scaled_width > 1 || scaled_height > 1)
{
// generate our mipmaps
GL_MipMap ((byte *) upload, scaled_width, scaled_height);
// take down to next level
scaled_width >>= 1;
scaled_height >>= 1;
// never go < 1
if (scaled_width < 1) scaled_width = 1;
if (scaled_height < 1) scaled_height = 1;
glTexImage2D (GL_TEXTURE_2D, miplevel++, GL_RGBA, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, upload);
}
}
This will crash on regular GLQuake because it's only valid for textures coming from a BSP. Other textures don't store the additional miplevels. You'll need some way of identifying whether the texture is coming from a BSP in your GL_Upload32; I suggest dropping the mipmap and alpha parameters and using a single int as a flags parameter. Add some #defines and you're there!
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for