http://blog.sina.com.cn/s/blog_78ea87380101ejbf.html

使用两相机,一个master相机, 主要负责场景的渲染, 另一个rtt相机, 和master相机建立为镜面投影相机,用于在和master相机的纵向镜像投影,从而获取master投影场景的逆场景, 渲染到纹理,进行镜面贴图,实现水面的倒影效果。

 
效果如图:
实现代码(需要一张天空背景图, 一张water法线图):
 
vertex shader:

varying vec3 lightdir;

varying vec3 eyedir;

varying vec3 normal;

varying vec3 halfvec;

varying vec4 ambient, diffuse, specular;

attribute vec3 tangent;

uniform float _time;

uniform vec3  lightDir;

//传入RTT相机模型投影矩阵,使用主要为不让纹理跟随主相机的变动而异常变动,

//可以使用gl_ProjectionMatrix * vVertex试试相应的效果,实验时需要把fragshader中的coord.y=1.0-coord.y打开;

uniform mat4 uRTTViewMatrix;

varying vec4 vRTTVertex;

void main()

{

vec4 vVertex = gl_ModelViewMatrix * gl_Vertex;

vRTTVertex = uRTTViewMatrix * gl_Vertex;

vec3 tLightDir = lightDir;

lightdir = normalize(tLightDir - vVertex.xyz);

vec3 tEyeDir = -vVertex.xyz;

eyedir = normalize(tEyeDir);

vec3 tNormal = normalize(gl_NormalMatrix * gl_Normal);

normal = normalize(tNormal);

////

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 LdotN = max(0.0, dot(lightdir, normal));

if(LdotN > 0.0)

{

diffuse = LdotN ;

vec3 H = normalize(lightdir + eyedir);

float spec = max(0.0, dot(H, normal));

specular =  pow(spec, 16.0);

}

////

//切线空间;

vec3 _tangent = normalize(gl_NormalMatrix * tangent);

vec3 _bNormal = normalize(cross(normal, _tangent));

lightdir.x = dot(lightdir, _tangent);

lightdir.y = dot(lightdir, _bNormal);

lightdir.z = dot(lightdir, normal);

lightdir = normalize(lightdir);

eyedir.x = dot(eyedir, _tangent);

eyedir.y = dot(eyedir, _bNormal);

eyedir.z = dot(eyedir, normal);

eyedir = normalize(eyedir);

halfvec = normalize(lightdir + eyedir);

gl_TexCoord[0] = gl_MultiTexCoord0;

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

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

gl_Position = ftransform();

}

fragment shader:

uniform sampler2D _baseTex;

uniform sampler2D _normTex;

varying vec3 lightdir;

varying vec3 eyedir;

varying vec3 normal;

varying vec3 halfvec;

varying vec4 ambient, diffuse, specular;

varying vec4 vRTTVertex;

void main()

{

vec3 L = normalize(lightdir);

vec3 E = normalize(eyedir);

vec3 N = normalize(normal);

vec3 H = normalize(halfvec);

vec3 _normC = texture2D(_normTex, gl_TexCoord[1].xy).xyz;

//vRTTVertex范围[-0.5 ,0.5] ,转换为[0.0,1.0];

vec2 coord = (vRTTVertex.xy/vRTTVertex.w)*0.5 + 0.5;

//触使镜面纹理波动效果;

vec2 _tInc = vec2(0.0,0.0);

_tInc.y = clamp(_normC.y * 0.00925, 0.0, 1.0) * 0.5 ; //适当调节参数,使上下摆动幅度;

vec4 _color = texture2D(_baseTex, coord + _tInc);

_normC = texture2D(_normTex, gl_TexCoord[1].xy + _normC * 0.05);

//将[0,1]范围转到[-1,1];

_normC = normalize((_normC - vec3(0.5)) * 2.0);

float LdotN = max(dot(L, _normC), 0.0);

float HdotN = max(dot(H, _normC), 0.0);

if(HdotN > 0.0)

{

HdotN = pow(HdotN, 64.0);

}

gl_FragColor = vec4(ambient.xyz * _color.xyz + diffuse.xyz * LdotN * _color.xyz

+ specular.xyz * HdotN, _color.a);

}

 
main程序:
 

