我们常用osgDB::readImage或者osg::Image::allocateImage()方式创建Image对象,

跟深一步的带Mipmap的Image怎样创建呢? 偶然在分析osgParticle::PrecipitationEffect.cpp中的代码时有所收获

不废话,直接贴代码

以下这段代码是申请一个带mipmap的宽高相同(size)的Image的方法,image的总大小totalSize的计算方法以及mipmapData中要存储的各级mipmap的大小

osg::Image* image = new osg::Image;

 osg::Image::MipmapDataType mipmapData;

unsigned int s = size;

unsigned int totalSize = 0;


unsigned i;


//C语言 n>>=1 中的>>=意思是先将变量n的各个二进制位顺序右移1位,最高位补二进制0,然后将这个结果再复制给n。

for(i=0; s>0; s>>=1, ++i)   

{


    if (i>0) mipmapData.push_back(totalSize);


    totalSize += s*s*4;   // 4 代表RGBA方式占4个字节

}

unsigned char* ptr = new unsigned char[totalSize];   

image->setImage(size, size, size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, ptr, osg::Image::USE_NEW_DELETE,1);   

image->setMipmapLevels(mipmapData);

s = size;

   // 填充image分级数据

    for(i=0; s>0; s>>=1, ++i)

    {

        fillSpotLightImage(ptr, centerColour, backgroudColour, s, power);

        ptr += s*s*4;

    }

return image;


static void fillSpotLightImage(unsigned char* ptr, const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)

{

    if (size==1)

    {

        float r = 0.5f;

        osg::Vec4 color = centerColour*r+backgroudColour*(1.0f-r);

        *ptr++ = (unsigned char)((color[0])*255.0f);

        *ptr++ = (unsigned char)((color[1])*255.0f);

        *ptr++ = (unsigned char)((color[2])*255.0f);

        *ptr++ = (unsigned char)((color[3])*255.0f);

        return;

    }


    float mid = (float(size)-1.0f)*0.5f;

    float div = 2.0f/float(size);

    for(unsigned int r=0;r<size;++r)

    {

        //unsigned char* ptr = image->data(0,r,0);

        for(unsigned int c=0;c<size;++c)

        {

            float dx = (float(c) - mid)*div;

            float dy = (float(r) - mid)*div;

            float r = powf(1.0f-sqrtf(dx*dx+dy*dy),power);

            if (r<0.0f) r=0.0f;

            osg::Vec4 color = centerColour*r+backgroudColour*(1.0f-r);

            *ptr++ = (unsigned char)((color[0])*255.0f);

            *ptr++ = (unsigned char)((color[1])*255.0f);

            *ptr++ = (unsigned char)((color[2])*255.0f);

            *ptr++ = (unsigned char)((color[3])*255.0f);

        }

    }

}