diff --git a/VisualStudio/Demos/osgpbuffer/osgpbuffer.dsp b/VisualStudio/Demos/osgpbuffer/osgpbuffer.dsp new file mode 100644 index 000000000..b7440ba89 --- /dev/null +++ b/VisualStudio/Demos/osgpbuffer/osgpbuffer.dsp @@ -0,0 +1,114 @@ +# Microsoft Developer Studio Project File - Name="Demo osgpbuffer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Demo osgpbuffer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "osgpbuffer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "osgpbuffer.mak" CFG="Demo osgpbuffer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Demo osgpbuffer - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Demo osgpbuffer - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Demo osgpbuffer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x414 /d "NDEBUG" +# ADD RSC /l 0x414 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 osgGLUT.lib osgDB.lib osgGA.lib osgUtil.lib osg.lib opengl32.lib glu32.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgpbuffer.exe" + +!ELSEIF "$(CFG)" == "Demo osgpbuffer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x414 /d "_DEBUG" +# ADD RSC /l 0x414 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 osgGLUTd.lib osgDBd.lib osgGAd.lib osgUtild.lib osgd.lib opengl32.lib glu32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../bin/osgpbufferd.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Demo osgpbuffer - Win32 Release" +# Name "Demo osgpbuffer - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgpbuffer\osgpbuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgpbuffer\pbuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgpbuffer\RenderToTextureStage.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgpbuffer\pbuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgpbuffer\RenderToTextureStage.h +# End Source File +# End Group +# End Target +# End Project diff --git a/VisualStudio/VisualStudio.dsw b/VisualStudio/VisualStudio.dsw index 13205c7ef..6947e47ee 100644 --- a/VisualStudio/VisualStudio.dsw +++ b/VisualStudio/VisualStudio.dsw @@ -705,6 +705,33 @@ Package=<4> ############################################################################### +Project: "Demo osgpbuffer"=.\Demos\osgpbuffer\osgpbuffer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name Core osg + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgDB + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgGA + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgGLUT + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgUtil + End Project Dependency +}}} + +############################################################################### + Project: "Demo osgshadowtexture"=.\Demos\osgshadowtexture\osgshadowtexture.dsp - Package Owner=<4> Package=<5> diff --git a/src/Demos/osglogo/osglogo.cpp b/src/Demos/osglogo/osglogo.cpp index 83ebd202a..d02b6c1b1 100644 --- a/src/Demos/osglogo/osglogo.cpp +++ b/src/Demos/osglogo/osglogo.cpp @@ -197,8 +197,8 @@ osg::Node* createLogo() osg::Matrix::translate(bb.center())); // add the box and globe to it. - xform->addChild(createBox(bb,chordRatio)); - //xform->addChild(createBoxNo5(bb,chordRatio)); + //xform->addChild(createBox(bb,chordRatio)); + xform->addChild(createBoxNo5(bb,chordRatio)); // add the transform to the group. group->addChild(xform); diff --git a/src/Demos/osgpbuffer/RenderToTextureStage.cpp b/src/Demos/osgpbuffer/RenderToTextureStage.cpp new file mode 100644 index 000000000..c24cb64b2 --- /dev/null +++ b/src/Demos/osgpbuffer/RenderToTextureStage.cpp @@ -0,0 +1,80 @@ +#include +//#include + +#include "RenderToTextureStage.h" + +//using namespace osg; +//using namespace osgUtil; + +// register a RenderToTextureStage prototype with the RenderBin prototype list. +//RegisterRenderBinProxy s_registerRenderToTextureStageProxy; + +MyRenderToTextureStage::MyRenderToTextureStage() +{ + _pbuffer = 0L; +} + +MyRenderToTextureStage::~MyRenderToTextureStage() +{ +} + +void MyRenderToTextureStage::reset() +{ + RenderStage::reset(); +} + +void MyRenderToTextureStage::draw(osg::State& state, osgUtil::RenderLeaf*& previous) +{ + if (_pbuffer && _texture.valid()) + { + // Create pbuffer texture + const osg::uint contextID = state.getContextID(); + GLuint& handle = _texture->getTextureObject(contextID); + if (handle == 0) + { + // Create dynamic texture, subload callback required. + _texture->apply(state); + } + + HDC hdc = ::wglGetCurrentDC(); + HGLRC hglrc = ::wglGetCurrentContext(); + + // Release pbuffer from "render to texture". + _pbuffer->releaseTexImage(); + + // Make the p-buffer's context current. + _pbuffer->makeCurrent(); + + // Render in p-buffer. + RenderStage::draw(state,previous); + + // restore window's context as current. + if (!::wglMakeCurrent(hdc, hglrc)) + { + assert(0); + } + + if (true /*_isRenderTextureSupported*/) + { + // transfer contents of p-buffer to texture + _pbuffer->bindTexImage(handle); + } + else + { +// TODO: +// _pbuffer->copyTexImage(state); + } + + } + else + { + RenderStage::draw(state,previous); + + // now copy the rendered image to attached texture. + if (_texture.valid()) + _texture->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + + if (_image.valid()) + _image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),GL_RGBA,GL_UNSIGNED_BYTE); + } +} diff --git a/src/Demos/osgpbuffer/RenderToTextureStage.h b/src/Demos/osgpbuffer/RenderToTextureStage.h new file mode 100644 index 000000000..16d9ec858 --- /dev/null +++ b/src/Demos/osgpbuffer/RenderToTextureStage.h @@ -0,0 +1,60 @@ +//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield +//Distributed under the terms of the GNU Library General Public License (LGPL) +//as published by the Free Software Foundation. + +#ifndef RENDERTOTEXTURESTAGE +#define RENDERTOTEXTURESTAGE 1 + +#include + +#include + +#include "pbuffer.h" + +// namespace osgUtil { + +/** + * RenderStage which copies the final image to an attached texture or image. + * Generally used as a pre-rendering stage. + */ +class /*OSGUTIL_EXPORT*/ MyRenderToTextureStage : public osgUtil::RenderStage +{ + public: + + + MyRenderToTextureStage(); + + virtual osg::Object* cloneType() const { return osgNew MyRenderToTextureStage(); } + virtual osg::Object* clone(const osg::CopyOp&) const { return osgNew MyRenderToTextureStage(); } // note only implements a clone of type. + virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=0L; } + virtual const char* libraryName() const { return ""; } + virtual const char* className() const { return "MyRenderToTextureStage"; } + + inline void setPBuffer(PBuffer* pbuffer) { _pbuffer = pbuffer; } + + virtual void reset(); + + void setTexture(osg::Texture2D* texture) { _texture = texture; } + osg::Texture2D* getTexture() { return _texture.get(); } + + void setImage(osg::Image* image) { _image = image; } + osg::Image* getImage() { return _image.get(); } + + virtual void draw(osg::State& state,osgUtil::RenderLeaf*& previous); + + public: + + + protected: + + virtual ~MyRenderToTextureStage(); + + osg::ref_ptr _texture; + osg::ref_ptr _image; + PBuffer* _pbuffer; +}; + +// } + +#endif + diff --git a/src/Demos/osgpbuffer/osgpbuffer.cpp b/src/Demos/osgpbuffer/osgpbuffer.cpp new file mode 100644 index 000000000..ee1f70fac --- /dev/null +++ b/src/Demos/osgpbuffer/osgpbuffer.cpp @@ -0,0 +1,659 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "RenderToTextureStage.h" +#include "pbuffer.h" + + +PBuffer* g_pPixelBuffer; + + +class MyAppCallback : public osg::NodeCallback +{ + public: + + MyAppCallback(osg::Node* subgraph): + _subgraph(subgraph) {} + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + // traverse the subgraph to update any nodes. + if (_subgraph.valid()) _subgraph->accept(*nv); + + // must traverse the Node's subgraph + traverse(node,nv); + } + + osg::ref_ptr _subgraph; +}; + +class MyCullCallback : public osg::NodeCallback +{ + public: + + MyCullCallback(osg::Node* subgraph,osg::Texture2D* texture): + _subgraph(subgraph), + _texture(texture) + { + } + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + + osgUtil::CullVisitor* cullVisitor = dynamic_cast(nv); + if (cullVisitor && _texture.valid() && _subgraph.valid()) + doPreRender(*node,*cullVisitor); + + // must traverse the subgraph + traverse(node,nv); + } + + void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv); + + osg::ref_ptr _subgraph; + osg::ref_ptr _texture; +}; + + +void MyCullCallback::doPreRender(osg::Node&, osgUtil::CullVisitor& cv) +{ + const osg::BoundingSphere& bs = _subgraph->getBound(); + if (!bs.valid()) + { + osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()< rtts = osgNew MyRenderToTextureStage; + rtts->setPBuffer(g_pPixelBuffer); + + // set up lighting. + // currently ignore lights in the scene graph itself.. + // will do later. + osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->_stage; + + // set up the background color and clear mask. + rtts->setClearColor(osg::Vec4(0.1f,0.9f,0.3f,1.0f)); + rtts->setClearMask(previous_stage->getClearMask()); + + // set up to charge the same RenderStageLighting is the parent previous stage. + rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); + + + // record the render bin, to be restored after creation + // of the render to text + osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); + + // set the current renderbin to be the newly created stage. + cv.setCurrentRenderBin(rtts.get()); + + float znear = 1.0f*bs.radius(); + float zfar = 3.0f*bs.radius(); + + // 2:1 aspect ratio as per flag geomtry below. + float top = 0.25f*znear; + float right = 0.5f*znear; + + znear *= 0.9f; + zfar *= 1.1f; + + // set up projection. + osg::Matrix* projection = osgNew osg::Matrix; + projection->makeFrustum(-right,right,-top,top,znear,zfar); + + cv.pushProjectionMatrix(projection); + + osg::Matrix* matrix = new osg::Matrix; + matrix->makeLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); + + cv.pushModelViewMatrix(matrix); + + osg::ref_ptr dummyState = osgNew osg::StateSet; + + cv.pushStateSet(dummyState.get()); + + { + // traverse the subgraph + _subgraph->accept(cv); + } + + cv.popStateSet(); + + // restore the previous model view matrix. + cv.popModelViewMatrix(); + + // restore the previous model view matrix. + cv.popProjectionMatrix(); + + // restore the previous renderbin. + cv.setCurrentRenderBin(previousRenderBin); + + if (rtts->_renderGraphList.size()==0 && rtts->_bins.size()==0) + { + // getting to this point means that all the subgraph has been + // culled by small feature culling or is beyond LOD ranges. + return; + } + + + + int height = 512; + int width = 512; + + + const osg::Viewport& viewport = *cv.getViewport(); + + // offset the impostor viewport from the center of the main window + // viewport as often the edges of the viewport might be obscured by + // other windows, which can cause image/reading writing problems. + int center_x = viewport.x()+viewport.width()/2; + int center_y = viewport.y()+viewport.height()/2; + + osg::Viewport* new_viewport = new osg::Viewport; +// new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); +new_viewport->setViewport(0,0,width,height); + rtts->setViewport(new_viewport); + + dummyState->setAttribute(new_viewport); + + // and the render to texture stage to the current stages + // dependancy list. + cv.getCurrentRenderBin()->_stage->addToDependencyList(rtts.get()); + + // if one exist attach texture to the RenderToTextureStage. + if (_texture.valid()) rtts->setTexture(_texture.get()); + + // if one exist attach image to the RenderToTextureStage. +// if (_image.valid()) rtts->setImage(_image.get()); + +} + + +// call back which cretes a deformation field to oscilate the model. +class MyGeometryCallback : + public osg::Drawable::AppCallback, + public osg::Drawable::AttributeFunctor +{ + public: + + MyGeometryCallback(const osg::Vec3& o, + const osg::Vec3& x,const osg::Vec3& y,const osg::Vec3& z, + double period,double xphase,double amplitude): + _firstCall(true), + _startTime(0.0), + _time(0.0), + _period(period), + _xphase(xphase), + _amplitude(amplitude), + _origin(o), + _xAxis(x), + _yAxis(y), + _zAxis(z) {} + + virtual void app(osg::NodeVisitor* nv,osg::Drawable* drawable) + { + const osg::FrameStamp* fs = nv->getFrameStamp(); + double referenceTime = fs->getReferenceTime(); + if (_firstCall) + { + _firstCall = false; + _startTime = referenceTime; + } + + _time = referenceTime-_startTime; + + drawable->accept(*this); + drawable->dirtyBound(); + + osg::Geometry* geometry = dynamic_cast(drawable); + if (geometry) + { + osgUtil::SmoothingVisitor::smooth(*geometry); + } + + } + + virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin) + { + if (type == osg::Drawable::VERTICES) + { + const float TwoPI=2.0f*osg::PI; + const float phase = -_time/_period; + + osg::Vec3* end = begin+count; + for (osg::Vec3* itr=begin;itr0)?_subloadImageWidth:texture.getImage()->s(); + GLsizei height = (_subloadImageHeight>0)?_subloadImageHeight:texture.getImage()->t(); + + + bool sizeChanged = false; + if (_textureWidth==0) + { + // need to calculate texture dimension + sizeChanged = true; + _textureWidth = 1; + for (; _textureWidth < (static_cast(_subloadTextureOffsetX) + width); _textureWidth <<= 1) {} + } + + if (_textureHeight==0) + { + // need to calculate texture dimension + sizeChanged = true; + _textureHeight = 1; + for (; _textureHeight < (static_cast(_subloadTextureOffsetY) + height); _textureHeight <<= 1) {} + } + + if (sizeChanged) + { + texture.setTextureSize(_textureWidth, _textureHeight); + } +*/ +#if 0 + // reserve appropriate texture memory + glTexImage2D(GL_TEXTURE_2D, 0, texture.getInternalFormat(), + _textureWidth, _textureHeight, 0, + (GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(), + NULL); + + + glPixelStorei(GL_UNPACK_ROW_LENGTH,texture.getImage()->s()); + + + glTexSubImage2D(GL_TEXTURE_2D, 0, + _subloadTextureOffsetX, _subloadTextureOffsetY, + width, height, + (GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(), + texture.getImage()->data(_subloadImageOffsetX,_subloadImageOffsetY)); + + glPixelStorei(GL_UNPACK_ROW_LENGTH,0); +#else + glTexImage2D( GL_TEXTURE_2D, 0, texture.getInternalFormat(), _textureWidth, _textureHeight, 0, GL_RGB, GL_FLOAT, 0 ); +#endif + } + + virtual void subload(const osg::Texture2D& texture,osg::State&) const + { + osg::notify(osg::INFO)<<"doing subload"<s()); + + glTexSubImage2D(GL_TEXTURE_2D, 0, + _subloadTextureOffsetX, _subloadTextureOffsetY, + (_subloadImageWidth>0)?_subloadImageWidth:texture.getImage()->s(), (_subloadImageHeight>0)?_subloadImageHeight:texture.getImage()->t(), + (GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(), + texture.getImage()->data(_subloadImageOffsetX,_subloadImageOffsetY)); + + glPixelStorei(GL_UNPACK_ROW_LENGTH,0); +#else +#endif + } + + + SubloadMode _subloadMode; + mutable GLsizei _textureWidth, _textureHeight; + GLint _subloadTextureOffsetX, _subloadTextureOffsetY; + GLint _subloadImageOffsetX, _subloadImageOffsetY; + GLsizei _subloadImageWidth, _subloadImageHeight; +}; + + + +osg::Node* createPreRenderSubGraph(osg::Node* subgraph) +{ + if (!subgraph) return 0; + + // create the quad to visualize. + osg::Geometry* polyGeom = new osg::Geometry(); + + polyGeom->setSupportsDisplayList(false); + + osg::Vec3 origin(0.0f,0.0f,0.0f); + osg::Vec3 xAxis(1.0f,0.0f,0.0f); + osg::Vec3 yAxis(0.0f,0.0f,1.0f); + osg::Vec3 zAxis(0.0f,-1.0f,0.0f); + float height = 100.0f; + float width = 200.0f; + int noSteps = 20; + + osg::Vec3Array* vertices = new osg::Vec3Array; + osg::Vec3 bottom = origin; + osg::Vec3 top = origin; top.z()+= height; + osg::Vec3 dv = xAxis*(width/((float)(noSteps-1))); + + osg::Vec2Array* texcoords = new osg::Vec2Array; + osg::Vec2 bottom_texcoord(0.0f,0.0f); + osg::Vec2 top_texcoord(0.0f,1.0f); + osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f); + + for(int i=0;ipush_back(top); + vertices->push_back(bottom); + top+=dv; + bottom+=dv; + + texcoords->push_back(top_texcoord); + texcoords->push_back(bottom_texcoord); + top_texcoord+=dv_texcoord; + bottom_texcoord+=dv_texcoord; + } + + + // pass the created vertex array to the points geometry object. + polyGeom->setVertexArray(vertices); + + polyGeom->setTexCoordArray(0,texcoords); + + osg::Vec4Array* colors = new osg::Vec4Array; + colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + polyGeom->setColorArray(colors); + polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL); + + polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,vertices->size())); + + // new we need to add the texture to the Drawable, we do so by creating a + // StateSet to contain the Texture StateAttribute. + osg::StateSet* stateset = new osg::StateSet; + + // set up the texture. +// osg::Image* image = new osg::Image; +// image->setInternalTextureFormat(GL_RGBA); + + // Dynamic texture filled with data from pbuffer. + osg::Texture2D* texture = new osg::Texture2D; + //texture->setSubloadMode(osg::Texture::IF_DIRTY); + texture->setInternalFormat(GL_RGB); + texture->setTextureSize(512,512); + texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); +texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP); +texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP); + texture->setSubloadCallback(new MyTextureSubloadCallback()); + stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); + + polyGeom->setStateSet(stateset); + + polyGeom->setAppCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f)); + + osg::Geode* geode = osgNew osg::Geode(); + geode->addDrawable(polyGeom); + + osg::Group* parent = new osg::Group; + + parent->setAppCallback(new MyAppCallback(subgraph)); + + parent->setCullCallback(new MyCullCallback(subgraph,texture)); + + parent->addChild(geode); + + return parent; +} + +void write_usage(std::ostream& out,const std::string& name) +{ + out << std::endl; + out <<"usage:"<< std::endl; + out <<" "< commandLine; + for(int i=1;iaddChild(loadedModel); + + osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f)); + loadedModelTransform->setAppCallback(nc); + + osg::Group* rootNode = new osg::Group(); +// rootNode->addChild(loadedModelTransform); + rootNode->addChild(createPreRenderSubGraph(loadedModelTransform)); + + + // add model to the viewer. + viewer.addViewport( rootNode ); + + + // register trackball, flight and drive. + viewer.registerCameraManipulator(new osgGA::TrackballManipulator); + viewer.registerCameraManipulator(new osgGA::FlightManipulator); + viewer.registerCameraManipulator(new osgGA::DriveManipulator); + + viewer.open(); + + g_pPixelBuffer = new PBuffer(512,512); + g_pPixelBuffer->initialize(); + + viewer.run(); + + delete g_pPixelBuffer; + + return 0; +} diff --git a/src/Demos/osgpbuffer/pbuffer.cpp b/src/Demos/osgpbuffer/pbuffer.cpp new file mode 100644 index 000000000..fc2a5ddee --- /dev/null +++ b/src/Demos/osgpbuffer/pbuffer.cpp @@ -0,0 +1,446 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "pbuffer.h" + +namespace osg { + bool isWGLExtensionSupported(const char *extension); +} + + +// WGL_ARB_pbuffer +static WGLCreatePBufferProc wglCreatePBuffer; +static WGLGetPBufferDCProc wglGetPBufferDC; +static WGLReleasePBufferDCProc wglReleasePBufferDC; +static WGLDestroyPBufferProc wglDestroyPBuffer; +static WGLQueryPBufferProc wglQueryPBuffer; + +// WGL_ARB_pixel_format +static WGLGetPixelFormatAttribivProc wglGetPixelFormatAttribiv; +static WGLGetPixelFormatAttribfvProc wglGetPixelFormatAttribfv; +static WGLChoosePixelFormatProc wglChoosePixelFormat; + +// WGL_ARB_render_texture +static WGLBindTexImageProc wglBindTexImage; +static WGLReleaseTexImageProc wglReleaseTexImage; +static WGLSetPbufferAttribProc wglSetPbufferAttrib; + + +#ifdef _WIN32 + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +typedef const char * (WINAPI * WGLGetExtensionsStringProc) (HDC hDC); +#endif + +#endif + +#ifdef _WIN32 +bool osg::isWGLExtensionSupported(const char *extension) +{ + + typedef std::set ExtensionSet; + static ExtensionSet s_extensionSet; + static const char* s_extensions = NULL; + static WGLGetExtensionsStringProc wglGetExtensionsString = (WGLGetExtensionsStringProc)osg::getGLExtensionFuncPtr("wglGetExtensionsStringARB"); + if (wglGetExtensionsString == NULL) return false; + if (s_extensions==NULL) + { + // get the extension list from OpenGL. + s_extensions = (const char*)wglGetExtensionsString(::wglGetCurrentDC()); + if (s_extensions==NULL) return false; + + // insert the ' ' delimiated extensions words into the extensionSet. + const char *startOfWord = s_extensions; + const char *endOfWord; + while ((endOfWord = strchr(startOfWord,' '))!=NULL) + { + s_extensionSet.insert(std::string(startOfWord,endOfWord)); + startOfWord = endOfWord+1; + } + if (*startOfWord!=0) s_extensionSet.insert(std::string(startOfWord)); + + osg::notify(osg::INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<~PBuffer(); + initialize(); + } +} + + +// This function actually does the creation of the p-buffer. +// It can only be called once a window has already been created. +void PBuffer::initialize() +{ + setupGLExtenions(); + + HDC hdc = wglGetCurrentDC(); + HGLRC hglrc = wglGetCurrentContext(); + + // Query for a suitable pixel format based on the specified mode. + std::vector iattributes; + std::vector fattributes; + + // P-buffer will be used with OpenGL + iattributes.push_back(WGL_SUPPORT_OPENGL_ARB); + iattributes.push_back(true); + + // Since we are trying to create a pbuffer, the pixel format we + // request (and subsequently use) must be "p-buffer capable". + iattributes.push_back(WGL_DRAW_TO_PBUFFER_ARB); + iattributes.push_back(true); + + // Bind to texture + iattributes.push_back(WGL_BIND_TO_TEXTURE_RGBA_ARB); + iattributes.push_back(true); + +//iattributes.push_back(WGL_ACCELERATION_ARB); +//iattributes.push_back(WGL_FULL_ACCELERATION_ARB); + + if (_RGB) + { + iattributes.push_back(WGL_PIXEL_TYPE_ARB); + iattributes.push_back(WGL_TYPE_RGBA_ARB); + + // We require a minimum of 8-bits for each R, G, B, and A. + iattributes.push_back(WGL_RED_BITS_ARB); + iattributes.push_back(8); + iattributes.push_back(WGL_GREEN_BITS_ARB); + iattributes.push_back(8); + iattributes.push_back(WGL_BLUE_BITS_ARB); + iattributes.push_back(8); + if (_minimumNumberAlphaBits > 0) + { + iattributes.push_back(WGL_ALPHA_BITS_ARB); + iattributes.push_back(_minimumNumberAlphaBits); + } + } + else + { + iattributes.push_back(WGL_PIXEL_TYPE_ARB); + iattributes.push_back(WGL_TYPE_COLORINDEX_ARB); + } + + iattributes.push_back(WGL_DOUBLE_BUFFER_ARB); + iattributes.push_back(_doubleBuffer); + + if (_minimumNumberDepthBits > 0) + { + iattributes.push_back(WGL_DEPTH_BITS_ARB); + iattributes.push_back(_minimumNumberDepthBits); + } + + if (_minimumNumberStencilBits > 0) + { + iattributes.push_back(WGL_STENCIL_BITS_ARB); + iattributes.push_back(_minimumNumberStencilBits); + } + + if (_minimumNumberAccumulationBits > 0) + { + iattributes.push_back(WGL_ACCUM_BITS_ARB); + iattributes.push_back(_minimumNumberAccumulationBits); + } + + // Terminate array + iattributes.push_back(0); + + + // Now obtain a list of pixel formats that meet these minimum requirements. + int format; + int pformat[MAX_PFORMATS]; + unsigned int nformats=0; + if ( !wglChoosePixelFormat( hdc, &iattributes.front(), &fattributes.front(), MAX_PFORMATS, pformat, &nformats ) ) + { + osg::notify(osg::FATAL)<< "pbuffer creation error: Couldn't find a suitable pixel format." < pbattr; + + // Texture format + pbattr.push_back(WGL_TEXTURE_FORMAT_ARB); + pbattr.push_back(WGL_TEXTURE_RGBA_ARB); +#if 1 + // Texture target + pbattr.push_back(WGL_TEXTURE_TARGET_ARB); + pbattr.push_back(WGL_TEXTURE_2D_ARB); +#else + // Cubemap + pbattr.push_back(WGL_TEXTURE_TARGET_ARB); + pbattr.push_back(WGL_TEXTURE_CUBE_MAP_ARB); + + // Cubemap face + pbattr.push_back(WGL_CUBE_MAP_FACE_ARB); + pbattr.push_back(WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB); +#endif + // Terminate array + pbattr.push_back(0); + + iattributes[0] = 0; + _hPBuffer = wglCreatePBuffer( hdc, format, _width, _height, &pbattr.front() ); + if ( !_hPBuffer ) + { + DWORD err = GetLastError(); + osg::notify(osg::FATAL)<< "pbuffer creation error: wglCreatePBufferARB() failed\n" < +#include "GL/gl.h" +#include +#include "GL/wglext.h" +#include +*/ + +#include + +#if defined(WIN32) + #define WIN32_LEAN_AND_MEAN + #include +#endif + + +#ifndef WGL_ARB_pbuffer +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 + +DECLARE_HANDLE(HPBUFFERARB); + +typedef HPBUFFERARB (WINAPI * WGLCreatePBufferProc) ( + HDC hDC, + int iPixelFormat, + int iWidth, + int iHeight, + const int *piAttribList); +typedef HDC (WINAPI * WGLGetPBufferDCProc) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * WGLReleasePBufferDCProc) ( + HPBUFFERARB hPbuffer, + HDC hDC); +typedef BOOL (WINAPI * WGLDestroyPBufferProc) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * WGLQueryPBufferProc) ( + HPBUFFERARB hPbuffer, + int iAttribute, + int *piValue); +#endif + + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +typedef BOOL (WINAPI * WGLGetPixelFormatAttribivProc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * WGLGetPixelFormatAttribfvProc) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * WGLChoosePixelFormatProc) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + + + +#ifndef WGL_ARB_render_texture +#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 +#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 +#define WGL_TEXTURE_FORMAT_ARB 0x2072 +#define WGL_TEXTURE_TARGET_ARB 0x2073 +#define WGL_MIPMAP_TEXTURE_ARB 0x2074 +#define WGL_TEXTURE_RGB_ARB 0x2075 +#define WGL_TEXTURE_RGBA_ARB 0x2076 +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 +#define WGL_TEXTURE_1D_ARB 0x2079 +#define WGL_TEXTURE_2D_ARB 0x207A +#define WGL_NO_TEXTURE_ARB 0x2077 +#define WGL_MIPMAP_LEVEL_ARB 0x207B +#define WGL_CUBE_MAP_FACE_ARB 0x207C +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 +#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 +#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 +#define WGL_FRONT_LEFT_ARB 0x2083 +#define WGL_FRONT_RIGHT_ARB 0x2084 +#define WGL_BACK_LEFT_ARB 0x2085 +#define WGL_BACK_RIGHT_ARB 0x2086 +#define WGL_AUX0_ARB 0x2087 +#define WGL_AUX1_ARB 0x2088 +#define WGL_AUX2_ARB 0x2089 +#define WGL_AUX3_ARB 0x208A +#define WGL_AUX4_ARB 0x208B +#define WGL_AUX5_ARB 0x208C +#define WGL_AUX6_ARB 0x208D +#define WGL_AUX7_ARB 0x208E +#define WGL_AUX8_ARB 0x208F +#define WGL_AUX9_ARB 0x2090 +#endif + +#ifndef WGL_ARB_render_texture +#define WGL_ARB_render_texture 1 +typedef BOOL (WINAPI * WGLBindTexImageProc) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * WGLReleaseTexImageProc) (HPBUFFERARB hPbuffer, int iBuffer); +typedef BOOL (WINAPI * WGLSetPbufferAttribProc) (HPBUFFERARB hPbuffer, const int * piAttribList); +#endif + + +#define MAX_PFORMATS 256 +#define MAX_ATTRIBS 32 + + + +class PBuffer +{ + private: + + HDC _hDC; // Handle to a device context. + HGLRC _hGLcontext; // Handle to a GL context. + HPBUFFERARB _hPBuffer; // Handle to a pbuffer. + int _width; + int _height; + + bool _doubleBuffer; + bool _RGB; + bool _shareLists; + unsigned int _minimumNumberDepthBits; + unsigned int _minimumNumberAlphaBits; + unsigned int _minimumNumberStencilBits; + unsigned int _minimumNumberAccumulationBits; + + bool _isPBufferSupported; + bool _isPixelFormatSupported; + bool _isRenderTextureSupported; + + public: + + PBuffer(const int width, const int height ); + ~PBuffer(); + void handleModeSwitch(); + void makeCurrent(); + void initialize(); + void bindTexImage(GLuint textureID); + void releaseTexImage(); + + + protected: + + void setupGLExtenions(); + +}; + +#endif \ No newline at end of file