转自 http://blog.sina.com.cn/s/blog_78ea87380101ehk3.html

此文实现一个简单的的水面效果,主要是法线贴图, 效果图如下:

 

此文分为三部分:vertexShader, fragmentShader, main;
 
vertexShader:
 

varying vec3 lightdir;           //切线空间灯光向量;

varying vec3 eyedir;             //切线空间眼点向量;

varying vec4 ambient, diffuse, specular;

attribute vec3 tangent;          //顶点切线;

uniform float time;                       //时间更新;

uniform vec3  lightPos;         //灯光的位置;

void main()

{

vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);

vec3 L = normalize(lightPos - vVertex);                 //定点到光源向量;

vec3 E = normalize(-vVertex);                                     //定点到眼点向量;

vec3 N = normalize(gl_NormalMatrix * gl_Normal);

vec3 H = normalize(L + E);

//获取漫反射, 镜面反射量;

ambient = vec4(1.0,1.0,1.0,1.0);

diffuse = vec4(1.0,1.0,1.0,1.0);

specular = vec4(1.0,1.0,1.0,1.0);

float _diffuse = max(dot(L, N), 0.0);

if(_diffuse > 0.0)

{

diffuse = diffuse * _diffuse;

float _specular = max(dot(H,N),0.0);

specular = specular * pow(_specular , 64.0);

}

//计算切线空间量;

vec3 T = normalize(vec3(gl_NormalMatrix * tangent));

vec3 B = normalize(cross(N,T));

lightdir.x = dot(L,T);

lightdir.y = dot(L,B);

lightdir.z = dot(L,N);

lightdir = normalize(lightdir);

eyedir.x = dot(E,T);

eyedir.y = dot(E,B);

eyedir.z = dot(E,N);

lightdir = normalize(eyedir);

gl_TexCoord[0] = gl_MultiTexCoord0;

//根据时间获取法线纹理位置;

gl_TexCoord[1].x = gl_TexCoord[0].x + time * 0.05;

gl_TexCoord[1].y = gl_TexCoord[0].y + time * 0.05;

gl_Position  = ftransform();

}

fragmentShader:

varying vec3 lightdir;
varying vec3 eyedir;
varying vec4 ambient, diffuse, specular;

uniform sampler2D baseTex;
uniform sampler2D normTex;

void main()
{
         vec3 L = normalize(lightdir);
         vec3 E = normalize(eyedir);

         vec4 _baseColor = texture2D(baseTex, gl_TexCoord[0].xy);
         vec3 _normColor = texture2D(normTex, gl_TexCoord[1].xy).xyz;
        
         _baseColor = texture2D(baseTex, gl_TexCoord[0].xy + _normColor * 0.35); //调制底面纹理波动;
         _normColor = texture2D(normTex, gl_TexCoord[1].xy + _normColor * 0.02).xyz;

         vec3 N = normalize(_normColor * 2.0 - vec3(1.0));     //将法线转到[-1,1]范围;

         float _diff = max(dot(L,N),0.0);
         float _spec = max(dot(E,N),0.0);

         if(_diff > 0.0)
         {
                 _spec = pow(_spec, 64.0);
         }
 gl_FragColor = vec4(ambient.xyz * _baseColor.xyz + diffuse.xyz * _diff * _baseColor.xyz + specular * _spec, 1.0);
}

osg main()函数:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include "../OsgInstance/CommLib.h"
osg::ref_ptr createPlane(int _w, int _h)
{
         osg::ref_ptr geode = new osg::Geode;
         osg::ref_ptr geom = new osg::Geometry;
         geode->addDrawable(geom);

         osg::ref_ptr vArr = new osg::Vec3Array;
         vArr->push_back(osg::Vec3(-_w/2.0,0,-_h/2.0));
         vArr->push_back(osg::Vec3(-_w/2.0,0,_h/2.0));
         vArr->push_back(osg::Vec3(_w/2.0,0,_h/2.0));
         vArr->push_back(osg::Vec3(_w/2.0,0,-_h/2.0));

         geom->setVertexArray(vArr);

         osg::ref_ptr tArr = new osg::Vec2Array;
         tArr->push_back(osg::Vec2(0.0,0.0));
         tArr->push_back(osg::Vec2(0.0,1.0));
         tArr->push_back(osg::Vec2(1.0,1.0));
         tArr->push_back(osg::Vec2(1.0,0.0));

         geom->setTexCoordArray(0, tArr);

         osg::ref_ptr nArr = new osg::Vec3Array;
         nArr->push_back(osg::Vec3(0.0,-1.0,1.0));
         geom->setNormalArray(nArr);
         geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

         geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

         return geode;
}

