Added Brede Johansen's osgpbuffer demo, currently only runs under Windows,

requires the equivilant glx support to be added.
This commit is contained in:
Robert Osfield 2002-12-05 14:30:57 +00:00
parent b0c4256e90
commit a91324e158
8 changed files with 1589 additions and 2 deletions

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -0,0 +1,80 @@
#include <cassert>
//#include <osgDB/ReadFile>
#include "RenderToTextureStage.h"
//using namespace osg;
//using namespace osgUtil;
// register a RenderToTextureStage prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderToTextureStage> 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);
}
}

View File

@ -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 <osg/Texture2D>
#include <osgUtil/RenderStage>
#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<const MyRenderToTextureStage*>(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<osg::Texture2D> _texture;
osg::ref_ptr<osg::Image> _image;
PBuffer* _pbuffer;
};
// }
#endif

View File

@ -0,0 +1,659 @@
#include <cassert>
#include <osg/GLExtensions>
#include <osg/Node>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Texture2D>
#include <osg/Stencil>
#include <osg/ColorMask>
#include <osg/Depth>
#include <osg/Billboard>
#include <osg/Material>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgUtil/TransformCallback>
#include <osgUtil/SmoothingVisitor>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgGLUT/glut>
#include <osgGLUT/Viewer>
#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<osg::Node> _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<osgUtil::CullVisitor*>(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<osg::Node> _subgraph;
osg::ref_ptr<osg::Texture2D> _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()<<std::endl;
return;
}
// create the render to texture stage.
osg::ref_ptr<MyRenderToTextureStage> 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<osg::StateSet> 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<osg::Geometry*>(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;itr<end;++itr)
{
osg::Vec3 dv(*itr-_origin);
osg::Vec3 local(dv*_xAxis,dv*_yAxis,dv*_zAxis);
local.z() = local.x()*_amplitude*
sinf(TwoPI*(phase+local.x()*_xphase));
(*itr) = _origin +
_xAxis*local.x()+
_yAxis*local.y()+
_zAxis*local.z();
}
}
}
bool _firstCall;
double _startTime;
double _time;
double _period;
double _xphase;
float _amplitude;
osg::Vec3 _origin;
osg::Vec3 _xAxis;
osg::Vec3 _yAxis;
osg::Vec3 _zAxis;
};
// Custom Texture subload callback, just acts the the standard subload modes in osg::Texture right now
// but code be used to define your own style callbacks.
class MyTextureSubloadCallback : public osg::Texture2D::SubloadCallback
{
public:
MyTextureSubloadCallback():
_subloadMode(AUTO),
_textureWidth(0),
_textureHeight(0),
_subloadTextureOffsetX(0),
_subloadTextureOffsetY(0),
_subloadImageOffsetX(0),
_subloadImageOffsetY(0),
_subloadImageWidth(0),
_subloadImageHeight(0)
{
}
enum SubloadMode {
OFF,
AUTO,
IF_DIRTY
};
/** Set the texture subload mode. */
inline void setSubloadMode(const SubloadMode mode) { _subloadMode = mode; }
/** Get the texture subload mode. */
inline const SubloadMode getSubloadMode() const { return _subloadMode; }
/** Set the texture subload texture offsets. */
inline void setSubloadTextureOffset(const int x, const int y)
{
_subloadTextureOffsetX = x;
_subloadTextureOffsetY = y;
}
/** Get the texture subload texture offsets. */
inline void getSubloadTextureOffset(int& x, int& y) const
{
x = _subloadTextureOffsetX;
y = _subloadTextureOffsetY;
}
/** Set the texture subload width. If width or height are zero then
* the repsective size value is calculated from the source image sizes. */
inline void setSubloadTextureSize(const int width, const int height)
{
_textureWidth = width;
_textureHeight = height;
}
/** Get the texture subload width. */
inline void getSubloadTextureSize(int& width, int& height) const
{
width = _textureWidth;
height = _textureHeight;
}
/** Set the subload image offsets. */
inline void setSubloadImageOffset(const int x, const int y)
{
_subloadImageOffsetX = x;
_subloadImageOffsetY = y;
}
/** Get the subload image offsets. */
inline void getSubloadImageOffset(int& x, int& y) const
{
x = _subloadImageOffsetX;
y = _subloadImageOffsetY;
}
/** Set the image subload width. If width or height are zero then
* the repsective size value is calculated from the source image sizes. */
inline void setSubloadImageSize(const int width, const int height)
{
_subloadImageWidth = width;
_subloadImageHeight = height;
}
/** Get the image subload width. */
inline void getSubloadImageSize(int& width, int& height) const
{
width = _subloadImageWidth;
height = _subloadImageHeight;
}
virtual void load(const osg::Texture2D& texture,osg::State&) const
{
osg::notify(osg::INFO)<<"doing load"<<std::endl;
/*
static bool s_SGIS_GenMipmap = osg::isGLExtensionSupported("GL_SGIS_generate_mipmap");
if (s_SGIS_GenMipmap && (texture.getFilter(osg::Texture2D::MIN_FILTER) != osg::Texture2D::LINEAR && texture.getFilter(osg::Texture2D::MIN_FILTER) != osg::Texture2D::NEAREST))
{
texture.setNumMipmapLevels(1); // will leave this at one, since the mipmap will be created internally by OpenGL.
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
}
else
{
texture.setNumMipmapLevels(1);
}
GLsizei width = (_subloadImageWidth>0)?_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<GLsizei>(_subloadTextureOffsetX) + width); _textureWidth <<= 1) {}
}
if (_textureHeight==0)
{
// need to calculate texture dimension
sizeChanged = true;
_textureHeight = 1;
for (; _textureHeight < (static_cast<GLsizei>(_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"<<std::endl;
#if 0
glPixelStorei(GL_UNPACK_ROW_LENGTH,texture.getImage()->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;i<noSteps;++i)
{
vertices->push_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 <<" "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
out << std::endl;
out <<"options:"<< std::endl;
out <<" -l libraryName - load plugin of name libraryName"<< std::endl;
out <<" i.e. -l osgdb_pfb"<< std::endl;
out <<" Useful for loading reader/writers which can load"<< std::endl;
out <<" other file formats in addition to its extension."<< std::endl;
out <<" -e extensionName - load reader/wrter plugin for file extension"<< std::endl;
out <<" i.e. -e pfb"<< std::endl;
out <<" Useful short hand for specifying full library name as"<< std::endl;
out <<" done with -l above, as it automatically expands to"<< std::endl;
out <<" the full library name appropriate for each platform."<< std::endl;
out <<std::endl;
out <<" -stereo - switch on stereo rendering, using the default of,"<< std::endl;
out <<" ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
out <<" environmental variable. See doc/stereo.html for "<< std::endl;
out <<" further details on setting up accurate stereo "<< std::endl;
out <<" for your system. "<< std::endl;
out <<" -stereo ANAGLYPHIC - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
out <<" -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
out <<std::endl;
out <<" -stencil - use a visual with stencil buffer enabled, this "<< std::endl;
out <<" also allows the depth complexity statistics mode"<< std::endl;
out <<" to be used (press 'p' three times to cycle to it)."<< std::endl;
out << std::endl;
}
int main( int argc, char **argv )
{
// initialize the GLUT
glutInit( &argc, argv );
if (argc<2)
{
write_usage(osg::notify(osg::NOTICE),argv[0]);
return 0;
}
// create the commandline args.
std::vector<std::string> commandLine;
for(int i=1;i<argc;++i) commandLine.push_back(argv[i]);
// initialize the viewer.
osgGLUT::Viewer viewer;
viewer.setWindowTitle(argv[0]);
// configure the viewer from the commandline arguments, and eat any
// parameters that have been matched.
viewer.readCommandLine(commandLine);
// configure the plugin registry from the commandline arguments, and
// eat any parameters that have been matched.
osgDB::readCommandLine(commandLine);
// load the nodes from the commandline arguments.
osg::Node* loadedModel = osgDB::readNodeFiles(commandLine);
if (!loadedModel)
{
// write_usage(osg::notify(osg::NOTICE),argv[0]);
return 1;
}
// create a transform to spin the model.
osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform;
loadedModelTransform->addChild(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;
}

View File

@ -0,0 +1,446 @@
#include <cstdio>
#include <set>
#include <vector>
#include <string>
#include <cassert>
#include <osg/GLExtensions>
#include <osg/Notify>
#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<std::string> 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:"<<std::endl;
for(ExtensionSet::iterator itr=s_extensionSet.begin();
itr!=s_extensionSet.end();
++itr)
{
osg::notify(osg::INFO)<<" "<<*itr<<std::endl;
}
}
// true if extension found in extensionSet.
bool result = s_extensionSet.find(extension)!=s_extensionSet.end();
if (result)
osg::notify(osg::INFO)<<"OpenGL WGL extension '"<<extension<<"' is supported."<<std::endl;
else
osg::notify(osg::INFO)<<"OpenGL WGL extension '"<<extension<<"' is not supported."<<std::endl;
return result;
}
#endif
PBuffer::PBuffer(const int width, const int height) :
_width(width),
_height(height),
_hDC(NULL),
_hGLcontext(NULL),
_hPBuffer(NULL)
{
_doubleBuffer = false;
_RGB = true;
_shareLists = false;
_minimumNumberDepthBits = 16;
_minimumNumberAlphaBits = 8;
_minimumNumberStencilBits = 0;
_minimumNumberAccumulationBits = 0;
}
PBuffer::~PBuffer()
{
if (_hPBuffer)
{
wglDeleteContext( _hGLcontext );
wglReleasePBufferDC( _hPBuffer, _hDC );
wglDestroyPBuffer( _hPBuffer );
}
}
// Check to see if the pbuffer was lost.
// If it was lost, destroy it and then recreate it.
void PBuffer::handleModeSwitch()
{
int lost = 0;
wglQueryPBuffer( _hPBuffer, WGL_PBUFFER_LOST_ARB, &lost );
if ( lost )
{
this->~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<int> iattributes;
std::vector<float> 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." <<std::endl;
exit( -1 );
}
format = pformat[0];
// Create the p-buffer.
std::vector<int> 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" <<std::endl;
switch (err)
{
case ERROR_INVALID_PIXEL_FORMAT:
osg::notify(osg::FATAL)<< "error: ERROR_INVALID_PIXEL_FORMAT\n" <<std::endl;
break;
case ERROR_NO_SYSTEM_RESOURCES:
osg::notify(osg::FATAL)<< "error: ERROR_NO_SYSTEM_RESOURCES\n" <<std::endl;
break;
case ERROR_INVALID_DATA:
osg::notify(osg::FATAL)<< "error: ERROR_INVALID_DATA\n" <<std::endl;
break;
}
exit( -1 );
}
// Get the device context.
_hDC = wglGetPBufferDC( _hPBuffer );
if ( !_hDC )
{
osg::notify(osg::FATAL)<< "pbuffer creation error: wglGetPBufferDC() failed\n" << std::endl;
exit( -1 );
}
// Create a gl context for the p-buffer.
_hGLcontext = wglCreateContext( _hDC );
if ( !_hGLcontext )
{
osg::notify(osg::FATAL)<< "pbuffer creation error: wglCreateContext() failed\n" << std::endl;
exit( -1 );
}
if( _shareLists )
{
if( !wglShareLists(hglrc, _hGLcontext) )
{
osg::notify(osg::FATAL)<< "pbuffer: wglShareLists() failed\n" << std::endl;
exit( -1 );
}
}
// Determine the actual width and height we were able to create.
wglQueryPBuffer( _hPBuffer, WGL_PBUFFER_WIDTH_ARB, &_width );
wglQueryPBuffer( _hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &_height );
osg::notify(osg::INFO)<< "PBuffer created " << _width << " x " << _height << "pbuffer."<< std::endl;
}
void PBuffer::releaseTexImage()
{
if(!wglReleaseTexImage( _hPBuffer, WGL_FRONT_LEFT_ARB ) )
{
assert(0);
}
}
void PBuffer::makeCurrent()
{
if ( !wglMakeCurrent( _hDC, _hGLcontext ) )
{
osg::notify(osg::FATAL)<< "PBuffer::makeCurrent() failed.\n"<< std::endl;
exit( -1 );
}
}
void PBuffer::bindTexImage(GLuint textureID)
{
glBindTexture(GL_TEXTURE_2D, textureID);
if(!::wglBindTexImage(_hPBuffer, WGL_FRONT_LEFT_ARB))
{
assert(0);
}
}
void PBuffer::setupGLExtenions()
{
#ifdef _WIN32
_isPBufferSupported = osg::isWGLExtensionSupported("WGL_ARB_pbuffer");
if (_isPBufferSupported)
{
wglCreatePBuffer = (WGLCreatePBufferProc)osg::getGLExtensionFuncPtr("wglCreatePbufferARB");
wglGetPBufferDC = (WGLGetPBufferDCProc)osg::getGLExtensionFuncPtr("wglGetPbufferDCARB");
wglReleasePBufferDC = (WGLReleasePBufferDCProc)osg::getGLExtensionFuncPtr("wglReleasePbufferDCARB");
wglDestroyPBuffer = (WGLDestroyPBufferProc)osg::getGLExtensionFuncPtr("wglDestroyPbufferARB");
wglQueryPBuffer = (WGLQueryPBufferProc)osg::getGLExtensionFuncPtr("wglQueryPbufferARB");
}
_isPixelFormatSupported = osg::isWGLExtensionSupported("WGL_ARB_pixel_format");
if (_isPixelFormatSupported)
{
wglGetPixelFormatAttribiv = (WGLGetPixelFormatAttribivProc)osg::getGLExtensionFuncPtr("wglGetPixelFormatAttribivARB");
wglGetPixelFormatAttribfv = (WGLGetPixelFormatAttribfvProc)osg::getGLExtensionFuncPtr("wglGetPixelFormatAttribfvARB");
wglChoosePixelFormat = (WGLChoosePixelFormatProc)osg::getGLExtensionFuncPtr("wglChoosePixelFormatARB");
}
_isRenderTextureSupported = osg::isWGLExtensionSupported("WGL_ARB_render_texture");
if (_isRenderTextureSupported)
{
wglBindTexImage = (WGLBindTexImageProc)osg::getGLExtensionFuncPtr("wglBindTexImageARB");
wglReleaseTexImage = (WGLReleaseTexImageProc)osg::getGLExtensionFuncPtr("wglReleaseTexImageARB");
wglSetPbufferAttrib = (WGLSetPbufferAttribProc)osg::getGLExtensionFuncPtr("wglSetPbufferAttribARB");
}
#endif
}
#if DEBUGGING
fprintf( fp, "nformats = %d\n\n", nformats );
int values[MAX_ATTRIBS];
int iatr[MAX_ATTRIBS] = { WGL_PIXEL_TYPE_ARB, WGL_COLOR_BITS_ARB,
WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB, WGL_BLUE_BITS_ARB,
WGL_ALPHA_BITS_ARB, WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_ACCUM_BITS_ARB,
WGL_DOUBLE_BUFFER_ARB, WGL_SUPPORT_OPENGL_ARB, WGL_ACCELERATION_ARB };
int niatr = 12;
for ( int j = 0; j < MAX_ATTRIBS; j++ )
{
values[j] = false;
iattributes[j] = iattributes[2*j];
}
for ( unsigned int i = 0; i < nformats; i++ )
{
if ( !wglGetPixelFormatAttribivARB( hdc, pformat[i], 0, niatr, iatr, values ) )
{
fprintf( stderr, "pbuffer creation error: wglGetPixelFormatAttribiv() failed\n" );
exit( -1 );
}
fprintf( fp, "%d. pformat = %d\n", i, pformat[i] );
fprintf( fp, "--------------------\n" );
for ( int k = 0; k < niatr; k++ )
{
if ( iatr[k] == WGL_PIXEL_TYPE_ARB )
{
if ( values[k] == WGL_TYPE_COLORINDEX_ARB )
fprintf( fp, " Pixel type = WGL_TYPE_COLORINDEX_ARB\n" );
if ( values[k] == WGL_TYPE_RGBA_ARB )
fprintf( fp, " Pixel type = WGL_TYPE_RGBA_ARB\n" );
}
if ( iatr[k] == WGL_COLOR_BITS_ARB )
{
fprintf( fp, " Color bits = %d\n", values[k] );
}
if ( iatr[k] == WGL_RED_BITS_ARB )
{
fprintf( fp, " red %d\n", values[k] );
}
if ( iatr[k] == WGL_GREEN_BITS_ARB )
{
fprintf( fp, " green %d\n", values[k] );
}
if ( iatr[k] == WGL_BLUE_BITS_ARB )
{
fprintf( fp, " blue %d\n", values[k] );
}
if ( iatr[k] == WGL_ALPHA_BITS_ARB )
{
fprintf( fp, " alpha %d\n", values[k] );
}
if ( iatr[k] == WGL_DEPTH_BITS_ARB )
{
fprintf( fp, " Depth bits = %d\n", values[k] );
}
if ( iatr[k] == WGL_STENCIL_BITS_ARB )
{
fprintf( fp, " Stencil bits = %d\n", values[k] );
}
if ( iatr[k] == WGL_ACCUM_BITS_ARB )
{
fprintf( fp, " Accum bits = %d\n", values[k] );
}
if ( iatr[k] == WGL_DOUBLE_BUFFER_ARB )
{
fprintf( fp, " Double Buffer = %d\n", values[k] );
}
if ( iatr[k] == WGL_SUPPORT_OPENGL_ARB )
{
fprintf( fp, " Support OpenGL = %d\n", values[k] );
}
if ( iatr[k] == WGL_ACCELERATION_ARB )
{
if ( values[k] == WGL_FULL_ACCELERATION_ARB )
fprintf( fp, " Acceleration = WGL_FULL_ACCELERATION_ARB\n" );
if ( values[k] == WGL_GENERIC_ACCELERATION_ARB )
fprintf( fp, " Acceleration = WGL_GENERIC_ACCELERATION_ARB\n" );
}
}
fprintf( fp, "\n" );
}
fprintf( fp, "selected pformat = %d\n", format );
#endif

View File

@ -0,0 +1,201 @@
#ifndef PBUFFERS_H
#define PBUFFERS_H
/*
#include <windows.h>
#include "GL/gl.h"
#include <GL/glut.h>
#include "GL/wglext.h"
#include <GL/glext.h>
*/
#include <osg/GL>
#if defined(WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#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