Hi Rene,

To do transparency work you'll need to enable OpenGL blending via:

  stateset->setMode(GL_BLEND, osg::StateAttribute::ON);


And is typically best also tell the OSG to depth sort the geometry too
by placing it in the transparent bin:

   stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

Robert.

On Sun, Oct 25, 2009 at 10:11 PM, Rene Bokhorst <[email protected]> wrote:
> Hi,
>
> I can't find the solution to my problem in any of the other posts, so I'm 
> writing in a new thread.
>
> For a lighting event here in Eindhoven (NL) our company is going to project 
> an image on a building using big ass beamers. It's an event which follows up 
> after Glow (http://www.gloweindhoven.nl/). Our idea was to have an 
> interactive application running between two users and the image projected by 
> the big ass beamer. We're going to capture the movements of two users that 
> are "throwing paint" at a building. All the user does is make the gesture, 
> and my application extrapolates the course the paint will fly at the 
> building. To round it off; a nice animated splash of paint is then projected 
> on the building.
>
> So I decided OSG would be a decent way to make this happen. Well... I got 
> most things in place. Someone supplied a sequence of transparent PNG images 
> for me to display. I used libpng to load them and put them in a osg::Image 
> object which I then proceed to put in an osg::ImageSequence object. I then 
> proceed to do some things I read on these forums to make the loaded PNG 
> appear as a transparent texture-on-a-quad in my view.
>
> And this actually works:
>
>
> Code:
>
> SplashContainer
> LichtStadEindhovenApp::Splash(
>        osg::Vec3f position,
>        osg::Vec2f scale,
>        DWORD color,
>        float speed,
>        int nsplash)
> {
>        SplashContainer cont;
>        osg::ref_ptr<osg::ImageSequence> tmpImageSequence = new 
> osg::ImageSequence();
>
>        for ( int k = 0 ; k < splash[nsplash]->size() ; k += 1 )
>        {
>                
> tmpImageSequence->addImage(LoadBitmapPNG(splash[nsplash]->operator 
> [](k).c_str(), color));
>        }
>
>        osg::ref_ptr<osg::Geode> geode = new osg::Geode();
>        osg::ref_ptr<osg::PositionAttitudeTransform> texPAT = new 
> osg::PositionAttitudeTransform();
>
>    osg::ref_ptr<osg::Geometry> quad1 = createTexturedQuadGeometry(
>        osg::Vec3d(0.0, 0.0, 0.0),                      //Center vector
>                osg::Vec3d(0.0, 0.0, scale.x()),        //Width vector
>        osg::Vec3d(scale.y(), 0.0, 0.0),        //Height vector
>        1.0,                                                            
> //Texture coordinates left
>        1.0);                                                           
> //Texture coordinatse top
>
>        texPAT->setPosition(position);
>
>        mNavTrans->addChild(texPAT.get());
>        texPAT->addChild(geode);
>        osg::Quat q(osg::DegreesToRadians(90.0f), osg::Vec3f(0.0f, 1.0f, 
> 0.0f));
>        texPAT->setAttitude(q);
>    geode->addDrawable(quad1.get());
>
>        osg::ref_ptr<osg::Texture2D> splashTexture = new 
> osg::Texture2D(tmpImageSequence);
>        osg::ref_ptr<osg::StateSet> stateset = quad1->getOrCreateStateSet();
>
>    stateset->setTextureAttributeAndModes(0, splashTexture.get(), 
> osg::StateAttribute::ON);
>    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
>
>        osg::ref_ptr<osg::BlendFunc> texture_blending_function = new 
> osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, 
> osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
>    stateset->setAttributeAndModes(texture_blending_function.get(), 
> osg::StateAttribute::ON);
>    stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
>
>        osg::ref_ptr<osg::AlphaFunc> alpha_transparency_function = new 
> osg::AlphaFunc();
>        
> alpha_transparency_function->setFunction(osg::AlphaFunc::ComparisonFunction::ALWAYS,
>  0.5);
>        stateset->setAttributeAndModes(alpha_transparency_function.get(), 
> osg::StateAttribute::ON );
>
>        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
>
>        quad1->setStateSet(stateset.get());
>
>        cont.geode = geode;
>        cont.imgseq = tmpImageSequence;
>        cont.pos = texPAT;
>        cont.f_incr = speed;
>        cont.f_time = 0.0f;
>        if ( nsplash == 1 || nsplash == 2 )
>                cont.bSaveLastFrame = false;
>        else
>                cont.bSaveLastFrame = true;
>
>        printf("ptr count 1: %d\n", tmpImageSequence->referenceCount());
>        m_vecSplashes.push_back(cont);
>        printf("ptr count 2: %d\n", 
> m_vecSplashes[m_vecSplashes.size()-1].imgseq->referenceCount());
>
>        nThrown += 1;
>
>        return cont;
> }
>
>
>
>
> My problem is is that I also want this quad to be 70% transparent. So that 
> when a new quad is placed in front of it, a little bit of the image farther 
> away remains visible.
>
> I've read several posts all of which say I should add this piece of code 
> somewhere.
>
>
> Code:
>
>        osg::Material* mat = 
> (osg::Material*)stateset->getAttribute(osg::StateAttribute::MATERIAL);
>        if ( !mat )
>                mat = new osg::Material();
>        mat->setAlpha(osg::Material::FRONT_AND_BACK, 0.70f);
>        stateset->setAttribute(mat, osg::StateAttribute::ON);
>
>
>
>
> however adding it to the function I described above does nothing to achieve 
> anything at all. My tree looks like this
>
>
> Code:
>
> //                                                             texPAT -- 
> geode -- quad
> //                                                           /
> // mRoot -- mPos -- mTrans -- mNavTrans
> //                                               \     \     \
> //                                                \     \      texPAT -- 
> geode -- quad
> //                                                 \      texPAT -- geode -- 
> quad
> //                                                   texPAT -- geode -- quad
>
>
>
>
> I tried setting the state of mNavTrans to make all underlying objects 
> transparent. That didn't work, but I think that's because the individual PNG 
> transparency code will override any changes made in the parent node.
>
> At the moment all my images are displayed with correct transparency in the 
> image. However I also want to achieve the effect where the quad on which that 
> image is printed also becomes transparent. Nothing I do seems to be able to 
> change that. Does anybody have any suggestions?
>
> Here's some more interesting code that might shed some more light on my 
> project.
>
>
> Code:
>
> osg::Image*
> LichtStadEindhovenApp::LoadBitmapPNG(
>        LPCTSTR szFile,
>        DWORD col)
> {
>        osg::Image* image = new osg::Image();
>        HBITMAP hbm = NULL;
>
>        bool retVal = false;
>        bool shouldWeLoad = true;
>        int size = 0;
>        int index = 0;
>
>        int i = 0;
>        while ( i < loadedPNGs.size() )
>        {
>                if ( strcmp(loadedPNGs[i].file.c_str(), szFile) == 0 )
>                {
>                        //printf("PNG's already loaded, do not load again!\n");
>                        shouldWeLoad = false;
>                        index = i;
>                        break;
>                }
>                i += 1;
>        }
>        if ( shouldWeLoad == true )
>        {
>                // check the header first
>                FILE *fp = fopen(szFile, "rb");
>                if (!fp)
>                        return false;
>                BYTE header[8];
>                fread(header, 1, 8, fp);
>                fseek(fp, 0, SEEK_END);
>                size = ftell(fp);
>                fclose(fp);
>                if (png_sig_cmp(header, 0, 8))
>                        return false;
>                // now allocate stuff
>                png_structp png_ptr = 
> png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, user_error_fn, 
> user_warning_fn);
>                if (!png_ptr)
>                        return false;
>                png_infop info_ptr = png_create_info_struct(png_ptr);
>                if (!info_ptr)
>                {
>                        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
> (png_infopp)NULL);
>                        return false;
>                }
>
>                png_infop end_info = png_create_info_struct(png_ptr);
>                if (!end_info)
>                {
>                        png_destroy_read_struct(&png_ptr, &info_ptr, 
> (png_infopp)NULL);
>                        return false;
>                }
>
>                fp = fopen(szFile, "rb");
>                if (fp == NULL)
>                        return NULL;
>
>                png_init_io(png_ptr, fp);
>
>                // should really use png_set_rows() to allocate space first, 
> rather than doubling up
>
>                png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | 
> PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING, NULL);
>
>                fclose(fp);
>
>                struct PNGInfo pinfo;
>                pinfo.file = std::string(szFile);
>                pinfo.end_info = end_info;
>                pinfo.info_ptr = info_ptr;
>                pinfo.png_ptr = png_ptr;
>                loadedPNGs.push_back(pinfo);
>                index = loadedPNGs.size() - 1;
>        }
>
>        png_bytep* row_pointers = png_get_rows(loadedPNGs[index].png_ptr, 
> loadedPNGs[index].info_ptr);
>
>        // now for a tonne of ugly DIB setup crap
>
>        int width = loadedPNGs[index].info_ptr->width;
>        int height = loadedPNGs[index].info_ptr->height;
>        int bpp = loadedPNGs[index].info_ptr->channels * 8;
>        int memWidth = (width * (bpp >> 3) + 3) & ~3;
>
>        LPBITMAPINFO lpbi = (LPBITMAPINFO) new char[sizeof(BITMAPINFOHEADER) + 
> (256 * sizeof(RGBQUAD))];
>
>        // create a greyscale palette
>        for (int a_i = 0; a_i < 256; a_i++)
>        {
>                lpbi->bmiColors[a_i].rgbRed = (BYTE)a_i;
>                lpbi->bmiColors[a_i].rgbGreen = (BYTE)a_i;
>                lpbi->bmiColors[a_i].rgbBlue = (BYTE)a_i;
>                lpbi->bmiColors[a_i].rgbReserved = (BYTE)a_i;
>        }
>
>        lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
>        lpbi->bmiHeader.biWidth = width;
>        lpbi->bmiHeader.biHeight = -height; // must be negative for top down
>        lpbi->bmiHeader.biPlanes = 1;
>        lpbi->bmiHeader.biBitCount = bpp;
>        lpbi->bmiHeader.biCompression = BI_RGB;
>        lpbi->bmiHeader.biSizeImage = memWidth * height;
>        lpbi->bmiHeader.biXPelsPerMeter = 0;
>        lpbi->bmiHeader.biYPelsPerMeter = 0;
>        lpbi->bmiHeader.biClrUsed = 0;
>        lpbi->bmiHeader.biClrImportant = 0;
>
>        BYTE * pixelData = NULL;
>        hbm = ::CreateDIBSection(NULL, lpbi, DIB_RGB_COLORS, (void 
> **)&pixelData, NULL, 0 );
>        if (hbm && pixelData)
>        {
>                // now copy the rows
>                for (int i = 0; i < height; i++)
>                {
>                        int bitesize = width * 
> loadedPNGs[index].info_ptr->channels;
>                        BYTE* buff = new BYTE[bitesize];
>                        memset(buff, 0, bitesize);
>                        memcpy(buff, row_pointers[i], bitesize);
>                        for ( int g = 0 ; g < width ; g += 1 )
>                        {
>                                buff[(g * 
> loadedPNGs[index].info_ptr->channels) + 0] = GetRValue(col);
>                                buff[(g * 
> loadedPNGs[index].info_ptr->channels) + 1] = GetGValue(col);
>                                buff[(g * 
> loadedPNGs[index].info_ptr->channels) + 2] = GetBValue(col);
>                                buff[(g * 
> loadedPNGs[index].info_ptr->channels) + 3] = 128;
>                        }
>                        memcpy(pixelData + memWidth * i, buff, bitesize);
>                        delete [] buff;
>                        buff = NULL;
>                }
>        }
>
>        // Create data to hold the destination image
>        BYTE* ptrDestImage = new unsigned char[width * height * 4];
>        BYTE* ptrSourceRow = NULL;
>        BYTE* ptrDestRow = NULL;
>
>        int iWidth = width;
>        int iHeight = height;
>
>        // Copy the System::Drawing::Bitmap instance over line by line - this 
> gets around the
>        // lack of stride support in the osg::Image.
>        for (int i = 0; i < iHeight; i++)
>        {
>                // Get the source row pointer
>                ptrSourceRow = pixelData + (i * (iWidth * 4));
>
>                // Get the destination row pointer
>                ptrDestRow = ptrDestImage + (i * (iWidth * 4));
>
>                // Copy the source row to the destination row
>                memcpy(ptrDestRow, ptrSourceRow, iWidth * 4);
>        }
>
>        // Set the data on the osg::Image
>        image->setImage(
>                iWidth,
>                iHeight,
>                1,
>                GL_RGBA,
>                GL_RGBA,
>                GL_UNSIGNED_BYTE,
>                ptrDestImage,
>                osg::Image::AllocationMode::USE_NEW_DELETE);
>
>        //delete [] ptrDestImage;
>        ::DeleteObject(hbm);
>
>        delete (char*) lpbi;
>
>        //png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
>
>        return image;
> }
>
>
>
>
> Thank you!
>
> Cheers,
> Rene[/code]
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=18680#18680
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> [email protected]
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to