转自 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. C# new用法总结

    有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法: 用于在泛型声明中约束可能用作类型参数的参数的类型,这是在Framewor ...

  2. Redis入门教程:特性及数据类型的操作

    虽然Redis已经很火了,相信还是有很多同学对Redis只是有所听闻或者了解并不全面,下面是一个比较系统的Redis介绍,对Redis的特性及各种数据类型及操作进行了介绍.是一个很不错的Redis入门 ...

  3. WebView介绍

    本文主要对WebView进行介绍,包括webView 4个可以定制的点.设置WebView back键响应.控制网页的链接仍在webView中跳转.显示页面加载进度.处理https请求.利用addJa ...

  4. 【LeetCode 230】Kth Smallest Element in a BST

    Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. Not ...

  5. 2016年VR&AR有市场吗?

    新霸哥发现了近期虚拟现实(VR)和增强现实(AR)非常火,已经成为了科技产业中最具前景的技术之一.其实说起这两项技术的应用,人们最容易把它与电子游戏联系在一起,那么在2016年VR&AR有市场 ...

  6. bzoj 3931 [CQOI2015]网络吞吐量(最短路,最大流)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3931 [题意] 只能通过1-n的最短路,求网络最大流 [思路] 分别以1,n为起点做最 ...

  7. 从使用到原理学习Java线程池

    线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收. 所 ...

  8. 第三百天了 how can I 坚持

    郭娜还是不搭理我,或许是真没有遇到合适的.? 该咋办,好焦虑. 其实态度应该放低点,就这样是找不到对象的. 有必要这么死耗嘛,人生总是这么纠结. 周六年后,周日来吃火锅,这一年又过去了. 睡觉.

  9. 软件工程第一次个人项目——词频统计by11061153柴泽华

    一.预计工程设计时间 明确要求: 15min: 查阅资料: 1h: 学习C++基础知识与特性: 4-5h: 主函数编写及输入输出部分: 0.5h: 文件的遍历: 1h: 编写两种模式的词频统计函数: ...

  10. log4j2使用总结

    一.Log4j有三个主要的组件:Loggers,Appenders和Layouts,这里可简单理解为日志级别,日志要输出的地方和日志格式 1. Logger Logger的日志级别有6级,分别是TRA ...