OSGEarth绘制动态水效果
来源:互联网 发布:迦南诗选全集软件下载 编辑:程序博客网 时间:2024/05/27 12:21
在OSGEarth上绘制水效果的思路为:
1. 使用OSG::Geometry的方式绘制多边形;
2. 在绘制的多边形上贴一个水的纹理;
3. 对纹理使用shader效果,使之动态展示。
此种方式适用于小范围的不严格的水效果,若需要大范围或者有水底效果的请使用OSGOcean。
代码如下:water.h
class Water : public HandleAdapter{public: Water(GraphicsView* view); ~Water();protected: virtual void slotPickedXYZ(osg::Vec3d pos); virtual void slotMoveingXYZ(osg::Vec3d pos); virtual void slotRightHandle();private: void drawWater(osg::Vec3d pos = osg::Vec3d()); osg::Texture2D* creatText2D(const QString& strFile); void initShader();private: osg::ref_ptr<osg::Vec3dArray> m_vecPoints; osg::Geode* m_pWater; char* m_waterFrag; char* m_waterVert;};
实现代码如下:water.cpp
Water::Water(GraphicsView* view): HandleAdapter(view){ m_pWater = NULL; m_vecPoints = new osg::Vec3dArray; m_vecPoints->clear(); initShader();}Water::~Water(){}void Water::slotPickedXYZ(osg::Vec3d pos){ m_vecPoints->push_back(pos); if (m_vecPoints->size() <= 2) { return; } drawWater();}void Water::slotMoveingXYZ(osg::Vec3d pos){ if (m_vecPoints->size() < 2) { return; } drawWater(pos);}void Water::slotRightHandle(){ endHandle(); m_pWater = nullptr;}void Water::drawWater(osg::Vec3d pos /*= osg::Vec3d()*/){ osg::ref_ptr<osg::Vec3dArray> vecPoints = new osg::Vec3dArray; vecPoints = m_vecPoints; if (pos == osg::Vec3d() && m_vecPoints->size() <= 2) { return; } if (pos != osg::Vec3d()) { vecPoints->push_back(pos); } osg::ref_ptr<osg::Geometry> pWater = new osg::Geometry; pWater->setVertexArray(vecPoints); pWater->addPrimitiveSet( new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, vecPoints->size())); //纹理 osg::ref_ptr<osg::Texture2D> pText2D = new osg::Texture2D; pText2D->setTextureSize(1024, 1024); pText2D->setInternalFormat(GL_RGBA); pWater->getOrCreateStateSet()->setTextureAttributeAndModes(0, pText2D); pWater->getOrCreateStateSet()->setTextureAttributeAndModes(1, creatText2D("shui_5.jpg")); pWater->getOrCreateStateSet()->setTextureAttributeAndModes(2, creatText2D("water_DUDV.jpg")); pWater->getOrCreateStateSet()->setTextureAttributeAndModes(3, creatText2D("water_NM.jpg")); // shader osg::ref_ptr<osg::Shader> pVeter = new osg::Shader(osg::Shader::VERTEX, m_waterVert); osg::ref_ptr<osg::Shader> pFrag = new osg::Shader(osg::Shader::FRAGMENT, m_waterFrag); osg::ref_ptr<osg::Program> pProgram = new osg::Program; pProgram->addShader(pVeter); pProgram->addShader(pFrag); pWater->getOrCreateStateSet()->addUniform(new osg::Uniform("reflection", 0)); pWater->getOrCreateStateSet()->addUniform(new osg::Uniform("defaultTex", 1)); pWater->getOrCreateStateSet()->addUniform(new osg::Uniform("refraction", 2)); pWater->getOrCreateStateSet()->addUniform(new osg::Uniform("normalTex", 3)); pWater->getOrCreateStateSet()->setAttributeAndModes(pProgram); if (m_pWater == NULL) { m_pWater = new osg::Geode; m_pLayerGroup->addChild(m_pWater); } m_pWater->addDrawable(pWater); m_pWater->setStateSet(pWater->getOrCreateStateSet());}osg::Texture2D* Water::creatText2D(const QString& strFile){ if (strFile.isEmpty()) { return NULL; } osg::ref_ptr<osg::Texture2D> pText2D = new osg::Texture2D; pText2D->setImage(osgDB::readImageFile(strFile.toStdString())); pText2D->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); pText2D->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT); pText2D->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); pText2D->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture::LINEAR); return pText2D.release();}
shader的内容如下:
void Water::initShader(){ m_waterVert = { "uniform float osg_FrameTime;\n" "varying vec4 projCoords;\n" "varying vec3 lightDir, eyeDir;\n" "varying vec2 flowCoords, rippleCoords;\n" "void main()\n" "{\n" " vec3 T = vec3(0.0, 1.0, 0.0);\n" " vec3 N = vec3(0.0, 0.0, 1.0);\n" " vec3 B = vec3(1.0, 0.0, 0.0);\n" " T = normalize(gl_NormalMatrix * T);\n" " B = normalize(gl_NormalMatrix * B);\n" " N = normalize(gl_NormalMatrix * N);\n" " mat3 TBNmat;\n" " TBNmat[0][0] = T[0]; TBNmat[1][0] = T[1]; TBNmat[2][0] = T[2];\n" " TBNmat[0][1] = B[0]; TBNmat[1][1] = B[1]; TBNmat[2][1] = B[2];\n" " TBNmat[0][2] = N[0]; TBNmat[1][2] = N[1]; TBNmat[2][2] = N[2];\n" " vec3 vertexInEye = vec3(gl_ModelViewMatrix * gl_Vertex);\n" " lightDir = gl_LightSource[0].position.xyz - vertexInEye;\n" " lightDir = normalize(TBNmat * lightDir);\n" " eyeDir = normalize(TBNmat * (-vertexInEye));\n" " vec2 t1 = vec2(osg_FrameTime*0.02, osg_FrameTime*0.02);\n" " vec2 t2 = vec2(osg_FrameTime*0.05, osg_FrameTime*0.05);\n" " flowCoords = gl_MultiTexCoord0.xy + t1/10.0;\n" //* 5.0 + t1 " rippleCoords = gl_MultiTexCoord0.xy + t1;\n" // " gl_TexCoord[0] = gl_MultiTexCoord0;\n" " gl_Position = ftransform();\n" " projCoords = gl_Position;\n" "}\n" }; m_waterFrag = { "uniform sampler2D defaultTex;\n" "uniform sampler2D reflection;\n" "uniform sampler2D refraction;\n" "uniform sampler2D normalTex;\n" "varying vec4 projCoords;\n" "varying vec3 lightDir, eyeDir;\n" "varying vec2 flowCoords, rippleCoords;\n" "void main()\n" "{\n" " vec2 rippleEffect = 0.02 * texture2D(refraction, rippleCoords * 0.01).xy;\n" " vec4 N = texture2D(normalTex, flowCoords + rippleEffect);\n" " N = N * 2.0 - vec4(1.0);\n" " N.a = 1.0; N = normalize(N);\n" " vec3 refVec = normalize(reflect(-lightDir, vec3(N) * 0.6));\n" " float refAngle = clamp(dot(eyeDir, refVec), 0.0, 1.0);\n" " vec4 specular = vec4(pow(refAngle, 40.0));\n" " vec2 dist = texture2D(refraction, flowCoords + rippleEffect).xy;\n" " dist = (dist * 2.0 - vec2(1.0)) * 0.1;\n" " vec2 uv = projCoords.xy / projCoords.w;\n" " uv = clamp((uv + 1.0) * 0.5 + dist, 0.0, 1.0);\n" " vec4 base = texture2D(defaultTex, uv);\n" " vec4 refl = texture2D(reflection, uv);\n" " gl_FragColor = mix(base, refl + specular, 0.6);\n" "}\n" };}
1 0
- OSGEarth绘制动态水效果
- Canvas 绘制动态效果线框
- Android Paint绘制动态心电图效果
- OSGEarth绘制Geometry:画线(一)
- OSGEarth绘制Geometry:绘圆(二)
- OSGEarth绘制Geometry:绘多边形(三)
- osgearth API编程动态建立一个地球!
- canvas绘制圆环百分比进度的动态效果
- H5动画,canvas绘制圆环百分比进度的动态效果
- H5动画,canvas绘制圆环百分比进度的动态效果
- osgEarth js脚本绘制柱状图 10.feature_population_cylinders.earth
- Archie osgEarth Step By Step ⑤OsgEarth开发指南——使用osgearth API编程动态建立地图
- Archie osgEarth Step By Step ⑤OsgEarth开发指南——使用osgearth API编程动态建立地图
- osgearth API编程动态建立一个地球【转】
- Adobe Edge Animate应用(2)-绘制图形并应用动态效果
- 绘制玻璃效果
- 绘制玻璃效果
- 绘制玻璃效果
- 设计模式读书笔记:State(状态)
- iOS中多线程原理与runloop介绍
- HDU(1241)
- Ubuntu 14.04 下手动安装Firefox的Flash插件
- 在java中实现调用简单的c程序
- OSGEarth绘制动态水效果
- STM32固件库详解
- This system is not registered with RHN
- atitit.http get post的原理以及框架实现java php
- 说说我的iOS项目结构设计
- Unity学习笔记 之 关于 Unity UI 的 Slider 的代码记录
- 黑马程序员——OC基础---开发技巧(多文件开发,xcode功能演示)
- VMware虚拟机下 Redhat上网
- 如何在discuz帖子中插入视频