root/OpenSceneGraph/trunk/src/osg/ImageUtils.cpp @ 13205

Revision 13205, 23.9 kB (checked in by robert, 10 days ago)

Added shaders to support experimental shader based displacement mapping technique osgTerrain::ShaderTerrain?.

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <float.h>
15#include <string.h>
16
17#include <osg/Math>
18#include <osg/Notify>
19#include <osg/ImageUtils>
20#include <osg/Texture>
21
22namespace osg
23{
24
25struct FindRangeOperator
26{
27    FindRangeOperator():
28        _rmin(FLT_MAX),
29        _rmax(-FLT_MAX),
30        _gmin(FLT_MAX),
31        _gmax(-FLT_MAX),
32        _bmin(FLT_MAX),
33        _bmax(-FLT_MAX),
34        _amin(FLT_MAX),
35        _amax(-FLT_MAX) {}
36
37    float _rmin, _rmax, _gmin, _gmax, _bmin, _bmax, _amin, _amax;
38
39    inline void luminance(float l) { rgba(l,l,l,l); }
40    inline void alpha(float a) { rgba(1.0f,1.0f,1.0f,a); }
41    inline void luminance_alpha(float l,float a) { rgba(l,l,l,a); }
42    inline void rgb(float r,float g,float b) { rgba(r,g,b,1.0f);  }
43    inline void rgba(float r,float g,float b,float a)
44    {
45        _rmin = osg::minimum(r,_rmin);
46        _rmax = osg::maximum(r,_rmax);
47        _gmin = osg::minimum(g,_gmin);
48        _gmax = osg::maximum(g,_gmax);
49        _bmin = osg::minimum(b,_bmin);
50        _bmax = osg::maximum(b,_bmax);
51        _amin = osg::minimum(a,_amin);
52        _amax = osg::maximum(a,_amax);
53    }
54
55
56
57};
58
59struct OffsetAndScaleOperator
60{
61    OffsetAndScaleOperator(const osg::Vec4& offset, const osg::Vec4& scale):
62        _offset(offset),
63        _scale(scale) {}
64
65    osg::Vec4 _offset;
66    osg::Vec4 _scale;
67
68    inline void luminance(float& l) const { l= _offset.r() + l*_scale.r(); }
69    inline void alpha(float& a) const { a = _offset.a() + a*_scale.a(); }
70    inline void luminance_alpha(float& l,float& a) const
71    {
72        l= _offset.r() + l*_scale.r();
73        a = _offset.a() + a*_scale.a();
74    }
75    inline void rgb(float& r,float& g,float& b) const
76    {
77        r = _offset.r() + r*_scale.r();
78        g = _offset.g() + g*_scale.g();
79        b = _offset.b() + b*_scale.b();
80    }
81    inline void rgba(float& r,float& g,float& b,float& a) const
82    {
83        r = _offset.r() + r*_scale.r();
84        g = _offset.g() + g*_scale.g();
85        b = _offset.b() + b*_scale.b();
86        a = _offset.a() + a*_scale.a();
87    }
88};
89
90bool computeMinMax(const osg::Image* image, osg::Vec4& minValue, osg::Vec4& maxValue)
91{
92    if (!image) return false;
93
94    osg::FindRangeOperator rangeOp;
95    readImage(image, rangeOp);
96    minValue.r() = rangeOp._rmin;
97    minValue.g() = rangeOp._gmin;
98    minValue.b() = rangeOp._bmin;
99    minValue.a() = rangeOp._amin;
100
101    maxValue.r() = rangeOp._rmax;
102    maxValue.g() = rangeOp._gmax;
103    maxValue.b() = rangeOp._bmax;
104    maxValue.a() = rangeOp._amax;
105
106    return minValue.r()<=maxValue.r() &&
107           minValue.g()<=maxValue.g() &&
108           minValue.b()<=maxValue.b() &&
109           minValue.a()<=maxValue.a();
110}
111
112bool offsetAndScaleImage(osg::Image* image, const osg::Vec4& offset, const osg::Vec4& scale)
113{
114    if (!image) return false;
115
116    modifyImage(image,OffsetAndScaleOperator(offset, scale));
117
118    return true;
119}
120
121template<typename SRC, typename DEST>
122void _copyRowAndScale(const SRC* src, DEST* dest, int num, float scale)
123{
124    if (scale==1.0)
125    {
126        for(int i=0; i<num; ++i)
127        {
128            *dest = DEST(*src);
129            ++dest; ++src;
130        }
131    }
132    else
133    {
134        for(int i=0; i<num; ++i)
135        {
136            *dest = DEST(float(*src)*scale);
137            ++dest; ++src;
138        }
139    }
140}
141
142template<typename DEST>
143void _copyRowAndScale(const unsigned char* src, GLenum srcDataType, DEST* dest, int num, float scale)
144{
145    switch(srcDataType)
146    {
147        case(GL_BYTE):              _copyRowAndScale((char*)src, dest, num, scale); break;
148        case(GL_UNSIGNED_BYTE):     _copyRowAndScale((unsigned char*)src, dest, num, scale); break;
149        case(GL_SHORT):             _copyRowAndScale((short*)src, dest, num, scale); break;
150        case(GL_UNSIGNED_SHORT):    _copyRowAndScale((unsigned short*)src, dest, num, scale); break;
151        case(GL_INT):               _copyRowAndScale((int*)src, dest, num, scale); break;
152        case(GL_UNSIGNED_INT):      _copyRowAndScale((unsigned int*)src, dest, num, scale); break;
153        case(GL_FLOAT):             _copyRowAndScale((float*)src, dest, num, scale); break;
154    }
155}
156
157void _copyRowAndScale(const unsigned char* src, GLenum srcDataType, unsigned char* dest, GLenum dstDataType, int num, float scale)
158{
159    switch(dstDataType)
160    {
161        case(GL_BYTE):              _copyRowAndScale(src, srcDataType, (char*)dest, num, scale); break;
162        case(GL_UNSIGNED_BYTE):     _copyRowAndScale(src, srcDataType, (unsigned char*)dest, num, scale); break;
163        case(GL_SHORT):             _copyRowAndScale(src, srcDataType, (short*)dest, num, scale); break;
164        case(GL_UNSIGNED_SHORT):    _copyRowAndScale(src, srcDataType, (unsigned short*)dest, num, scale); break;
165        case(GL_INT):               _copyRowAndScale(src, srcDataType, (int*)dest, num, scale); break;
166        case(GL_UNSIGNED_INT):      _copyRowAndScale(src, srcDataType, (unsigned int*)dest, num, scale); break;
167        case(GL_FLOAT):             _copyRowAndScale(src, srcDataType, (float*)dest, num, scale); break;
168    }
169}
170
171struct RecordRowOperator
172{
173    RecordRowOperator(unsigned int num):_colours(num),_pos(0) {}
174
175    mutable std::vector<osg::Vec4>  _colours;
176    mutable unsigned int            _pos;
177
178    inline void luminance(float l) const { rgba(l,l,l,1.0f); }
179    inline void alpha(float a) const { rgba(1.0f,1.0f,1.0f,a); }
180    inline void luminance_alpha(float l,float a) const { rgba(l,l,l,a);  }
181    inline void rgb(float r,float g,float b) const { rgba(r,g,b,1.0f); }
182    inline void rgba(float r,float g,float b,float a) const { _colours[_pos++].set(r,g,b,a); }
183};
184
185struct WriteRowOperator
186{
187    WriteRowOperator():_pos(0) {}
188    WriteRowOperator(unsigned int num):_colours(num),_pos(0) {}
189
190    std::vector<osg::Vec4>  _colours;
191    mutable unsigned int    _pos;
192
193    inline void luminance(float& l) const { l = _colours[_pos++].r(); }
194    inline void alpha(float& a) const { a = _colours[_pos++].a(); }
195    inline void luminance_alpha(float& l,float& a) const { l = _colours[_pos].r(); a = _colours[_pos++].a(); }
196    inline void rgb(float& r,float& g,float& b) const { r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); }
197    inline void rgba(float& r,float& g,float& b,float& a) const {  r = _colours[_pos].r(); g = _colours[_pos].g(); b = _colours[_pos].b(); a = _colours[_pos++].a(); }
198};
199
200bool copyImage(const osg::Image* srcImage, int src_s, int src_t, int src_r, int width, int height, int depth,
201               osg::Image* destImage, int dest_s, int dest_t, int dest_r, bool doRescale)
202{
203    if ((src_s+width) > (dest_s + destImage->s()))
204    {
205        OSG_NOTICE<<"copyImage("<<srcImage<<", "<<src_s<<", "<< src_t<<", "<<src_r<<", "<<width<<", "<<height<<", "<<depth<<std::endl;
206        OSG_NOTICE<<"          "<<destImage<<", "<<dest_s<<", "<< dest_t<<", "<<dest_r<<", "<<doRescale<<")"<<std::endl;
207        OSG_NOTICE<<"   input width too large."<<std::endl;
208        return false;
209    }
210
211    if ((src_t+height) > (dest_t + destImage->t()))
212    {
213        OSG_NOTICE<<"copyImage("<<srcImage<<", "<<src_s<<", "<< src_t<<", "<<src_r<<", "<<width<<", "<<height<<", "<<depth<<std::endl;
214        OSG_NOTICE<<"          "<<destImage<<", "<<dest_s<<", "<< dest_t<<", "<<dest_r<<", "<<doRescale<<")"<<std::endl;
215        OSG_NOTICE<<"   input height too large."<<std::endl;
216        return false;
217    }
218
219    if ((src_r+depth) > (dest_r + destImage->r()))
220    {
221        OSG_NOTICE<<"copyImage("<<srcImage<<", "<<src_s<<", "<< src_t<<", "<<src_r<<", "<<width<<", "<<height<<", "<<depth<<std::endl;
222        OSG_NOTICE<<"          "<<destImage<<", "<<dest_s<<", "<< dest_t<<", "<<dest_r<<", "<<doRescale<<")"<<std::endl;
223        OSG_NOTICE<<"   input depth too large."<<std::endl;
224        return false;
225    }
226
227    float scale = 1.0f;
228    if (doRescale && srcImage->getDataType() != destImage->getDataType())
229    {
230        switch(srcImage->getDataType())
231        {
232            case(GL_BYTE):              scale = 1.0f/128.0f ; break;
233            case(GL_UNSIGNED_BYTE):     scale = 1.0f/255.0f; break;
234            case(GL_SHORT):             scale = 1.0f/32768.0f; break;
235            case(GL_UNSIGNED_SHORT):    scale = 1.0f/65535.0f; break;
236            case(GL_INT):               scale = 1.0f/2147483648.0f; break;
237            case(GL_UNSIGNED_INT):      scale = 1.0f/4294967295.0f; break;
238            case(GL_FLOAT):             scale = 1.0f; break;
239        }
240        switch(destImage->getDataType())
241        {
242            case(GL_BYTE):              scale *= 128.0f ; break;
243            case(GL_UNSIGNED_BYTE):     scale *= 255.0f; break;
244            case(GL_SHORT):             scale *= 32768.0f; break;
245            case(GL_UNSIGNED_SHORT):    scale *= 65535.0f; break;
246            case(GL_INT):               scale *= 2147483648.0f; break;
247            case(GL_UNSIGNED_INT):      scale *= 4294967295.0f; break;
248            case(GL_FLOAT):             scale *= 1.0f; break;
249        }
250    }
251
252    if (srcImage->getPixelFormat() == destImage->getPixelFormat())
253    {
254        //OSG_NOTICE<<"copyImage("<<srcImage<<", "<<src_s<<", "<< src_t<<", "<<src_r<<", "<<width<<", "<<height<<", "<<depth<<std::endl;
255        //OSG_NOTICE<<"          "<<destImage<<", "<<dest_s<<", "<< dest_t<<", "<<dest_r<<", "<<doRescale<<")"<<std::endl;
256
257        if (srcImage->getDataType() == destImage->getDataType() && !doRescale)
258        {
259            //OSG_NOTICE<<"   Compatible pixelFormat and dataType."<<std::endl;
260            for(int slice = 0; slice<depth; ++slice)
261            {
262                for(int row = 0; row<height; ++row)
263                {
264                    const unsigned char* srcData = srcImage->data(src_s, src_t+row, src_r+slice);
265                    unsigned char* destData = destImage->data(dest_s, dest_t+row, dest_r+slice);
266                    memcpy(destData, srcData, (width*destImage->getPixelSizeInBits())/8);
267                }
268            }
269            return true;
270        }
271        else
272        {
273            //OSG_NOTICE<<"   Compatible pixelFormat and incompatible dataType."<<std::endl;
274            for(int slice = 0; slice<depth; ++slice)
275            {
276                for(int row = 0; row<height; ++row)
277                {
278                    const unsigned char* srcData = srcImage->data(src_s, src_t+row, src_r+slice);
279                    unsigned char* destData = destImage->data(dest_s, dest_t+row, dest_r+slice);
280                    unsigned int numComponents = osg::Image::computeNumComponents(destImage->getPixelFormat());
281
282                    _copyRowAndScale(srcData, srcImage->getDataType(), destData, destImage->getDataType(), (width*numComponents), scale);
283                }
284            }
285
286            return true;
287        }
288    }
289    else
290    {
291        //OSG_NOTICE<<"copyImage("<<srcImage<<", "<<src_s<<", "<< src_t<<", "<<src_r<<", "<<width<<", "<<height<<", "<<depth<<std::endl;
292        //OSG_NOTICE<<"          "<<destImage<<", "<<dest_s<<", "<< dest_t<<", "<<dest_r<<", "<<doRescale<<")"<<std::endl;
293
294        RecordRowOperator readOp(width);
295        WriteRowOperator writeOp;
296
297        for(int slice = 0; slice<depth; ++slice)
298        {
299            for(int row = 0; row<height; ++row)
300            {
301
302                // reset the indices to beginning
303                readOp._pos = 0;
304                writeOp._pos = 0;
305
306                // read the pixels into readOp's _colour array
307                readRow(width, srcImage->getPixelFormat(), srcImage->getDataType(), srcImage->data(src_s,src_t+row,src_r+slice), readOp);
308
309                // pass readOp's _colour array contents over to writeOp (note this is just a pointer swap).
310                writeOp._colours.swap(readOp._colours);
311
312                modifyRow(width, destImage->getPixelFormat(), destImage->getDataType(), destImage->data(dest_s, dest_t+row,dest_r+slice), writeOp);
313
314                // return readOp's _colour array contents back to its rightful owner.
315                writeOp._colours.swap(readOp._colours);
316            }
317        }
318
319        return false;
320    }
321
322}
323
324
325struct SetToColourOperator
326{
327    SetToColourOperator(const osg::Vec4& colour):
328        _colour(colour) {}
329
330    inline void luminance(float& l) const { l = (_colour.r()+_colour.g()+_colour.b())*0.333333; }
331    inline void alpha(float& a) const { a = _colour.a(); }
332    inline void luminance_alpha(float& l,float& a) const { l = (_colour.r()+_colour.g()+_colour.b())*0.333333; a = _colour.a(); }
333    inline void rgb(float& r,float& g,float& b) const { r = _colour.r(); g = _colour.g(); b = _colour.b(); }
334    inline void rgba(float& r,float& g,float& b,float& a) const { r = _colour.r(); g = _colour.g(); b = _colour.b(); a = _colour.a(); }
335
336    osg::Vec4 _colour;
337};
338
339bool clearImageToColor(osg::Image* image, const osg::Vec4& colour)
340{
341    if (!image) return false;
342
343    modifyImage(image, SetToColourOperator(colour));
344
345    return true;
346}
347
348/** Search through the list of Images and find the maximum number of components used amoung the images.*/
349unsigned int maximimNumOfComponents(const ImageList& imageList)
350{
351    unsigned int max_components = 0;
352    for(osg::ImageList::const_iterator itr=imageList.begin();
353        itr!=imageList.end();
354        ++itr)
355    {
356        osg::Image* image = itr->get();
357        GLenum pixelFormat = image->getPixelFormat();
358        if (pixelFormat==GL_ALPHA ||
359            pixelFormat==GL_INTENSITY ||
360            pixelFormat==GL_LUMINANCE ||
361            pixelFormat==GL_LUMINANCE_ALPHA ||
362            pixelFormat==GL_RGB ||
363            pixelFormat==GL_RGBA ||
364            pixelFormat==GL_BGR ||
365            pixelFormat==GL_BGRA)
366        {
367            max_components = maximum(Image::computeNumComponents(pixelFormat), max_components);
368        }
369    }
370    return max_components;
371}
372
373osg::Image* createImage3D(const ImageList& imageList,
374                          GLenum desiredPixelFormat,
375                          int s_maximumImageSize,
376                          int t_maximumImageSize,
377                          int r_maximumImageSize,
378                          bool resizeToPowerOfTwo)
379{
380    OSG_INFO<<"createImage3D(..)"<<std::endl;
381    int max_s = 0;
382    int max_t = 0;
383    int total_r = 0;
384    for(osg::ImageList::const_iterator itr=imageList.begin();
385        itr!=imageList.end();
386        ++itr)
387    {
388        osg::Image* image = itr->get();
389        GLenum pixelFormat = image->getPixelFormat();
390        if (pixelFormat==GL_ALPHA ||
391            pixelFormat==GL_INTENSITY ||
392            pixelFormat==GL_LUMINANCE ||
393            pixelFormat==GL_LUMINANCE_ALPHA ||
394            pixelFormat==GL_RGB ||
395            pixelFormat==GL_RGBA ||
396            pixelFormat==GL_BGR ||
397            pixelFormat==GL_BGRA)
398        {
399            max_s = maximum(image->s(), max_s);
400            max_t = maximum(image->t(), max_t);
401            total_r += image->r();
402        }
403        else
404        {
405            OSG_INFO<<"Image "<<image->getFileName()<<" has unsuitable pixel format 0x"<< std::hex<< pixelFormat << std::dec << std::endl;
406        }
407    }
408
409    //bool remapRGBtoLuminance;
410    //bool remapRGBtoRGBA;
411
412    if (desiredPixelFormat==0)
413    {
414        unsigned int max_components = maximimNumOfComponents(imageList);
415        switch(max_components)
416        {
417        case(1):
418            OSG_INFO<<"desiredPixelFormat = GL_LUMINANCE" << std::endl;
419            desiredPixelFormat = GL_LUMINANCE;
420            break;
421        case(2):
422            OSG_INFO<<"desiredPixelFormat = GL_LUMINANCE_ALPHA" << std::endl;
423            desiredPixelFormat = GL_LUMINANCE_ALPHA;
424            break;
425        case(3):
426            OSG_INFO<<"desiredPixelFormat = GL_RGB" << std::endl;
427            desiredPixelFormat = GL_RGB;
428            break;
429        case(4):
430            OSG_INFO<<"desiredPixelFormat = GL_RGBA" << std::endl;
431            desiredPixelFormat = GL_RGBA;
432            break;
433        }
434    }
435    if (desiredPixelFormat==0) return 0;
436
437    // compute nearest powers of two for each axis.
438
439    int size_s = 1;
440    int size_t = 1;
441    int size_r = 1;
442
443    if (resizeToPowerOfTwo)
444    {
445        while(size_s<max_s && size_s<s_maximumImageSize) size_s*=2;
446        while(size_t<max_t && size_t<t_maximumImageSize) size_t*=2;
447        while(size_r<total_r && size_r<r_maximumImageSize) size_r*=2;
448    }
449    else
450    {
451        size_s = max_s;
452        size_t = max_t;
453        size_r = total_r;
454    }
455
456    // now allocate the 3d texture;
457    osg::ref_ptr<osg::Image> image_3d = new osg::Image;
458    image_3d->allocateImage(size_s,size_t,size_r,
459                            desiredPixelFormat,GL_UNSIGNED_BYTE);
460
461    unsigned int r_offset = (total_r<size_r) ? (size_r-total_r)/2 : 0;
462
463    int curr_dest_r = r_offset;
464
465    // copy across the values from the source images into the image_3d.
466    for(osg::ImageList::const_iterator itr=imageList.begin();
467        itr!=imageList.end();
468        ++itr)
469    {
470        osg::Image* image = itr->get();
471        GLenum pixelFormat = image->getPixelFormat();
472        if (pixelFormat==GL_ALPHA ||
473            pixelFormat==GL_LUMINANCE ||
474            pixelFormat==GL_INTENSITY ||
475            pixelFormat==GL_LUMINANCE_ALPHA ||
476            pixelFormat==GL_RGB ||
477            pixelFormat==GL_RGBA ||
478            pixelFormat==GL_BGR ||
479            pixelFormat==GL_BGRA)
480        {
481
482            int num_s = minimum(image->s(), image_3d->s());
483            int num_t = minimum(image->t(), image_3d->t());
484            int num_r = minimum(image->r(), (image_3d->r() - curr_dest_r));
485
486            unsigned int s_offset_dest = (image->s()<size_s) ? (size_s - image->s())/2 : 0;
487            unsigned int t_offset_dest = (image->t()<size_t) ? (size_t - image->t())/2 : 0;
488
489            copyImage(image, 0, 0, 0, num_s, num_t, num_r,
490                      image_3d.get(), s_offset_dest, t_offset_dest, curr_dest_r, false);
491
492            curr_dest_r += num_r;
493        }
494    }
495
496    return image_3d.release();
497}
498
499struct ModulateAlphaByLuminanceOperator
500{
501    ModulateAlphaByLuminanceOperator() {}
502
503    inline void luminance(float&) const {}
504    inline void alpha(float&) const {}
505    inline void luminance_alpha(float& l,float& a) const { a*= l; }
506    inline void rgb(float&,float&,float&) const {}
507    inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a *= l;}
508};
509
510osg::Image* createImage3DWithAlpha(const ImageList& imageList,
511            int s_maximumImageSize,
512            int t_maximumImageSize,
513            int r_maximumImageSize,
514            bool resizeToPowerOfTwo)
515{
516    GLenum desiredPixelFormat = 0;
517    bool modulateAlphaByLuminance = false;
518
519    unsigned int maxNumComponents = maximimNumOfComponents(imageList);
520    if (maxNumComponents==3)
521    {
522        desiredPixelFormat = GL_RGBA;
523        modulateAlphaByLuminance = true;
524    }
525
526    osg::ref_ptr<osg::Image> image = createImage3D(imageList,
527                                        desiredPixelFormat,
528                                        s_maximumImageSize,
529                                        t_maximumImageSize,
530                                        r_maximumImageSize,
531                                        resizeToPowerOfTwo);
532    if (image.valid())
533    {
534        if (modulateAlphaByLuminance)
535        {
536            modifyImage(image.get(), ModulateAlphaByLuminanceOperator());
537        }
538        return image.release();
539    }
540    else
541    {
542        return 0;
543    }
544}
545
546
547static void fillSpotLightImage(unsigned char* ptr, const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)
548{
549    if (size==1)
550    {
551        float r = 0.5f;
552        osg::Vec4 color = centerColour*r+backgroudColour*(1.0f-r);
553        *ptr++ = (unsigned char)((color[0])*255.0f);
554        *ptr++ = (unsigned char)((color[1])*255.0f);
555        *ptr++ = (unsigned char)((color[2])*255.0f);
556        *ptr++ = (unsigned char)((color[3])*255.0f);
557        return;
558    }
559
560    float mid = (float(size)-1.0f)*0.5f;
561    float div = 2.0f/float(size);
562    for(unsigned int r=0;r<size;++r)
563    {
564        //unsigned char* ptr = image->data(0,r,0);
565        for(unsigned int c=0;c<size;++c)
566        {
567            float dx = (float(c) - mid)*div;
568            float dy = (float(r) - mid)*div;
569            float r = powf(1.0f-sqrtf(dx*dx+dy*dy),power);
570            if (r<0.0f) r=0.0f;
571            osg::Vec4 color = centerColour*r+backgroudColour*(1.0f-r);
572            *ptr++ = (unsigned char)((color[0])*255.0f);
573            *ptr++ = (unsigned char)((color[1])*255.0f);
574            *ptr++ = (unsigned char)((color[2])*255.0f);
575            *ptr++ = (unsigned char)((color[3])*255.0f);
576        }
577    }
578}
579
580osg::Image* createSpotLightImage(const osg::Vec4& centerColour, const osg::Vec4& backgroudColour, unsigned int size, float power)
581{
582
583#if 0
584    osg::Image* image = new osg::Image;
585    unsigned char* ptr = image->data(0,0,0);
586    fillSpotLightImage(ptr, centerColour, backgroudColour, size, power);
587
588    return image;
589#else
590    osg::Image* image = new osg::Image;
591    osg::Image::MipmapDataType mipmapData;
592    unsigned int s = size;
593    unsigned int totalSize = 0;
594    unsigned i;
595    for(i=0; s>0; s>>=1, ++i)
596    {
597        if (i>0) mipmapData.push_back(totalSize);
598        totalSize += s*s*4;
599    }
600
601    unsigned char* ptr = new unsigned char[totalSize];
602    image->setImage(size, size, size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, ptr, osg::Image::USE_NEW_DELETE,1);
603
604    image->setMipmapLevels(mipmapData);
605
606    s = size;
607    for(i=0; s>0; s>>=1, ++i)
608    {
609        fillSpotLightImage(ptr, centerColour, backgroudColour, s, power);
610        ptr += s*s*4;
611    }
612
613    return image;
614#endif
615}
616
617
618
619struct ModulateAlphaByColorOperator
620{
621    ModulateAlphaByColorOperator(const osg::Vec4& colour):_colour(colour) { _lum = _colour.length(); }
622
623    osg::Vec4 _colour;
624    float _lum;
625
626    inline void luminance(float&) const {}
627    inline void alpha(float&) const {}
628    inline void luminance_alpha(float& l,float& a) const { a*= l*_lum; }
629    inline void rgb(float&,float&,float&) const {}
630    inline void rgba(float& r,float& g,float& b,float& a) const { a = (r*_colour.r()+g*_colour.g()+b*_colour.b()+a*_colour.a()); }
631};
632
633struct ReplaceAlphaWithLuminanceOperator
634{
635    ReplaceAlphaWithLuminanceOperator() {}
636
637    inline void luminance(float&) const {}
638    inline void alpha(float&) const {}
639    inline void luminance_alpha(float& l,float& a) const { a= l; }
640    inline void rgb(float&,float&,float&) const { }
641    inline void rgba(float& r,float& g,float& b,float& a) const { float l = (r+g+b)*0.3333333; a = l; }
642};
643
644osg::Image* colorSpaceConversion(ColorSpaceOperation op, osg::Image* image, const osg::Vec4& colour)
645{
646    switch(op)
647    {
648        case (MODULATE_ALPHA_BY_LUMINANCE):
649        {
650            OSG_NOTICE<<"doing conversion MODULATE_ALPHA_BY_LUMINANCE"<<std::endl;
651            osg::modifyImage(image, ModulateAlphaByLuminanceOperator());
652            return image;
653        }
654        case (MODULATE_ALPHA_BY_COLOR):
655        {
656            OSG_NOTICE<<"doing conversion MODULATE_ALPHA_BY_COLOUR"<<std::endl;
657            osg::modifyImage(image, ModulateAlphaByColorOperator(colour));
658            return image;
659        }
660        case (REPLACE_ALPHA_WITH_LUMINANCE):
661        {
662            OSG_NOTICE<<"doing conversion REPLACE_ALPHA_WITH_LUMINANCE"<<std::endl;
663            osg::modifyImage(image, ReplaceAlphaWithLuminanceOperator());
664            return image;
665        }
666        case (REPLACE_RGB_WITH_LUMINANCE):
667        {
668            OSG_NOTICE<<"doing conversion REPLACE_ALPHA_WITH_LUMINANCE"<<std::endl;
669            osg::Image* newImage = new osg::Image;
670            newImage->allocateImage(image->s(), image->t(), image->r(), GL_LUMINANCE, image->getDataType());
671            osg::copyImage(image, 0, 0, 0, image->s(), image->t(), image->r(),
672                        newImage, 0, 0, 0, false);
673            return newImage;
674        }
675        default:
676            return image;
677    }
678}
679
680
681
682}
Note: See TracBrowser for help on using the browser.