glsl镜面水倒影的实现[转]
http://blog.sina.com.cn/s/blog_78ea87380101ejbf.html
使用两相机,一个master相机, 主要负责场景的渲染, 另一个rtt相机, 和master相机建立为镜面投影相机,用于在和master相机的纵向镜像投影,从而获取master投影场景的逆场景, 渲染到纹理,进行镜面贴图,实现水面的倒影效果。
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);
}
//创建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镜面水倒影的实现[转]的更多相关文章
- Android -- 图片处理, 画画板,缩放,旋转,平移,镜面,倒影,图片合成,颜色处理
1. 画画板 示例代码 public class MainActivity extends Activity { private ImageView iv; private Bitmap baseBi ...
- 初识android中的动画
动画效果可以大大提高界面的交互效果,因此,动画在移动开发中的应用场景较为普遍.掌握基本的动画效果在成熟的软件开发中不可或缺.除此之外,用户对于动画的接受程度远高于文字和图片,利用动画效果可以加深用户对 ...
- Android -- 图像处理(信息量超大)
Android的图像处理提供的API很帮,但是不适合用来写游戏,写游戏还是用专门的引擎比较好. Android的图像处理还有3D的处理的API,感觉超屌. 我先分享一下Android的一般的处理,比如 ...
- OpenGL(十五) OpenCV+OpenGL实现水面倒影
有两幅原始图片,一个是景物图像,一个是水面图像,尝试生成景物在水中的倒影: 在OpenGL中,加载并显示这个景物图像可以把这个图像作为纹理载入即可,把图像直接选择180度的效果就相当于是在镜面中倒影的 ...
- glsl水包含倒影的实现(rtt) [转]
转自 http://blog.sina.com.cn/s/blog_78ea87380101eixi.html 此文实现一个简单地水面倒影效果,通过rtt相机 获取倒影纹理, 水的基本实现方法(参考前 ...
- glsl水包含倒影的实现(rtt) 【转】
http://blog.sina.com.cn/s/blog_78ea87380101eixi.html 此文实现一个简单地水面倒影效果,通过rtt相机 获取倒影纹理, 水的基本实现方法(参考前一博文 ...
- GLSL实现Simple Displace Mapping 水仿真流体绘制 【转】
http://blog.csdn.net/a3070173/archive/2008/11/20/3342062.aspx Dislace Mapping其实就是在顶点着色器中 对顶点进行置换偏移,经 ...
- osg通过glsl实现一个平面的水效果(法线贴图) 【转】
转自 http://blog.sina.com.cn/s/blog_78ea87380101ehk3.html 此文实现一个简单的的水面效果,主要是法线贴图, 效果图如下: 此文分为三部分:ver ...
- CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果
CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...
随机推荐
- ALPHA(四)
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:丹丹 组员7:何家伟 组员8:政演 组员9:鸿杰 组员10:刘一好 组员:何宇恒 展示组内最新 ...
- quagga源码学习--BGP协议的初始化
quagga支持BGP-4,BGP-4+协议,支持多协议(mpls,isis,ospf等等)以及单播,组播路由的导入和分发. 具体的协议,这里就不附录了,网络上有很多资料,或者RFC. 协议源码的学习 ...
- ZOJ 3362 Beer Problem(SPFA费用流应用)
Beer Problem Time Limit: 2 Seconds Memory Limit: 32768 KB Everyone knows that World Finals of A ...
- 无序字母对 character
无序字母对 character 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入 ...
- Java简明教程 12.多线程(multithreading)
单线程和多线程 关于它们的区别,zhihu上有一个回答,我认为十分不错,如下: . 单进程单线程:一个人在一个桌子上吃菜. . 单进程多线程:多个人在同一个桌子上一起吃菜. . 多进程单线程:多个人每 ...
- ZJOI2017D1
假装我还活着. 去温州前沉迷各种奇怪的动画片..嗯补了不少高达.. 到温州以后继续看片..嗯ZG还是挺不错的..然后接着就FA♂现我什么都不会写..有点尴尬.. 因为宾馆离温州中学比较远就完全没去听课 ...
- HTML+CSS 滚动条样式自定义 - 适用于 div,iframe, html 等
友言:这两天被滚动条整的无与伦比,在此做下总结: 首先自定义浏览器滚动条的实现原理:计算浏览器滚动条的高度,层级1的高度与滚动条的总高度是一样的,通过相似比例计算: 浏览器滚动条总高度 :滚动条高度 ...
- js数据类型判断
在一般情况下使用typeof 但是有时候typeof返回的结果都是object,比如数组和json对象的时候,这个时候需要用到 instanceof了 还有一个更好得办法,Object.prototy ...
- POJ3983 快算24
很正常的题目,迷一样的答案. 测试数据只有一组,对没错只有一组. #include<cstdio> int main() { printf("5*(5-(1/5))\n" ...
- Docker(五):镜像
一,什么是镜像? Docker的镜像文件是由文件系统叠加而成的.最底端是一个引导文件系统,即bootfs.Docker用户几乎永远没有机会和引导文件有什么交互,实际上,当一个容器启动之后,容器就会被移 ...