BSP Textures

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

BSP Textures

Post by mh »

...and loading the first 4 miplevels of a BSP texture from the internally stored miplevels, rather than generating them with GL_MipMap. :D

I don't know if any other engine does this, but it's something that every other GL engine should do.
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
MDave
Posts: 76
Joined: Mon Dec 17, 2007 7:08 pm

Post by MDave »

Amen! :) I always wondered why ID never used them for glquake.
LordHavoc
Posts: 322
Joined: Fri Nov 05, 2004 3:12 am
Location: western Oregon, USA
Contact:

Post by LordHavoc »

MDave wrote:Amen! :) I always wondered why ID never used them for glquake.
Because they were an approximation of the truecolor mipmaps ID wished they could have used... like the ones glquake generates.

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).
But if using the paletted dithered mipmaps from the bsp, how about taking it two steps further:
  • 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.
It's a very interesting idea to use the bsp textures though, just not sure whether it would look better or worse :)
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

I'm not sure about the "identical look to software Quake" bit ( :lol: ) (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
MDave
Posts: 76
Joined: Mon Dec 17, 2007 7:08 pm

Post by MDave »

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:

Code: Select all

static	unsigned			upload[1024*512];
added to the top of GL_Upload32, and the rest below it here:

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);
		}
	}
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

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! :D
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
Post Reply