//创建Quad;

osg::ref_ptr<osg::Geode> createQuad(int _w, int _h)

{

osg::ref_ptr<osg::Geode> geode = new osg::Geode;

osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;

geode->addDrawable(geom);

osg::ref_ptr<osg::Vec3Array> vArr = new osg::Vec3Array;

vArr->push_back(osg::Vec3(-_w/2.0,-_h/2.0,0.0));

vArr->push_back(osg::Vec3(-_w/2.0,_h/2.0,0.0));

vArr->push_back(osg::Vec3(_w/2.0,_h/2.0,0.0));

vArr->push_back(osg::Vec3(_w/2.0,-_h/2.0,0.0));

geom->setVertexArray(vArr);

osg::ref_ptr<osg::Vec2Array> texArr = new osg::Vec2Array;

texArr->push_back(osg::Vec2(0.0,0.0));

texArr->push_back(osg::Vec2(0.0,1.0));

texArr->push_back(osg::Vec2(1.0,1.0));

texArr->push_back(osg::Vec2(1.0,0.0));

geom->setTexCoordArray(0,texArr);

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

osg::ref_ptr<osg::Vec3Array> nArr = new osg::Vec3Array;

nArr->push_back(osg::Vec3d(0.0,0.0,-1.0));

geom->setNormalArray(nArr);

geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

return geode;

}

osg::ref_ptr<osg::Camera> createRTTCamera(int x, int y, int w, int h)

{

osg::ref_ptr<osg::Camera> _camera = new osg::Camera;

_camera->setAllowEventFocus(false);

_camera->setViewport(x, y, w, h);

_camera->setClearColor(osg::Vec4(0.2,0.3,0.58,1.0));

_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

_camera->setRenderOrder(osg::Camera::PRE_RENDER);

_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);

_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);

_camera->setProjectionMatrixAsPerspective(30.0, double(w)/double(h),0.1, 9999.89);

_camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);

return _camera;

}

osg::ref_ptr<osg::Camera> createCamera(int x, int y, int w, int h)

{

osg::ref_ptr<osg::Camera> _camera = new osg::Camera;

_camera->setAllowEventFocus(false);

_camera->setViewport(x, y, w, h);

_camera->setClearColor(osg::Vec4(0.1,0.6,0.48,1.0));

_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

_camera->setRenderOrder(osg::Camera::POST_RENDER);

_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);

_camera->setProjectionMatrixAsPerspective(30.0, double(w)/double(h),0.1, 9999.89);

_camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);

return _camera;

}

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

{

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

osg::ref_ptr<osg::Group> _root = new osg::Group;

osg::ref_ptr<osg::Node> _water  = createQuad(10000,10000); //osgDB::readNodeFile("water2.3DS");

osg::ref_ptr<osg::Node> _cessna = osgDB::readNodeFile("cessna.osg");

osg::ref_ptr<osg::Node> _ceep = osgDB::readNodeFile("ceep.ive");

osg::ref_ptr<osg::Node> _skyBox = HalfSphere::createHalfSphere(osgDB::readImageFile("sky-HXY2.jpg"), 5000.0);

//水池;

osg::ref_ptr<osg::MatrixTransform> _m0 = new osg::MatrixTransform;

_m0->addChild(_water);

//天空;

osg::ref_ptr<osg::MatrixTransform> _m1 = new osg::MatrixTransform;

_m1->addChild(_skyBox);

//cessna172;

osg::ref_ptr<osg::MatrixTransform> _m2 = new osg::MatrixTransform;

_m2->addChild(_cessna);

_m2->setMatrix(osg::Matrix::translate(osg::Vec3d(10.0, 10.0, 100.0)));

//ceep;

osg::ref_ptr<osg::MatrixTransform> _m3 = new osg::MatrixTransform;

_m3->addChild(_ceep);

_m3->setMatrix(osg::Matrix::translate(osg::Vec3d(-100.0,0.0,0)));

//rtt相机;

osg::ref_ptr<osg::Camera> _rttCam = createRTTCamera(0,0,1920,1080);

_rttCam->addChild(_m1);

_rttCam->addChild(_m2);

_rttCam->addChild(_m3);

osg::ref_ptr<osg::Camera> _mstCam = createCamera(0,0,1920,1080);

_mstCam->addChild(_m0);

_mstCam->addChild(_m1);

_mstCam->addChild(_m2);

_mstCam->addChild(_m3);

_root->addChild(_rttCam);

_root->addChild(_mstCam);

//纹理绑定;

osg::ref_ptr<osg::Texture2D> _tex = new osg::Texture2D;

_tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);

_tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);

_tex->setTextureSize(1920,1080);

_tex->setInternalFormat(GL_RGB);

_rttCam->attach(osg::Camera::COLOR_BUFFER, _tex);

_m0->getOrCreateStateSet()->setTextureAttributeAndModes(0, _tex, 1);

osg::ref_ptr<osg::Texture2D> _tex1 = new osg::Texture2D;

_tex1->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);

_tex1->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);

_tex1->setImage(osgDB::readImageFile("water.bmp"));

_m0->getOrCreateStateSet()->setTextureAttributeAndModes(1, _tex1, 1);

_m0->getOrCreateStateSet()->setMode(GL_LIGHTING , 0);

//添加shader;

osg::ref_ptr<osg::Program> program = new osg::Program;

osg::ref_ptr<osg::Shader> vertShader = new osg::Shader(osg::Shader::VERTEX);

if(!vertShader->loadShaderSourceFromFile("water.vert"))

{

return -1;

}

osg::ref_ptr<osg::Shader> fragShader = new osg::Shader(osg::Shader::FRAGMENT);

if(!fragShader->loadShaderSourceFromFile("water.frag"))

{

return -1;

}

program->addShader(vertShader);

program->addShader(fragShader);

_m0->getOrCreateStateSet()->setAttribute(program,1);

_m0->getOrCreateStateSet()->addUniform(new osg::Uniform("_baseTex", 0));

_m0->getOrCreateStateSet()->addUniform(new osg::Uniform("_normTex", 1));

_m0->getOrCreateStateSet()->addUniform(new osg::Uniform("_time", float(0.0)));//lightDir

_m0->getOrCreateStateSet()->addUniform(new osg::Uniform("lightDir", osg::Vec3f(100.0, 100.0, 100.0)));

_m0->getOrCreateStateSet()->addUniform(new osg::Uniform("uRTTViewMatrix", osg::Matrix::identity()));

viewer->setSceneData(_root);

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

viewer->getCamera()->setClearColor(osg::Vec4(0.8,0.8,0.7,1.0));

while(!viewer->done())

{

float _t = viewer->getCamera()->getView()->getFrameStamp()->getSimulationTime();

_m0->getOrCreateStateSet()->getUniform("_time")->set(_t);

_m0->getOrCreateStateSet()->getUniform("lightDir")->set(viewer->getCamera()->getViewMatrix().getTrans());

_mstCam->setViewMatrix(viewer->getCamera()->getViewMatrix());

//rtt相机正投倒影;

//_rttCam->setViewMatrix(viewer->getCamera()->getViewMatrix());

//_rttCam->setProjectionMatrix(viewer->getCamera()->getProjectionMatrix());

//rtt相机镜像投影;

osg::Vec3 _eye, _center, _up;

_mstCam->getViewMatrixAsLookAt(_eye, _center, _up);

//求取投影相机相应的eye,center,up位置及方向;

osg::Vec3 _refEye = osg::Vec3(_eye.x(), _eye.y(), -_eye.z());

osg::Vec3 _refUp  = osg::Vec3(_up.x(), _up.y(), -_up.z());

osg::Vec3 _refCenter = osg::Vec3(_center.x(), _center.y(), -_center.z());

//使用_refUp有倒影,不解?;

_rttCam->setViewMatrixAsLookAt(_refEye, _refCenter, osg::Vec3d(0.0, 0.0, 1.0));

//设置rtt相机的投影矩阵;

_m0->getOrCreateStateSet()->getUniform("uRTTViewMatrix")->set(

_rttCam->getViewMatrix()*_rttCam->getProjectionMatrix());

viewer->frame();

}

