OSGEarth绘制动态水效果

原创 2015年07月10日 21:22:35

在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"
    };
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

VS2010+OSG_3.2+osgEarth_2.5+osgOcean_1.0.1+VPB+CEGUI_0.8.4 编译包链接

  • 2014年08月28日 16:14
  • 124B
  • 下载

osgOcean+VS2010+Win7编译方法

1、首先要下载osgOcean-Source-1.0.1包,以及依赖包osgOcean-Resources-1.0.1、fftss-3.0-20071031,可在:链接:http://pan.baid...
  • L_Andy
  • L_Andy
  • 2016年05月20日 15:27
  • 1492

osgOcean与osgEarth融合技术细节

osgOcean与osgEarth融合的主要技术问题有2点: 1.osgOcean是平面的海洋,所以不支持osgEarth球面。 2.osgEarth渲染最终依靠shader完成,并且自带一套着色器合...
  • zsq306650083
  • zsq306650083
  • 2013年04月15日 10:41
  • 2353

OSG中实现水波的效果

  • 2008年12月12日 09:41
  • 1.43MB
  • 下载

基于OSG的水实现所想起的问题

以上两图来自于http://www.osgchina.org/index.php?option=com_content&view=article&id=180&Itemid=506由FreeSouth...
  • u011115875
  • u011115875
  • 2017年02月20日 15:14
  • 532

OSG Shader GLSL 4.3 使用纹理 例子

OSG 中使用纹理shader 例子#include #include #include #include #include #include static char * vertexS...
  • zhuyingqingfen
  • zhuyingqingfen
  • 2015年03月09日 10:18
  • 3089

osgearth各个例子功能概述

最近在学习osgearth,对其还不是很理解,有些例子不会运行,有些可以,把可以的做个统计,以备后面查用。 1、osgearth_graticule:生成经纬线。 2、osgearth_annotat...
  • J1101460678
  • J1101460678
  • 2016年03月09日 14:53
  • 3316

OSG学习笔记20——光照和材质的设置(正确绘制出想要的颜色)

本来一开始学习OSG和Opengl的时候,因为用不太到关于颜色渲染之类的内容,关注的比较多的都是如何与场景进行交互。现在突然想给场景添加一个地面,发现不能得到正确的结果,并且加载进来的模型也会随着地面...
  • u011310341
  • u011310341
  • 2017年03月25日 16:43
  • 1678

osgEarth开发数据准备(一)——DEM与纹理影像(遥感)下载与处理

获取数据的方式 数字高程数据终于下载完成了。数据获取折腾了足足一个星期,稍稍总结一下。虽然目前还没有一套可以免费使用的高精度覆盖全球的数字高程数据,但是还是有许多途径可以让我们找到一套可以使用的数据,...
  • giantchen547792075
  • giantchen547792075
  • 2013年06月14日 17:24
  • 6409

osgearth介绍

介绍 osgEarth为开发osg应用提供了一个地理空间SDK和地形引擎. osgEarth的目标: 提供基于osg开发3D地理空间应用的支持;直接从数据源可视化地形模型和影像变得更加简单;提供对开...
  • lizhenneng
  • lizhenneng
  • 2016年05月18日 11:32
  • 2756
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OSGEarth绘制动态水效果
举报原因:
原因补充:

(最多只允许输入30个字)