|
每种实现水的方法都不一定一样,好像也没看到过其他做水的源码,结合网上论文,结合osg想了种方法,在osg群各位高手的提示,指点下完成,代码写的乱,请各位多多指点。
//////////////////////////////////////////////////////////////////////////
//代码写的乱,我尽量说清楚,
#include <osg/Camera>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Image>
#include <osg/BlendFunc>[local]1[/local][local]1[/local][local]1[/local]
#include <osg/BlendEquation>
#include <osg/TexMat>
#include <osg/MatrixTransform>
#include <Windows.h>
#include <iostream>
using namespace std;
class RefCameraCallBack: public osg::NodeCallback//这个是反射相机的回调,这个相机是根据视点的相机的变化而变化
//位置就是视点在水平面的镜像,这个也较容易实现,我的代码写的乱,
//大家了解方法就行,可以自己动手改进一下。
{
public:
RefCameraCallBack(osg::Camera * camera):_cankaoCamera(camera),_frist(true),_yizi(1.0f)
{
//_rttCamera->attach(osg::Camera::BufferComponent::COLOR_BUFFER,_image);
}
~RefCameraCallBack(){}
virtual void operator() (osg::Node *node, osg::NodeVisitor *nv)
{
_RttCamera=dynamic_cast<osg::Camera *>(node);
//if(_RttCamera==NULL)
osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi=osg::GraphicsContext::getWindowingSystemInterface();
if(!wsi) cout<<"转型出错"<<endl;
//osg::GraphicsContext::ScreenIdentifier screen(0);
//wsi->getScreenResolution(screen,width,height);
const osg::GraphicsContext::Traits * traits=_cankaoCamera->getGraphicsContext()->getTraits();
w_h=traits->width/traits->height;
_time=_cankaoCamera->getView()->getFrameStamp()->getSimulationTime();
ViewCalculate();
cout<<_time<<endl;
_RttCamera->setViewMatrix(_cankaoCamera->getViewMatrix());
//_RttCamera->setViewMatrixAsLookAt(_eye_Positon,_eye_Center,_eye_Up);
double aspectRatio,zNear, zFar;
_cankaoCamera->getProjectionMatrixAsPerspective(fovy,aspectRatio,zNear,zFar);
//cout<<aspectRatio<<endl;
cout<<traits->width<<" "<<traits->height<<endl;
w_h=float(aspectRatio);
//double newAspect=traits->width/traits->height;
//double yizi=newAspect/aspectRatio;
//_RttCamera->setProjectionMatrix(_cankaoCamera->getProjectionMatrix()*osg::Matrix::scale(1.0/yizi,1.0,1.0));
//_RttCamera->setProjectionMatrixAsPerspective(fovy,1.0/yizi,zNear,zFar);
_RttCamera->setProjectionMatrix(_cankaoCamera->getProjectionMatrix());
}
//osg::Image * getImage(){return _image.get();}
//osg::Node * getReflectionNode(){return _water;}
float getW_H(){return w_h;}
float getFovy(){return static_cast<float>(osg:egreesToRadians(fovy/2.0));}
osg::Vec3 &getViewPosition(){return _eye_Positon;}
double getTime(){return _time;}
protected:
virtual void ViewCalculate()
{
_cankaoCamera->getViewMatrixAsLookAt(_eye_Positon,_eye_Center,_eye_Up,10.0);
//_eye_Positon.z()=(_eye_Positon.z()-_waterHigh)*2-_eye_Positon.z();
//_eye_Center.z()=(_eye_Center.z()-_waterHigh)*2-_eye_Center.z();
//_eye_Positon.z()=-_eye_Positon.z();
//_eye_Center.z()=-_eye_Center.z();
//_m=_cankaoCamera->getProjectionMatrix();
}
private:
osg::Camera * _cankaoCamera;
osg::Camera * _RttCamera;
osg::Matrix _m;
float w_h;
double fovy;
float _waterHigh;
bool _frist;
unsigned int _Width;
float _yizi;
osg::Vec3 _eye_Positon;
osg::Vec3 _eye_Center;
osg::Vec3 _eye_Up;
mutable double _time;
float _lookDistance;//这个值的意思是指眼的位置与中心的距离,osg的观察方式设计中是一个向量,只有方向,大小直接可以自己设置,
//这个值越大则设置的焦点越远,比如建筑物。值越小则距焦点越近,比如静物写真。
//还可以讲这个值想象成3ds Max软件中目标相机的目标点与相机的距离。
//这里将这个值默认的设置成100.0
};
class updateViewShader : public osg::Uniform::Callback
{
public:
updateViewShader(RefCameraCallBack * ref):_ref(ref){}
virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv )
{
uniform->set(_ref->getViewPosition());
}
private:
RefCameraCallBack * _ref;
};
class updateW_HShader : public osg::Uniform::Callback
{
public:
updateW_HShader(RefCameraCallBack * ref):_ref(ref){}
virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv )
{
if (!uniform)
{
cout<<"转型出错"<<endl;
return;
}
uniform->set((_ref->getW_H()));
float t;
uniform->get(t);
cout<<t<<endl;
}
private:
RefCameraCallBack * _ref;
};
class updateFovyShader : public osg::Uniform::Callback
{
public:
updateFovyShader(RefCameraCallBack * ref):_ref(ref){}
virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv )
{
if (!uniform)
{
cout<<"转型出错"<<endl;
return;
}
uniform->set((_ref->getFovy()));
float t;
uniform->get(t);
cout<<t<<endl;
}
private:
RefCameraCallBack * _ref;
};
class updateTimeShader : public osg::Uniform::Callback
{
public:
updateTimeShader(RefCameraCallBack * ref):_ref(ref){}
virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv )
{
if (!uniform)
{
cout<<"转型出错"<<endl;
return;
}
uniform->set(static_cast<float>((_ref->getTime())));
float t;
uniform->get(t);
cout<<t<<endl;
}
private:
RefCameraCallBack * _ref;
};
int main( int argc, char** argv )
{
osgViewer::Viewer viewer;
//////////////////////////////////////////////////////////////////////////注意路径
osg::ref_ptr<osg::Node> other = osgDB::readNodeFile( "E://ALL_TEST//OSG_TEST//debug//data//other.3ds" );//这个是水两边的瓷片,呵呵,为了更像一些
osg::ref_ptr<osg::Node> water=osgDB::readNodeFile("E://ALL_TEST//OSG_TEST//debug//data//water.3ds");//水的节点,就是一个平面
osg::ref_ptr<osg::Node> tree=osgDB::readNodeFile( "E://ALL_TEST//OSG_TEST//debug//data//tree.3ds" );//树
osg::ref_ptr<osg::Node> sky=osgDB::readNodeFile( "E://ALL_TEST//OSG_TEST//debug//data//sky.3ds" );//天空球
//osg::ref_ptr<osg::Node> _ref=osgDB::readNodeFile( "E:/ALL_TEST/OSG_TEST/debug/data/ref.3ds" );//
//////////////////////////////////////////////////////////////////////////创建rtt相机
osg::ref_ptr<osg::Camera> rtt=new osg::Camera;
rtt->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
rtt->setReferenceFrame( osg::Transform::ReferenceFrame::ABSOLUTE_RF_INHERIT_VIEWPOINT );
rtt->setRenderOrder( osg::Camera:RE_RENDER );//提前渲染
rtt->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
//////////////////////////////////////////////////////////////////////////创建rtt相机结束
//////////////////////////////////////////////////////////////////////////这里有必要说一下
//本来打算将渲染出来的像素拷贝出来,这样可以对像素进行调整,加效果,然而我测试的并不理想//
//速度很慢,而且会跳,问高手后原因是每进行一次image的分配会将速度降低,跳因为未分配完成//
//就直接调用,造成黑色,所以此种方式不可取,进行纹理的直接绑定这种方式不错,基本上不大影响速度。
//osg::Image * _image=new osg::Image;
//_image->setAllocationMode(osg::Image::AllocationMode::NO_DELETE);
//_image->setDataType(GL_RGBA);
//_image->setInternalTextureFormat(GL_RGBA);
//_image->setWriteHint(osg::Image::WriteHint::STORE_INLINE);
//_image->allocateImage(256,256,1,GL_RGBA,GL_UNSIGNED_INT);
//////////////////////////////////////////////////////////////////////////纹理的绑定
osg::ref_ptr<osg::Texture2D> texture=new osg::Texture2D;
texture->setWrap(osg::Texture2D::WrapParameter::WRAP_S,osg::Texture2D::WrapMode::REPEAT);
texture->setWrap(osg::Texture2D::WrapParameter::WRAP_T,osg::Texture2D::WrapMode::REPEAT);
texture->setInternalFormat( GL_RGBA );
texture->setFilter( osg::Texture::MIN_FILTER, osg::Texture:INEAR );
texture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR );
texture->setTextureSize(128,128);
rtt->attach( osg::Camera::BufferComponent::COLOR_BUFFER,texture.get() );
osg::Camera * camera=viewer.getCamera();//得到视点相机
osg::ref_ptr<RefCameraCallBack> ref=new RefCameraCallBack(camera);//反射相机
rtt->setUpdateCallback(ref.get());
//////////////////////////////////////////////////////////////////////////纹理绑定结束
//////////////////////////////////////////////////////////////////////////这里是将需要反射节点进行镜像
osg::ref_ptr<osg::MatrixTransform> _m_t=new osg::MatrixTransform;
_m_t->setReferenceFrame(osg::Transform::ReferenceFrame::RELATIVE_RF);
osg::Matrix m;
m.makeTranslate(0.0f,0.0f,-102.8f);
m.makeScale(1.0,1.0,-1.0);
m.makeTranslate(0.0f,0.0f,-102.8f);
_m_t->preMult(osg::Matrix::scale(1.0f,1.0f,-1.0f)*osg::Matrix::translate(0.0,0.0,-102.8));//这里的102.8是水面的高度,在建模软件里面得知
//_m_t->setMatrix(m);
rtt->setClearColor(osg::Vec4(0.0,0.0,0.0,0.0));
_m_t->addChild(tree.get());
_m_t->addChild(other.get());
_m_t->addChild(sky.get());
rtt->addChild(_m_t.get());//rtt相机渲染镜像的节点
//////////////////////////////////////////////////////////////////////////镜像结束
//////////////////////////////////////////////////////////////////////////创建设备上下文
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x =100;
traits->y =100;
traits->width = 1440;
traits->height = 900;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
//traits->supportsResize=false;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
gc->setClearColor(osg::Vec4(0.2,0.4,0.6,0.9));
gc->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
camera->setGraphicsContext(gc.get());
camera->setViewport(new osg::Viewport(0,0, traits->width, traits->height));
camera->setProjectionMatrixAsPerspective(30,traits->width/traits->height,1.0,10000.0);
//////////////////////////////////////////////////////////////////////////创建设备上下文结束
//////////////////////////////////////////////////////////////////////////shader部分
osg::StateSet* stateset = water->getOrCreateStateSet();
osg::Shader* vertexShader = new osg::Shader( osg::Shader::VERTEX );
osg::Shader* fragmentShader = new osg::Shader( osg::Shader::FRAGMENT );
//注意shader的路径,在shader里面有关键的一步计算,在shader里面有注释
vertexShader->loadShaderSourceFromFile( "E://ALL_TEST//OSG_TEST//debug//ocean.vert" );
fragmentShader->loadShaderSourceFromFile( "E://ALL_TEST//OSG_TEST//debug//ocean.frag" );
//注意shader的路径,在shader里面有关键的一步计算,在shader里面有注释
stateset->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON );
osg::Program* program = new osg::Program;
program->addShader( vertexShader );
program->addShader( fragmentShader );
stateset->setAttributeAndModes( program, osg::StateAttribute::ON );
osg::Uniform* view_position = new osg::Uniform( "view_position", ref->getViewPosition() );
stateset->addUniform(view_position);
view_position->setUpdateCallback(new updateViewShader(ref.get()));
osg::Image * noise_image=osgDB::readImageFile("water.bmp");
osg::ref_ptr<osg::Texture2D> noise=new osg::Texture2D(noise_image);
noise->setWrap(osg::Texture2D::WrapParameter::WRAP_S,osg::Texture2D::WrapMode::REPEAT);
noise->setWrap(osg::Texture2D::WrapParameter::WRAP_T,osg::Texture2D::WrapMode::REPEAT);
stateset->setTextureAttributeAndModes(1,noise.get(),osg::StateAttribute::ON);
osg::Uniform* Noise = new osg::Uniform( "normalMap", 1);
stateset->addUniform(Noise);
osg::Uniform * RTT=new osg::Uniform("cubeMap",0);
stateset->addUniform(RTT);
osg::Uniform* time = new osg::Uniform( "time", 0.0f);
stateset->addUniform(time);
time->setUpdateCallback(new updateTimeShader(ref.get()));
osg::Uniform* w_h = new osg::Uniform( "w_h", 10.0f);
stateset->addUniform(w_h);
w_h->setUpdateCallback(new updateW_HShader(ref.get()));
osg::Uniform* fovy = new osg::Uniform( "fovy",ref->getFovy());
stateset->addUniform(fovy);
fovy->setUpdateCallback(new updateFovyShader(ref.get()));
//////////////////////////////////////////////////////////////////////////shader部分结束
//////////////////////////////////////////////////////////////////////////将树Alpha透明
osg::ref_ptr<osg::BlendFunc> b_f=new osg::BlendFunc;
b_f->setFunction(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
tree->getOrCreateStateSet()->setAttributeAndModes(b_f.get(),osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
tree->getOrCreateStateSet()->setRenderingHint( osg::StateSet::RenderingHint::TRANSPARENT_BIN );
//////////////////////////////////////////////////////////////////////////Alpha透明结束
//////////////////////////////////////////////////////////////////////////将场景添加到根节点,关闭灯光
osg::ref_ptr<osg::Group> root = new osg::Group;
root->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
root->addChild(other.get());
root->addChild(tree.get());
root->addChild(sky.get());
root->addChild(rtt.get());
root->addChild(water.get());
//////////////////////////////////////////////////////////////////////////添加到根节点结束
viewer.setSceneData( root.get() );
return viewer.run();
} |
-
-
data.rar
1.85 MB, 下载次数: 11618, 下载积分: 威望 1
|