return 0;

}

//创建天空盒, 半球型;

osg::ref_ptr<osg::Node> HalfSphere::createHalfSphere(osg::Image *img, float radius)

{

osg::ref_ptr<osg::Geode> geode = new osg::Geode;

osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;

//压入顶点;

osg::ref_ptr<osg::Vec3Array> veArr = new osg::Vec3Array;

std::vector<std::vector<osg::Vec3>> veVertext;

//纹理坐标;

osg::ref_ptr<osg::Vec2Array> texArr = new osg::Vec2Array;

std::vector<std::vector<osg::Vec2>> texVertex;

for(int i=0; i<=90; i+=10)

{

std::vector<osg::Vec3> veTmp;

std::vector<osg::Vec2> _texTmp;

for(int j=0; j<=360; j += 10)

{

double x = radius * cos(osg::DegreesToRadians((float)i)) * cos(osg::DegreesToRadians((float)j));

double y = radius * cos(osg::DegreesToRadians((float)i)) * sin(osg::DegreesToRadians((float)j));

double z = radius * sin(osg::DegreesToRadians((float)i));

veTmp.push_back(osg::Vec3(x,y,z));

_texTmp.push_back(osg::Vec2((float)j/370.0+0.01,(float)i/100.0+0.01));

}

veVertext.push_back(veTmp);

texVertex.push_back(_texTmp);

}

//重新组织点;

//法线数组;

osg::ref_ptr<osg::Vec3Array> norArr = new osg::Vec3Array;

std::vector<std::vector<osg::Vec3>>::iterator it = veVertext.begin();

for(; it != veVertext.end(); )

{

std::vector<osg::Vec3> _tmp = *it;

it++;

if(it == veVertext.end())

break;

int count = (*it).size();

for(int i=0; i<count; i++)

{

veArr->push_back(_tmp.at(i));

veArr->push_back(it->at(i));

norArr->push_back(osg::Vec3(0,0,0) - _tmp.at(i));

norArr->push_back(osg::Vec3(0,0,0) - it->at(i));

}

}

geom->setVertexArray(veArr);

std::vector<std::vector<osg::Vec2>>::iterator itt = texVertex.begin();

for(; itt != texVertex.end(); )

{

std::vector<osg::Vec2> _tmp = *itt;

itt++;

if(itt == texVertex.end())

break;

int count = (*itt).size();

for(int i=0; i<count; i++)

{

texArr->push_back(_tmp.at(i));

texArr->push_back(itt->at(i));

}

}

geom->setTexCoordArray(0,texArr);

//法线;

geom->setNormalArray(norArr);

geom->setNormalBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);

geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP,0,veArr->size()));

geode->addDrawable(geom);

//纹理;

osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D;

if(img->valid())

{

tex->setImage(0,img);

}

tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);//列向;

tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);//行向;

geom->getOrCreateStateSet()->setTextureAttributeAndModes(0,tex,osg::StateAttribute::ON);

