zoukankan      html  css  js  c++  java
  • glsl水包含倒影的实现(rtt) 【转】

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

    此文实现一个简单地水面倒影效果,通过rtt相机 获取倒影纹理, 水的基本实现方法(参考前一博文:osg通过glsl实现一个平面的水效果(法线贴图)),具体代码如下:

     
    vertex定点着色器:

     

    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[0].x = 1.0 - gl_TexCoord[0].x;   

             //根据时间获取法线纹理位置;

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

    }

    fragment像素着色器:

     
    
    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.05); //调制底面纹理波动;
    
             _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主程序:

      

    osg::ref_ptr createHalfSphere(osg::Image *img, float radius)
    
    {
    
             osg::ref_ptr geode = new osg::Geode;
    
             osg::ref_ptr geom = new osg::Geometry;
    
     
    
             //压入顶点;
    
             osg::ref_ptr veArr = new osg::Vec3Array;
    
             std::vector> veVertext;
    
     
    
             //纹理坐标;
    
             osg::ref_ptr texArr = new osg::Vec2Array;
    
             std::vector> texVertex;
    
     
    
             for(int i=0; i<=90; i+=10)
    
             {
    
                     std::vector veTmp;
    
                     std::vector _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 norArr = new osg::Vec3Array;
    
     
    
             std::vector>::iterator it = veVertext.begin();
    
             for(; it != veVertext.end(); )
    
             {
    
                     std::vector _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>::iterator itt = texVertex.begin();
    
             for(; itt != texVertex.end(); )
    
             {
    
                     std::vector _tmp = *itt;
    
                     itt++;
    
                     if(itt == texVertex.end())
    
                              break;
    
     
    
                     int count = (*itt).size();
    
                     for(int i=0; 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 tex = new osg::Texture2D;
    
             if(img->valid())
    
             {
    
                     tex->setImage(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);
    
             //geode->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace,osg::StateAttribute::ON);
    
             return geode;
    
    }
    
     
    
    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,-_h/2.0,-10));
    
             vArr->push_back(osg::Vec3(-_w/2.0,_h/2.0,-10));
    
             vArr->push_back(osg::Vec3(_w/2.0,_h/2.0,-10));
    
             vArr->push_back(osg::Vec3(_w/2.0,-_h/2.0,-10));
    
     
    
             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,0.0,1.0));
    
             geom->setNormalArray(nArr);
    
             geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
    
     
    
             geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
    
     
    
             return geode;
    
    }
    
     
    
     
    
    osg::ref_ptr createCamera(int _x, int _y, int _w, int _h,
    
             bool _isTargetImpl = false,
    
             osg::Vec4f _color = osg::Vec4f(0.3,0.6,0.5,1.0),
    
             osg::Camera::RenderOrder _renderOrder = osg::Camera::POST_RENDER,
    
             osg::Camera::ReferenceFrame _referenceFrame = osg::Camera::ABSOLUTE_RF)
    
    {
    
             osg::ref_ptr _camera = new osg::Camera;
    
             _camera->setViewport(_x, _y, _w, _h);
    
             _camera->setAllowEventFocus(false);
    
             _camera->setClearColor(_color);
    
             _camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
             _camera->setRenderOrder(_renderOrder);
    
             _camera->setReferenceFrame(_referenceFrame);
    
     
    
             if(_isTargetImpl)
    
             {
    
                     _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
    
             }
    
     
    
             //_camera->setProjectionMatrixAsOrtho2D(0,0,_w,_h);
    
             _camera->setProjectionMatrixAsPerspective(30.0,double(_w)/double(_h),0.01, 999.9);
    
             _camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
    
     
    
             return _camera;
    
    }
    
     
    
    int main(int argc, char *argv[])
    
    {
    
             osg::ref_ptr _root = new osg::Group;
    
             _root->addChild(osgDB::readNodeFile("cow.osg"));
    
     
    
        osg::ref_ptr _skybox = createHalfSphere(osgDB::readImageFile("../images/01.jpg"),1000.0);
    
             osg::ref_ptr _waterPanle  = createPlane(1200,1200);
    
             osg::ref_ptr _ceep = osgDB::readNodeFile("ceep.ive");
    
     
    
             osg::ref_ptr _mceep = new osg::MatrixTransform;
    
             _mceep->addChild(_ceep);
    
             _mceep->setMatrix(osg::Matrix::translate(500.0, 500.0, 0.0));
    
     
    
     
    
     osg::ref_ptr _rttCam = createCamera(0,0,600,400,false, osg::Vec4f(0.3,0.5,0.8,1.0),osg::Camera::PRE_RENDER,osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT);
    
             _rttCam->addChild(_skybox);
    
             _rttCam->addChild(_mceep);
    
     
    
             _root->addChild(_skybox);
    
             _root->addChild(_waterPanle);
    
             _root->addChild(_mceep);
    
             _root->addChild(_rttCam);
    
     
    
             //背景图片;
    
             osg::ref_ptr baseTex = new osg::Texture2D;
    
             baseTex->setTextureSize(600,400);
    
             baseTex->setInternalFormat(GL_RGBA);
    
             baseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
    
             baseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
    
             _rttCam->attach(osg::Camera::COLOR_BUFFER, baseTex);
    
     
    
             //法线图;
    
             osg::ref_ptr normTex = new osg::Texture2D;
    
             normTex->setImage(osgDB::readImageFile("../images/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 !
    ");
    
             }
    
             if(!fragShader->loadShaderSourceFromFile("water.frag"))
    
             {
    
                     printf("load fragment shader error !
    ");
    
             }
    
     
    
             _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
    
     
    
     
    
             osg::ref_ptr viewer = new osgViewer::Viewer;
    
             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());
    
     
    
     
    
                     osg::Vec3 _eye, _center, _up;
    
                     viewer->getCamera()->getViewMatrixAsLookAt(_eye, _center, _up);
    
     
    
                     osg::Vec3 _ttDir = _center - _eye;
    
     
    
                     osg::Vec3 _refEye = osg::Vec3(_eye.x(),_eye.y(),-_eye.z());
    
                     osg::Vec3 _refCenter = _refEye + osg::Vec3(_ttDir.x(), _ttDir.y(), -_ttDir.z());
    
                     osg::Vec3 _nnUp = osg::Vec3(_up.x(), _up.y(), -_up.z());
    
     
    
                     
    
                     _rttCam->setViewMatrixAsLookAt(_refEye,_refCenter,_nnUp);
    
     
    
                     //_rttCam->setViewMatrix(viewer->getCamera()->getViewMatrix());
    
                     _rttCam->setProjectionMatrix(viewer->getCamera()->getProjectionMatrix());
    
     
    
                     viewer->frame();
    
             }
    
     
    
             return 0;
    
    }
    
  • 相关阅读:
    js提取url参数的几种方法。(搜集)
    Sharepoint 权限
    Sharepoint身份模拟
    代码操作Sharepoint文档库(创建、上传附件)
    stsadm部署wsp包
    Sharepoint网站栏开发
    邮件发送
    Spsite.OpenWeb()
    Lua require 相对路径
    dropdownlist批量填充数据
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/6710012.html
Copyright © 2011-2022 走看看