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


  • 相关阅读:
    HDU 3081 Marriage Match II
    HDU 4292 Food
    HDU 4322 Candy
    HDU 4183 Pahom on Water
    POJ 1966 Cable TV Network
    HDU 3605 Escape
    HDU 3338 Kakuro Extension
    HDU 3572 Task Schedule
    HDU 3998 Sequence
    Burning Midnight Oil
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/3804443.html
Copyright © 2011-2022 走看看