目标:(九十四)中的问题175
效果如下:
思路如下:
绘制瓦片编号采用glsl着色器实现,由于glsl不能直接显示数字,这里将数字变为纹理图片,通过组合数字纹理图片,达到显示数字的目的。瓦片编号是0..9和/十一个符号组成的,纹理图片需要包含这些数字符号。
步骤如下:
1、生成数字、分隔符的纹理图片。
int imagePixelSize=256;//图片的像素大小,指宽度,每个瓦片的像素大小为256*256
int charactorNum=11;//图片中字符的个数
int charactorPixelSizeW=10;//图片中字符的宽度
QFont font("宋体",35,QFont::Bold,true);
font.setBold(false);//加粗
font.setItalic(false);
QFontMetrics metrics(font);
int fh=metrics.height();
int fw=metrics.width("0");
double scale=fw*1.0/fh;
int charactorPixelSizeH=charactorPixelSizeW/scale;
font.setPixelSize(charactorPixelSizeH);//改变字体大小
osg::ref_ptr<osg::Texture2D> numTexture = new osg::Texture2D;
numTexture->setDataVariance(osg::Object::DYNAMIC);
osg::Image* numImage = new osg::Image;
GLenum pixelFormat = GL_RGBA;
numImage->allocateImage(imagePixelSize, charactorPixelSizeH, 1, pixelFormat, GL_UNSIGNED_BYTE);
memset(numImage->data(), 0, numImage->getImageSizeInBytes());
if (!numImage)
{
std::cout<<"load texture failed !"<<std::endl;
return -1;
}
numTexture->setImage(numImage);
QSize size(256,charactorPixelSizeH); //指定图片大小;
QImage image1(size,QImage::Format_ARGB32); //以ARGB32格式构造一个QImage,
//qimage的bit顺为 b g r a
image1.fill(qRgba(0,255,0,0));//填充图片背景
QPainter painter(&image1); //为这个QImage构造一个QPainter
painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
QPen pen = painter.pen();
pen.setColor(Qt::red);
painter.setPen(pen);
painter.setFont(font);
painter.drawText(image1.rect(),Qt::AlignLeft,"0123456789/");
int byteLine=image1.bytesPerLine();
int height=charactorPixelSizeH,width=imagePixelSize;
for(int i=0;i<height;i++){
for(int j=0;j<width;j++){
int r,g,b,a;
r=image1.bits()[i*byteLine+j*4+2];
*(numImage->data(j, height-i-1) + 0) = r;
g=image1.bits()[i*byteLine+j*4+1];
*(numImage->data(j, height-i-1) + 1) = g;
b=image1.bits()[i*byteLine+j*4];
*(numImage->data(j, height-i-1) + 2) = b;
a=image1.bits()[i*byteLine+j*4+3];
*(numImage->data(j, height-i-1) + 3) = a;
}
}
2、将纹理上传到着色器
//与osgearth用到的纹理单元保持一致,不要随意分配
int unit;
Rexter->getResources()->reserveTextureImageUnit( unit, "Tile XYZ" );
osg::Uniform* tileXYZUniform=new osg::Uniform("tile_xyz", unit);
surfaceStateSet->addUniform(tileXYZUniform);
surfaceStateSet->setTextureAttributeAndModes(unit,numTexture.get(),osg::StateAttribute::ON);
3、生成渲染瓦片编号的片段着色器
uniform sampler2D tile_xyz;
int xLen,yLen,zLen;
int calDigitalNum(int x){
if(x<0) return 0;
if(x==0) return 1;
int num=0;
num=int(log2(float(x))/log2(10.0));
return num+1;
}
vec4 drawDigital(int x,int len,vec4 color){
for(int i=len-1;i>=0;i--){//from high pos to low pos
if(oe_layer_tilec.s>curStartC.s && oe_layer_tilec.s<curEndC.s && oe_layer_tilec.t>curStartC.t && oe_layer_tilec.t<curEndC.t){
int i1=int(floor(pow(10.0,float(i))+0.5));
int i2=i1*10;
int index=int(mod(float(x),float(i2))/float(i1));
vec2 relativeC=oe_layer_tilec.st-curStartC.st;
vec4 numT = texture(tile_xyz,vec2(relativeC.s+tile_xyzW*index,relativeC.t/tile_xyzH));
if(numT.w>0){
color=numT;
}
}
curStartC.s=curStartC.s+tile_xyzW;
curEndC.s=curEndC.s+tile_xyzW;
}
return color;
}
vec4 drawSeprator(vec4 color){
int inde