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

