Software Generating of Mip Maps

Started by
18 comments, last by AhmedSaleh 1 year ago

@Vilem Otte

So I just need to add first map as a copy of full source, then ? how do I create levels of it ?

Game Programming is the process of converting dead pictures to live ones .
Advertisement

First level of mipmap pyramid is the source image you load - you can't mipmap it from the original image (as it has the same dimensions). You calculate only from there up.

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

@Vilem Otte

Can you show me pseudocode or sample so that I can understand it myself or rewrite it ?

Game Programming is the process of converting dead pictures to live ones .

@joej

Can you help as always please ?

Game Programming is the process of converting dead pictures to live ones .

I'm quite in a hurry right now - but I'm using a code like this for CPU based mipmap generation (I removed some of additional features - they would only bring more confusion) - which generate mipmaps in place:

void LoaderDevIL::GenerateMipmaps(Image* image) const
{
	// Calculate number of mipmaps
	size_t dimLog2[2] = { 0 };
	size_t width = image->mWidth;
	size_t height = image->mHeight;

	while (width > 1)
	{
		width /= 2;
		dimLog2[0]++;
	}

	while (height > 1)
	{
		height /= 2;
		dimLog2[1]++;
	}

	image->mMipLevels = dimLog2[0] > dimLog2[1] ? dimLog2[1] : dimLog2[0];

	// Generate output buffer and fill in first layer (lowest mip level)
	image->mMipmaps = new unsigned char*[image->mMipLevels];
	image->mMipmaps[0] = image->mData;

	// Build mip maps
	width = image->mWidth;
	height = image->mHeight;
	for (size_t i = 1; i < image->mMipLevels; i++)
	{
		size_t newWidth = width / 2;
		newWidth = newWidth == 0 ? 1 : newWidth;
		size_t newHeight = height / 2;
		newHeight = newHeight == 0 ? 1 : newHeight;

		image->mMipmaps[i] = new unsigned char[newWidth * newHeight * 4];

		for (size_t j = 0; j < newHeight; j++)
		{
			for (size_t k = 0; k < newWidth; k++)
			{
				size_t current = (k + j * newWidth) * image->mChannels;

				size_t sample[4];
				sample[0] = (k * 2 + j * 2 * width) * image->mChannels;
				sample[1] = (k * 2 + 1 + j * 2 * width) * image->mChannels;
				sample[2] = (k * 2 + (j * 2 + 1) * width) * image->mChannels;
				sample[3] = (k * 2 + 1 + (j * 2 + 1) * width) * image->mChannels;

				unsigned int sum[4];
				sum[0] = (unsigned int)(image->mMipmaps[i - 1][sample[0] + 0]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[1] + 0]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[2] + 0]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[3] + 0]);
				sum[1] = (unsigned int)(image->mMipmaps[i - 1][sample[0] + 1]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[1] + 1]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[2] + 1]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[3] + 1]);
				sum[2] = (unsigned int)(image->mMipmaps[i - 1][sample[0] + 2]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[1] + 2]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[2] + 2]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[3] + 2]);
				sum[3] = (unsigned int)(image->mMipmaps[i - 1][sample[0] + 3]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[1] + 3]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[2] + 3]) +
					(unsigned int)(image->mMipmaps[i - 1][sample[3] + 3]);
				sum[0] /= 4;
				sum[1] /= 4;
				sum[2] /= 4;
				sum[3] /= 4;

				image->mMipmaps[i][current + 0] = sum[0];
				image->mMipmaps[i][current + 1] = sum[1];
				image->mMipmaps[i][current + 2] = sum[2];
				image->mMipmaps[i][current + 3] = sum[3];
			}
		}

		width = newWidth;
		height = newHeight;
	}
}

And Image struct will resemble something like this:

struct Image
{
	...

	size_t mWidth;
	size_t mHeight;
	size_t mBpp;
	size_t mChannels;
	size_t mMipLevels;
	unsigned char* mData;
	unsigned char** mMipmaps;

	...
};

Keep in mind that mBpp is BYTES per pixel, not bits. Width, height and channels are obvious. mMipLevels holds how many miplevels you have. mData points to memory holding bottom-most mip level in mipmap pyramid (i.e. the largest image), and mMipmaps holds mMipLevels count of pointers - each representing single mip level in mipmap pyramid (the one at index 0 should be the same as mData - i.e. the original image).

My current blog on programming, linux and stuff - http://gameprogrammerdiary.blogspot.com

@Vilem Otte

Thanks so much <3 !

I see that mBPP is not used at all ? and the above code is ported, but still crashes

One more question

image->mMipmaps[i] = new unsigned char[newWidth * newHeight * 4];

is 4 BPP ?

number of channgels is RGB ? or RGBA ? or RG ..etc ?

Game Programming is the process of converting dead pictures to live ones .

it works perfect with 32bits..I have images that are 16bits also, 64 bits .. how do I fix that ?

Game Programming is the process of converting dead pictures to live ones .

AhmedSaleh said:
mage->mMipmaps[i] = new unsigned char[newWidth * newHeight * 4]; is 4 BPP ? number of channgels is RGB ? or RGBA ? or RG ..etc ?

What's your analysis?

fixed everything Many thanks @vilem otte

Game Programming is the process of converting dead pictures to live ones .

This topic is closed to new replies.

Advertisement