int main(int argc, char *argv[])
{

         osg::ref_ptr viewer = new osgViewer::Viewer;

         osg::ref_ptr _root = new osg::Group;
         osg::ref_ptr  _waterPanle = createPlane(500,500);
         _root->addChild(_waterPanle);

         //背景图片;
         osg::ref_ptr baseTex = new osg::Texture2D;
         baseTex->setImage(osgDB::readImageFile("water0.bmp"));
         baseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
         baseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);

         //法线图;
         osg::ref_ptr normTex = new osg::Texture2D;
         normTex->setImage(osgDB::readImageFile("water.bmp"));
         normTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
         normTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);

         _waterPanle->getOrCreateStateSet()->setTextureAttributeAndModes(0, baseTex, 1);
         _waterPanle->getOrCreateStateSet()->setTextureAttributeAndModes(1, normTex, 1);

 
         osg::ref_ptr program = new osg::Program;
         osg::ref_ptr  vertShader = new osg::Shader(osg::Shader::VERTEX);
         osg::ref_ptr  fragShader = new osg::Shader(osg::Shader::FRAGMENT);
         program->addShader(vertShader);
         program->addShader(fragShader);

         if(!vertShader->loadShaderSourceFromFile("water.vert"))
         {
                 printf("load vertex shader error !\n");
         }
         if(!fragShader->loadShaderSourceFromFile("water.frag"))
         {
                 printf("load fragment shader error !\n");
         }

         _waterPanle->getOrCreateStateSet()->setAttribute(program, 1);
         _waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("time", float(0.0)));
         _waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("baseTex", 0));
         _waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("normTex", 1));
 _waterPanle->getOrCreateStateSet()->addUniform(new osg::Uniform("lightPos", osg::Vec3(0.0,0.0,0.0)));//lightPos

 
         viewer->setSceneData(_root);
         viewer->setCameraManipulator(new osgGA::TrackballManipulator);

         while(!viewer->done())
         {

                 float _time = viewer->getFrameStamp()->getSimulationTime();     
                 _waterPanle->getOrCreateStateSet()->getUniform("time")->set(_time);

                 osg::Matrix _mmt = viewer->getCamera()->getViewMatrix();
                 _waterPanle->getOrCreateStateSet()->getUniform("lightPos")->set(_mmt.getTrans());

                 viewer->frame();
         }

}

osg通过glsl实现一个平面的水效果(法线贴图) 【转】的更多相关文章

  1. 一个有趣的模拟光照的shader(类似法线贴图)

    最近使用unity,碰到到一个很有趣的例子.场景无光线,却模拟出了光照,效果挺好.其思路与法线贴图原理异曲同工. 原作者提供的效果印象深刻. 模型除了使用原来的diffuse贴图外,还用到了一张模拟记 ...

  2. 已知有两个水杯,一个11L一个7L,水可以任意使用,求怎么得到2L 的详细解法

    问题:有两个水杯,一个是11L一个是7L,水可以随便用,怎么得到2L 1.了解问题的本质 问题中给出了两个杯子,只有这两个杯子有量度,所以只能让杯中的水满进满出才能确定杯子中最后有多少水. 现在问题要 ...

  3. 使用Unity实现动态2D水效果

    http://forum.china.unity3d.com/thread-16044-1-1.html 在这片教程里面我们将会用简单的物理效果来模拟动态的2D水效果.我们将会使用Line Rende ...

  4. 一个不错的loading效果--IT蓝豹

    一个不错的loading效果 介绍:一个不错的loading加载效果,弹性收缩,效果不错,学习android动画的朋友可以下载来研究研究本例子其实由SeekBar实现,由MetaballView,Me ...

  5. 一个Banner广告收缩效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 利用jquery+iframe做一个ajax上传效果

    以下是自学it网--中级班上课笔记 网址:www.zixue.it html页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict ...

  7. Css实现一个简单的幻灯片效果页面

    使用animation动画实现一个简单的幻灯片效果. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  8. SceneKit做一个旋转的地球效果

    SceneKit可以用寥寥几行帮你完成很多OpenGL复杂的3D设置代码,下面本猫就带大家完成一个旋转的3D地球的场景. 首先需要地球表面图片,将其导入到Xcode中: 我们用SceneKit内置的几 ...

  9. JaveWeb 公司项目(1)----- 使Div覆盖另一个Div完成切换效果

    最近在做网页,用的是CSS+DIV的布局方法,搭建了一个简易的界面,大体上分为三个部分,如图所示: 左侧的为主功能导航栏,右侧是具体的功能实现,下方是固定的版权声明,单击左边不同的导航按钮,在div中 ...

随机推荐

  1. js控制不同的时间段显示不同的css样式

    js控制不同的时间段显示不同的css样式 js函数,可以放到单独的js文件中也可以放到当前页的<head>标记之内 function getCSS(){        datetoday ...

  2. NGUI学习笔记-Label

    属性说明 Overflow: ShrinkContent : 如果文本超出文本框宽度,会自动缩小文本size,使其显示完整 ClampContent : 文本大小固定,超出文本框的部分不会显示,也不会 ...

  3. SDN环境搭建(mininet,OVS,ryu安装及命令)

    1.mininet安装与使用 1.1mininet安装 ubuntu 12.04/14.04/14.10      命令行  sudo apt-get install mininet 1.2 mini ...

  4. LeetCode 232 Implement Queue using Stacks

    Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...

  5. SpringMVC+Spring+Hibernate+Maven+mysql整合

    一.准备工作 1.工具:jdk1.7.0_80(64)+tomcat7.0.68+myeclipse10.6+mysql-5.5.48-win322. 开发环境安装配置.Maven项目创建(参考:ht ...

  6. crontab 定时任务格式

    如下内容节选自<Linux Crontab 定时任务 命令详解> 用crontab -e 添加要执行的命令 添加的命令必须以如下格式: * * * * * /command path 前五 ...

  7. 5个Xcode开发调试技巧

    转自Joywii的博客,原文:Four Tips for Debugging in XCode Like a Bro    1.Enable NSZombie Objects(开启僵尸对象) Enab ...

  8. Delphi异形窗口之PNG

    //1.单元内容 unit UnitAlienForm; interface uses Windows, Forms, Classes, Graphics; //从文件加载PNG procedure ...

  9. Spring EL hello world example

    The Spring EL is similar with OGNL and JSF EL, and evaluated or executed during the bean creation ti ...

  10. labview 中activex的初步使用方法

    1.在前面板放置一个activex容器 2.插入activex控件 3.百度找到这个activex控件的属性和方法介绍 4.程序框图中右键activex控件,创建xxx类的方法或者xxx的属性:act ...