glsl镜面水倒影的实现[转]

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);

时间: 2024-11-08 22:50:35

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

初识android中的动画

动画效果可以大大提高界面的交互效果,因此,动画在移动开发中的应用场景较为普遍.掌握基本的动画效果在成熟的软件开发中不可或缺.除此之外,用户对于动画的接受程度远高于文字和图片,利用动画效果可以加深用户对于产品的印象.因此本文给出安卓设计中几种常见的动画效果. 基础知识 在介绍安卓中的动画效果之前,有必要介绍一下安卓中的图片处理机制.图片的特效包括图形的缩放.镜面.倒影.旋转.平移等.图片的特效处理方式是将原图的图形矩阵乘以一个特效矩阵,形成一个新的图形矩阵来实现的.矩阵Matrix 类,维护了一个

Android的多媒体编程

多媒体编程 1.什么是多媒体? 多种媒体的综合. 图片.音乐.视频等: ##图片的常见格式: 1.bmp:以高质量保存所有类型的图片,并将其应用于计算机: 255 KB,255*340像素,24位深度 计算机表示图形的时候时候是使用像素点来表示的,每个像素点都有一个颜色,每个颜色都是使用6位16进制的数值来表示的,一个像素点使用24个bit表示. 图像大小的计算公式:分辨率的宽*高*位深度 + 头文件占用的数据大小=图形实际大小 ,颜色不会失真,图片的体积比较大. 2.jpg:36.4 KB,2

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

Android的图像处理提供的API很帮,但是不适合用来写游戏,写游戏还是用专门的引擎比较好. Android的图像处理还有3D的处理的API,感觉超屌. 我先分享一下Android的一般的处理,比如平移.翻转等: 缩放.旋转.平移.镜面.倒影                                                       缩放 Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawab

冰冷红尘,喟叹于心

光阴荏苒,风,携着秋的萧瑟载来初冬的凉寒,而落叶纷飞的日子总给人些许伤感.莫名惆怅.许是季节导演了这场凄美片段,又许是岁月绘就了这幅烟雨画卷,让我的世界顿然失去色彩.蓦然回首,却见忧伤满天.一片一片… 时光,若一湾宁静的水倒影着过往流年,淌过春秋冬夏,浸透每一个白天和黑夜.我在晨风暮雨中看尽浮华,倏尔.跌入万劫不复的多情崖下.于是冗长岁月里,揣一怀清风,揽一轮皓月,执笔写下渐已老去的青春年华.回头,转身,又瞥见岁月剥落的满地感伤. 华年似水,那些走过的青春渐已淡去,唯有记忆里有些无法忘却的点,连

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

http://blog.csdn.net/a3070173/archive/2008/11/20/3342062.aspx Dislace Mapping其实就是在顶点着色器中 对顶点进行置换偏移,经常用于水仿真流体绘制. 顶点着色器: uniform float g_fScale; uniform sampler2D g_DisplaceTexture; void main() { float fDisplace = texture2DLod(g_DisplaceTexture, gl_Mul

GLSL 中的光照计算

理论知识转载地址:http://blog.csdn.net/ym19860303/article/details/25545933 1.Lambert模型(漫反射) 环境光: Iambdiff = Kd*Ia 其中Ia 表示环境光强度,Kd(0<K<1)为材质对环境光的反射系数,Iambdiff是漫反射体与环境光交互反射的光强. 方向光: Ildiff = Kd * Il * Cos(θ) 其中Il是点光源强度,θ是入射光方向与顶点法线的夹角,称入射角(0<=A<=90°),Ild

OpenGLES2.0着色器语言glsl

OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了.这就加大了处理的速度. 下面的这篇教程是转载的.原文地址如下,感谢作者manyou http://www.apkbus.com/blog-99192-39382.html 一.着色语言基础 数据类型概述 1. 标量 标量也被称为"无向量"其值只有大小,并不具有方向.标量之间的运算遵循简单的

GLSL 在OpenGL中向shader传递信息【转】

http://blog.csdn.net/hgl868/article/details/7872219 引言 一个OpenGL程序可以用多种方式和shader通信.注意这种通信是单向的,因为shader的输出只能是渲染到某些目标,比如颜色和深度缓存. OpenGL的部分状态可以被shader访问,因此程序改变OpenGL某些状态就可以与shader进行通信了.例如一个程序想把光的颜色传给shader,可以直接调用OpenGL接口,就像使用固定功能流水线时做的那样. 不过,使用OpenGL状态并不

虚幻UE4中移动端水材质的设置

内容: *概述 *纹理文件 *基本颜色 *法线的设置 *标量参数和材质属性 *场景设置 *最终效果 概述 本教程由52VR翻译自unrealengine官方,在本教程中,我们将教您如何创建可以在移动设备上使用的实例化水资源.本教程是最新版本,支持只有在高端移动设备(如iPad Pro)才能进行的高品质移动端反射渲染功能. **********请一定要下载本页面上的纹理文件********** ********还要确保您的项目设置>渲染(Rendering)>允许静态照明(Allow Stati