图形学基础 | Mipmap生成

首先从MIPMAP的原理说起,它是把一张贴图按照2的倍数进行缩小。直到1X1。
把缩小的图都存储起来。在渲染时,根据一个像素离眼睛为之的距离,来判断从一个合适的图层中取出texel颜色赋值给像素。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
如果贴图的基本尺寸是256x256像素的话,它mipmap就会有8个层级。
每个层级是上一层级的四分之一的大小,依次层级大小就是:128x128;64x64;32x32;16x16;8x8;4x4;2x2;1x1(一个像素)。
例如在一个场景中,渲染贴图需要填满的空间大小是40x40像素的话,如果没有三线性过滤,那32x32 会被放大显示,或者有三线性过滤,会在64x64和32x32之间切换。最简单的生成贴图的方法就是依次做平均,当然也可以用更加高级的算法。

C++生成代码

void generate_mipmaps(float gamma) {
		IUINT32** mipmaps = NULL;
		int num_mip_levels = logbase2ofx(this->width) + 1;
		this->datas_len = num_mip_levels;
		mipmaps = new IUINT32*[num_mip_levels];
		mipmaps[0] = datas[0];
		int mip_width = width;
		int mip_height = height;
		for (int mip_level = 1; mip_level < num_mip_levels; mip_level++) {
			mip_width = mip_width >> 1; // 除以2
			mip_height = mip_height >> 1; // 除以2
			// 开辟空间
			mipmaps[mip_level] = new IUINT32[mip_width*mip_height];
			// src
			IUINT32 *src_buffer = mipmaps[mip_level - 1];
			// dst
			IUINT32 *dest_buffer = mipmaps[mip_level];
			for (int x = 0; x < mip_width; x++) {
				for (int y = 0; y < mip_height; y++) {
					float r0,g0,b0,a0,
						r1, g1, b1, a1,
						r2, g2, b2, a2,
						r3, g3, b3, a3;
					// 平均值
					int r_avg, g_avg, b_avg, a_avg;
					IUINT32 c = src_buffer[(x * 2 + 0) + (y * 2 + 0) * 2 * mip_width];
					b0 = c & 0xff;
					g0 = (c >> 8) & 0xff;
					r0 = (c >> 16) & 0xff;
					a0 = (c >> 24) & 0xff;

					c = src_buffer[(x * 2 + 1) + (y * 2 + 0) * 2 * mip_width];
					b1 = c & 0xff;
					g1 = (c >> 8) & 0xff;
					r1 = (c >> 16) & 0xff;
					a1 = (c >> 24) & 0xff;

					c = src_buffer[(x * 2 + 0) + (y * 2 + 1) * 2 * mip_width];
					b2 = c & 0xff;
					g2 = (c >> 8) & 0xff;
					r2 = (c >> 16) & 0xff;
					a2 = (c >> 24) & 0xff;

					c = src_buffer[(x * 2 + 1) + (y * 2 + 1) * 2 * mip_width];
					b3 = c & 0xff;
					g3 = (c >> 8) & 0xff;
					r3 = (c >> 16) & 0xff;
					a3 = (c >> 24) & 0xff;

					r_avg = (IUINT32)(0.5f + gamma*(r0 + r1 + r2 + r3) / 4);
					g_avg = (IUINT32)(0.5f + gamma*(g0 + g1 + g2 + g3) / 4);
					b_avg = (IUINT32)(0.5f + gamma*(b0 + b1 + b2 + b3) / 4);
					a_avg = (IUINT32)(0.5f + gamma*(b0 + b1 + b2 + b3) / 4);

					int R = CMID(r_avg, 0, 255);
					int G = CMID(g_avg, 0, 255);
					int B = CMID(b_avg, 0, 255);
					int A = CMID(a_avg, 0, 255);

					// ARGB
					dest_buffer[y*mip_width + x] = (A << 24) | (R << 16) | (G << 8) | B;
				}
			}
		}
		
		datas = mipmaps;
		datas_len = num_mip_levels;
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值