glsl镜面水倒影的实现[转]的更多相关文章

  1. Android -- 图片处理, 画画板,缩放,旋转,平移,镜面,倒影,图片合成,颜色处理

    1. 画画板 示例代码 public class MainActivity extends Activity { private ImageView iv; private Bitmap baseBi ...

  2. 初识android中的动画

    动画效果可以大大提高界面的交互效果,因此,动画在移动开发中的应用场景较为普遍.掌握基本的动画效果在成熟的软件开发中不可或缺.除此之外,用户对于动画的接受程度远高于文字和图片,利用动画效果可以加深用户对 ...

  3. Android -- 图像处理(信息量超大)

    Android的图像处理提供的API很帮,但是不适合用来写游戏,写游戏还是用专门的引擎比较好. Android的图像处理还有3D的处理的API,感觉超屌. 我先分享一下Android的一般的处理,比如 ...

  4. OpenGL(十五) OpenCV+OpenGL实现水面倒影

    有两幅原始图片,一个是景物图像,一个是水面图像,尝试生成景物在水中的倒影: 在OpenGL中,加载并显示这个景物图像可以把这个图像作为纹理载入即可,把图像直接选择180度的效果就相当于是在镜面中倒影的 ...

  5. glsl水包含倒影的实现(rtt) [转]

    转自 http://blog.sina.com.cn/s/blog_78ea87380101eixi.html 此文实现一个简单地水面倒影效果,通过rtt相机 获取倒影纹理, 水的基本实现方法(参考前 ...

  6. glsl水包含倒影的实现(rtt) 【转】

    http://blog.sina.com.cn/s/blog_78ea87380101eixi.html 此文实现一个简单地水面倒影效果,通过rtt相机 获取倒影纹理, 水的基本实现方法(参考前一博文 ...

  7. GLSL实现Simple Displace Mapping 水仿真流体绘制 【转】

    http://blog.csdn.net/a3070173/archive/2008/11/20/3342062.aspx Dislace Mapping其实就是在顶点着色器中 对顶点进行置换偏移,经 ...

  8. osg通过glsl实现一个平面的水效果(法线贴图) 【转】

    转自 http://blog.sina.com.cn/s/blog_78ea87380101ehk3.html 此文实现一个简单的的水面效果,主要是法线贴图, 效果图如下:   此文分为三部分:ver ...

  9. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

随机推荐

  1. python - 接口自动化测试 - HttpRequest - 接口测试类封装

    # -*- coding:utf-8 -*- ''' @project: ApiAutoTest @author: Jimmy @file: http_request.py @ide: PyCharm ...

  2. python 学习分享-常用模块篇

    模块 就是前人给你造的轮子,你开车就好!!! 常用模块有: time模块 random模块 os模块 sys模块 shutil模块 json  &  picle模块 shelve模块 xml处 ...

  3. Map-Reduce基础

    1.设置文件读入分隔符 默认按行读入; 按句子读入 : conf1.set("textinputformat.record.delimiter", "."); ...

  4. Leetcode 605.种花问题

    种花问题 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有.可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去. 给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表 ...

  5. bat 处理adb脚本

    @echo off REM Funtion: 测试parsermode 接口CdxParserGetMediaInfo 和CdxParserRead REM Code by lzp 2017-05-0 ...

  6. TOJ 3750: 二分查找

    3750: 二分查找   Time Limit(Common/Java):3000MS/9000MS     Memory Limit:65536KByteTotal Submit: 1925     ...

  7. poj2488 A Knight's Journey裸dfs

    A Knight's Journey Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35868   Accepted: 12 ...

  8. POJ3207 Ikki's Story IV - Panda's Trick 【2-sat】

    题目 liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping with Ikk ...

  9. 分布式文件系统FastDFS集群部署

    1.源码开放下载地址:https://github.com/happyfish100 早期源码开放下载地址:https://sourceforge.net/projects/fastdfs/files ...

  10. py2exe error: [Errno 2] No such file or directory: 'MSVCP90.dll'

    使用 python setup.py py2exe 打包时出现 py2exe error: [Errno 2] No such file or directory: 'MSVCP90.dll' 解决方 ...