IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    数值到颜色的自然映射

    远行发表于 2015-06-08 04:52:12
    love 0

    很久没更新博客了。额,一直想写这个来着。记得以前写过绘制三维标量场的文章,方法是找的渐变颜色纹理图片,然后用一维纹理坐标映射贴上去的。后面发现根本不需要去找图片,这种渐变色本来就是一种颜色空间的定义。请看hsv颜色模型,这种颜色模型类似于rgb,也是三个分量h(色调),s(饱和度),v(亮度)。h表示的绕圆锥的一周,也就是纯颜色的渐变,正是我们需要的东西。s表示从圆心到圆边缘的半径,0-1的范围,表示颜色纯度。v则是垂直的轴,表示亮度。如下图,我们要的就是绕圈一周的颜色渐变。

    hsv

    总体思路就是数值0-1,映射到hsv颜色空间的(0-360,1,255)。实现标量场的方法是,首先,将hsv的(0-360,1,255)转换为rgb,保存为一维数组。以该数组为数据,生成一维纹理,数值0-1作为纹理坐标,再贴图即可生成标量场。下面是用该方法生成标量场的相关代码。首先是构造一维纹理数组,然后用其生成1d纹理。

    int CTexture::BuildColorMapTexture()
    {
    		const int COLOR_SIZE = 240;//红到蓝
    		ImageRGBA colorMap(COLOR_SIZE, 1);
    
    		for (int i = 0; i < COLOR_SIZE; ++i)
    		{
    			colorMap.pixel(i, 0) = Hsv2Rgb(i, 1, 255);
    		}
    
    		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    		glGenTextures(1, &m;_uTexName);
    		glBindTexture(GL_TEXTURE_1D, m_uTexName);
    
    		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    
    		//生成2d的Mipmap纹理
    		int nRet = gluBuild1DMipmaps(GL_TEXTURE_1D, 4, COLOR_SIZE, GL_RGBA, GL_UNSIGNED_BYTE,
    			colorMap.raw());
    
    		if (nRet != 0)
    		{
    			return 0;
    		}
    
    		return 1;
    }
    

    hsv2rgb的代码如下,从网上可以随便找个修改。

    PixelRGBA Hsv2Rgb(float H, float S, float V)
    {
    		float R, G, B;
    
    		int i;
    		float f, p, q, t;
    		if(S == 0)
    		{
    			// achromatic (grey)
    			R = G = B = V;
    			return V4B(R, G, B, 255);
    		}
    
    		H /= 60; // sector 0 to 5
    		i = floor( H );
    		f = H - i; // factorial part of h
    		p = V * ( 1 - S );
    		q = V * ( 1 - S * f );
    		t = V * ( 1 - S * ( 1 - f ) );
    
    		switch( i )
    		{
    		case 0:
    			R = V;
    			G = t;
    			B = p;
    			break;
    		case 1:
    			R = q;
    			G = V;
    			B = p;
    			break;
    		case 2:
    			R = p;
    			G = V;
    			B = t;
    			break;
    		case 3:
    			R = p;
    			G = q;
    			B = V;
    			break;
    		case 4:
    			R = t;
    			G = p;
    			B = V;
    			break;
    		default: // case 5:
    			R = V;
    			G = p;
    			B = q;
    			break;
    		}
    
    		return V4B(R, G, B, 255);
    }
    

    剩下的事情就是使用BuildColorMapTexture生成1d纹理,然后将数值作为1d纹理坐标设置好就行了。下面是相关的效果图:

    颜色空间转换生成纹理:

    hvs

    渐变纹理贴图:

    texturetexture

    不同的方法效果有区别,原因可能是贴图的数据更精细,而且同一范围比如0-0.3对应的颜色就可能不一致。马上要毕业了,工作内容是游戏开发,以后估计不会再更新读研期间类似的文章的了。

    您可能也喜欢:

    使用GDI+加载多种格式的纹理

    OpenGL如何使用长宽非2次方的纹理

    纹理合成

    OpenGL立即模式必须先指定纹理坐标

    如何用OpenCV实现PCA降维
    无觅


沪ICP备19023445号-2号
友情链接