osg通过glsl实现一个平面的水效果(法线贴图) 【转】
转自 http://blog.sina.com.cn/s/blog_78ea87380101ehk3.html
此文实现一个简单的的水面效果,主要是法线贴图, 效果图如下:
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实现一个平面的水效果(法线贴图) 【转】的更多相关文章
- 一个有趣的模拟光照的shader(类似法线贴图)
		最近使用unity,碰到到一个很有趣的例子.场景无光线,却模拟出了光照,效果挺好.其思路与法线贴图原理异曲同工. 原作者提供的效果印象深刻. 模型除了使用原来的diffuse贴图外,还用到了一张模拟记 ... 
- 已知有两个水杯,一个11L一个7L,水可以任意使用,求怎么得到2L 的详细解法
		问题:有两个水杯,一个是11L一个是7L,水可以随便用,怎么得到2L 1.了解问题的本质 问题中给出了两个杯子,只有这两个杯子有量度,所以只能让杯中的水满进满出才能确定杯子中最后有多少水. 现在问题要 ... 
- 使用Unity实现动态2D水效果
		http://forum.china.unity3d.com/thread-16044-1-1.html 在这片教程里面我们将会用简单的物理效果来模拟动态的2D水效果.我们将会使用Line Rende ... 
- 一个不错的loading效果--IT蓝豹
		一个不错的loading效果 介绍:一个不错的loading加载效果,弹性收缩,效果不错,学习android动画的朋友可以下载来研究研究本例子其实由SeekBar实现,由MetaballView,Me ... 
- 一个Banner广告收缩效果
		<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ... 
- 利用jquery+iframe做一个ajax上传效果
		以下是自学it网--中级班上课笔记 网址:www.zixue.it html页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict ... 
- 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 ... 
- SceneKit做一个旋转的地球效果
		SceneKit可以用寥寥几行帮你完成很多OpenGL复杂的3D设置代码,下面本猫就带大家完成一个旋转的3D地球的场景. 首先需要地球表面图片,将其导入到Xcode中: 我们用SceneKit内置的几 ... 
- JaveWeb 公司项目(1)----- 使Div覆盖另一个Div完成切换效果
		最近在做网页,用的是CSS+DIV的布局方法,搭建了一个简易的界面,大体上分为三个部分,如图所示: 左侧的为主功能导航栏,右侧是具体的功能实现,下方是固定的版权声明,单击左边不同的导航按钮,在div中 ... 
随机推荐
- 屏蔽页面js报的错误
			有时候,某些js的错误,确实没有什么大影响,但是这个又实在没办法. 一般,下下策采取 <script language="javascript"> function k ... 
- 解决Jsoup网页抓取过程中需要cookie的问题
			最近在做城觅网的信息抓取,发现城觅网上海与北京的url是一样的.那怎样才确定信息的来源呢?折腾了半天,才发现城觅网是使用cookie的,如果你把网站的cookie禁用了,就无法在上海与北京之间切换了. ... 
- JavaEE参考示例 SpringSide 4.0 GA版杀青
			SpringSide是以Spring Framework为核心的,Pragmatic风格的JavaEE应用参考示例,是JavaEE世界中的主流技术选型,较佳实践的总结与演示. 经过漫长的7个月和6个R ... 
- ECSHOP seo修改建议
			ECSHOP是一个非常优秀的商城程序,以丰富的模板.稳定开源.非常快的执行速度赢得广大网店主的青眯.可是新建站30多天,目前百度只收录了首页,而google收录正常.我检查了他的网站一切正常,没有任何 ... 
- WPF MultiBinding 和 IMultiValueConverter
			MultiBinding,描述附加到单个绑定目标属性的Binding对象的集合.可以指定多个数值绑定. IMultiValueConverter通过转换器使用MultiBingding对象,该对象讲根 ... 
- 【转】C++ 智能指针详解
			一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 ... 
- The Tower of Babylon
			题意: 有n个,长x宽y高z的长方体,把这些长方体摞起来,上面长方体底面的长宽一定要小于下面的,求能摞的最大高度. 分析: 一个长方体,可以有三种放法,先把所有放的状态存起来,按底面升序排列,dp[i ... 
- ARM处理机模式--内部寄存器
			处理器模式 用户模式(user)简称usr 快速中断模式(FIQ)简称fiq 外部中断模式(IRQ)简称irq 特权模式(supervisor)简称sve 数据访问终止模式(abort)简称abt 未 ... 
- C++继承与派生的概念、什么是继承和派生
			在C++中可重用性是通过继承(inheritance)这一机制来实现的.因此,继承是C++的一个重要组成部分. 前面介绍了类,一个类中包含了若干数据成员和成员函数.在不同的类中,数据成员和成员函数是不 ... 
- nodejs + socket.io + redis 新手上路
			最近要更新网站架构了,决定转入 nodejs + socket.io + redis 方式. 战斗刚开始: 网上的文章太松散,我根据各个网友的分享进行整理 ,让大家可以方便上手. 进入node.js之 ... 
