osgEarth的Rex引擎原理分析(一二零)如何显示瓦片编号

目标:(九十四)中的问题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;
		curEn
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值