很久没更新博客了。额,一直想写这个来着。记得以前写过绘制三维标量场的文章,方法是找的渐变颜色纹理图片,然后用一维纹理坐标映射贴上去的。后面发现根本不需要去找图片,这种渐变色本来就是一种颜色空间的定义。请看hsv颜色模型 ,这种颜色模型类似于rgb,也是三个分量h(色调),s(饱和度),v(亮度)。h表示的绕圆锥的一周,也就是纯颜色的渐变,正是我们需要的东西。s表示从圆心到圆边缘的半径,0-1的范围,表示颜色纯度。v则是垂直的轴,表示亮度。如下图,我们要的就是绕圈一周的颜色渐变。
总体思路就是数值0-1,映射到hsv颜色空间的(0-360,1,255)。实现标量场的方法是,首先,将hsv的(0-360,1,255)转换为rgb,保存为一维数组。以该数组为数据,生成一维纹理,数值0-1作为纹理坐标,再贴图即可生成标量场。下面是用该方法生成标量场的相关代码。首先是构造一维纹理数组,然后用其生成1d纹理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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); int nRet = gluBuild1DMipmaps (GL_TEXTURE_1D, 4 , COLOR_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, colorMap.raw ()); if (nRet != 0 ) { return 0 ; } return 1 ; }
hsv2rgb的代码如下,从网上可以随便找个修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 PixelRGBA Hsv2Rgb (float H, float S, float V) { float R, G, B; int i; float f, p, q, t; if (S == 0 ) { R = G = B = V; return V4B (R, G, B, 255 ); } H /= 60 ; i = floor ( H ); f = H - i; 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: R = V; G = p; B = q; break; } return V4B (R, G, B, 255 ); }
剩下的事情就是使用BuildColorMapTexture生成1d纹理,然后将数值作为1d纹理坐标设置好就行了。下面是相关的效果图:
颜色空间转换生成纹理:
渐变纹理贴图:
不同的方法效果有区别,原因可能是贴图的数据更精细,而且同一范围比如0-0.3对应的颜色就可能不一致。马上要毕业了,工作内容是游戏开发,以后估计不会再更新读研期间类似的文章的了。