• 典型的shader砖块


    效果:

    shader.vs:

         #version 140          
        //顶点
         in vec4 MCvertex;   
        //法线
         in vec3 MCnormal;          
        //怀疑这些以osg_打头的都是osg的内置变量
         in vec3 osg_SimulationTime;          
         uniform mat4 osg_ModelViewMatrix;      
         uniform mat4 osg_ModelViewProjectionMatrix;  
         uniform mat3 osg_NormalMatrix;  
        
        //光照位置
         uniform vec3 LightPosition ;  
        //镜面光强度
         const float SpecularContribution = 0.3;  
        //散射光强度
         const float DiffuseContribution = 1.0 - SpecularContribution;  
        //光照强度值
         out float LightIntensity;  
        //顶点的x,y值
         out vec2 MCposition;  
         void main()  
         {  
        //物体坐标系->世界坐标系->相机坐标系的转换
               vec3 ecPosition = vec3(osg_ModelViewMatrix * MCvertex);          
        //法线转到相机坐标系
               vec3 tnorm = normalize(osg_NormalMatrix * MCnormal);          
            //光照的方向
               vec3 lightVec = normalize(vec3(LightPosition[0],LightPosition[1],LightPosition[2]*osg_SimulationTime) - ecPosition);      
        //计算出反射方向
               vec3 reflectVec = reflect(-lightVec, tnorm);          
               vec3 viewVec = normalize(-ecPosition);      
               float diffuse = max(dot(lightVec, tnorm), 0.0);      
               float spec = 0.0;          
               if (diffuse > 0.0)      
            {  
                   spec = max(dot(reflectVec, viewVec), 0.0);  
                   spec = pow(spec, 16.0);  
              }  
               LightIntensity = DiffuseContribution * diffuse + SpecularContribution * spec;  
               MCposition = MCvertex.xy;  
               gl_Position = osg_ModelViewProjectionMatrix * MCvertex;  
         }   

    shader.fs:

      #version 140   
        //转的颜色 和 砖缝的颜色
          uniform vec3 BrickColor = vec3(0,1,0), MortarColor = vec3(1,0,0);  
        //转的长和宽
          uniform vec2 BrickSize = vec2(0.3,0.15);  
        //砖的宽和高相对于砖缝的宽和高之间的比例
          uniform vec2 BrickPct = vec2(0.9,0.85);  
        //顶点的x、y
          in vec2 MCposition;  
        //光照强烈度
          in float LightIntensity;  
        //片元颜色
          out vec4 FragColor;  
          void main()  
          {  
              vec3 color;  
              vec2 position, useBrick;  
        //得到砖块行号和砖块列号
             position = MCposition / BrickSize;  
        //frack(x) = 1-floor(x),floor(x)=返回小于或等于x的最近整数。相当于取小数部分
               if (fract(position.y * 0.5) >= 0.5)  
                         position.x += 0.5;  
        //计算片元在当前砖块中的位置(取小数部分)
                 position = fract(position);  
        //step(edge0,x) 如果x>edge0,返回1,否则,返回0
                 useBrick = step(position, BrickPct);  
        //mix(x,y,a)=x*(1.0-a)+y*a,其实可以简写
                 //color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);  
    
         if(useBrick.x * useBrick.y == 0){ color = MortarColor; }else {color = BrickColor;}  
    
                 color *= LightIntensity;  
                 FragColor = vec4(color, 1.0);  
         }  

    main.cpp

    #include <osgViewer/Viewer>
    #include <osgDB/ReadFile>
    #include <osg/Shape>
    #include <osg/Shapedrawable>
    #include <osg/MatrixTransform>
    
    osg::ref_ptr<osg::MatrixTransform> lightPos;
    
    class MyNodeVisitor : public osg::NodeVisitor
    {
    public:
        MyNodeVisitor() :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}
    
        virtual void apply(osg::Geode& node)
        {
            for (int i = 0; i < node.getNumParents(); ++i)
            {
                osg::ref_ptr<osg::Geometry> polyGeom = dynamic_cast<osg::Geometry*>(node.getDrawable(i));
    
                if (!polyGeom)return;
    
                polyGeom->setVertexAttribArray(0, polyGeom->getVertexArray());
                polyGeom->setVertexAttribBinding(0, osg::Geometry::BIND_PER_VERTEX);
                polyGeom->setVertexAttribArray(1, polyGeom->getColorArray());
                polyGeom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);
                polyGeom->setVertexAttribArray(2, polyGeom->getNormalArray());
                polyGeom->setVertexAttribBinding(2, polyGeom->getNormalBinding());
            }
        }
    };
    
    
    int main()
    {
        osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
        osg::ref_ptr<osg::Node> geode = osgDB::readNodeFile("cow.osg");//CreateNode();
    
        MyNodeVisitor visitor;
        geode->accept(visitor);
    
        osg::ref_ptr<osg::StateSet> stateSet = geode->getOrCreateStateSet();
    
        osg::ref_ptr<osg::Shader> vShader = new osg::Shader(osg::Shader::VERTEX);
        vShader->loadShaderSourceFromFile("./data/shader.vs");
    
        osg::ref_ptr<osg::Shader> fShader = new osg::Shader(osg::Shader::FRAGMENT);
        fShader->loadShaderSourceFromFile("./data/shader.fs");
    
        osg::ref_ptr<osg::Program> program = new osg::Program;
        program->addShader(vShader.get());
        program->addShader(fShader.get());
    
        program->addBindAttribLocation("MCvertex", 0);
        program->addBindAttribLocation("MCnormal", 2);
    
        osg::ref_ptr<osg::Uniform> M4 = new osg::Uniform("LightPosition", osg::Vec3d(0, 2, 0));
        stateSet->addUniform(M4.get());
    
        stateSet->setAttributeAndModes(program.get(), osg::StateAttribute::ON);
        osg::ref_ptr<osg::Group> root = new osg::Group;
        root->addChild(geode);
    
        viewer->setSceneData(root);
        viewer->setUpViewInWindow(35, 35, 1024, 800);
    
        viewer->realize();
        osg::ref_ptr<osg::State> state = viewer->getCamera()->getGraphicsContext()->getState();
        state->setUseModelViewAndProjectionUniforms(true);
    
        return viewer->run();
    
    }

     下面的main.cpp添加了一些与shader无关的东西,在上面的main.cpp中我拿掉了,并把shader提出去了,看着头疼。

    main.cpp

    #include <osgViewer/Viewer>
    #include <osgDB/ReadFile>
    #include <osg/Shape>
    #include <osg/Shapedrawable>
    #include <osg/MatrixTransform>
    
    static char * vertexShader = {
        "#version 140        
    "
        //顶点
        "in vec4 MCvertex; 
    "
        //法线
        "in vec3 MCnormal;        
    "
        //怀疑这些以osg_打头的都是osg的内置变量
        "in vec3 osg_SimulationTime;        
    "
        "uniform mat4 osg_ModelViewMatrix;    
    "
        "uniform mat4 osg_ModelViewProjectionMatrix;
    "
        "uniform mat3 osg_NormalMatrix;
    "
        
        //光照位置
        "uniform vec3 LightPosition ;
    "
        //镜面光强度
        "const float SpecularContribution = 0.3;
    "
        //散射光强度
        "const float DiffuseContribution = 1.0 - SpecularContribution;
    "
        //光照强度值
        "out float LightIntensity;
    "
        //顶点的x,y值
        "out vec2 MCposition;
    "
        "void main()
    "
        "{
    "
        //物体坐标系->世界坐标系->相机坐标系的转换
        "      vec3 ecPosition = vec3(osg_ModelViewMatrix * MCvertex);        
    "
        //法线转到相机坐标系
        "      vec3 tnorm = normalize(osg_NormalMatrix * MCnormal);        
    "
            //光照的方向
        "      vec3 lightVec = normalize(vec3(LightPosition[0],LightPosition[1],LightPosition[2]*osg_SimulationTime) - ecPosition);    
    "
        //计算出反射方向
        "      vec3 reflectVec = reflect(-lightVec, tnorm);        
    "
        "      vec3 viewVec = normalize(-ecPosition);    
    "
        "      float diffuse = max(dot(lightVec, tnorm), 0.0);    
    "
        "      float spec = 0.0;        
    "
        "      if (diffuse > 0.0)    
    "
        "   {
    "
        "          spec = max(dot(reflectVec, viewVec), 0.0);
    "
        "          spec = pow(spec, 16.0);
    "
        "     }
    "
        "      LightIntensity = DiffuseContribution * diffuse + SpecularContribution * spec;
    "
        "      MCposition = MCvertex.xy;
    "
        "      gl_Position = osg_ModelViewProjectionMatrix * MCvertex;
    "
        "} 
    "
    };
    
    
    static char * fragShader = {
        " #version 140 
    "
        //转的颜色 和 砖缝的颜色
        " uniform vec3 BrickColor = vec3(0,1,0), MortarColor = vec3(1,0,0);
    "
        //转的长和宽
        " uniform vec2 BrickSize = vec2(0.3,0.15);
    "
        //砖的宽和高相对于砖缝的宽和高之间的比例
        " uniform vec2 BrickPct = vec2(0.9,0.85);
    "
        //顶点的x、y
        " in vec2 MCposition;
    "
        //光照强烈度
        " in float LightIntensity;
    "
        //片元颜色
        " out vec4 FragColor;
    "
        " void main()
    "
        " {
    "
        "     vec3 color;
    "
        "     vec2 position, useBrick;
    "
        //得到砖块行号和砖块列号
        "    position = MCposition / BrickSize;
    "
        //frack(x) = 1-floor(x),floor(x)=返回小于或等于x的最近整数。相当于取小数部分
        "      if (fract(position.y * 0.5) >= 0.5)
    "
        "                position.x += 0.5;
    "
        //计算片元在当前砖块中的位置(取小数部分)
        "        position = fract(position);
    "
        //step(edge0,x) 如果x>edge0,返回1,否则,返回0
        "        useBrick = step(position, BrickPct);
    "
        //mix(x,y,a)=x*(1.0-a)+y*a,其实可以简写,
        "        //color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);
    "
    
        "if(useBrick.x * useBrick.y == 0){ color = MortarColor; }else {color = BrickColor;}
    "
    
        "        color *= LightIntensity;
    "
        "        FragColor = vec4(color, 1.0);
    "
        "}
    "
    };
    
    osg::ref_ptr<osg::MatrixTransform> lightPos;
    
    class MyNodeVisitor : public osg::NodeVisitor
    {
    public:
        MyNodeVisitor() :osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){}
    
        virtual void apply(osg::Geode& node)
        {
            for (int i = 0; i < node.getNumParents(); ++i)
            {
                osg::ref_ptr<osg::Geometry> polyGeom = dynamic_cast<osg::Geometry*>(node.getDrawable(i));
    
                if (!polyGeom)return;
    
                polyGeom->setVertexAttribArray(0, polyGeom->getVertexArray());
                polyGeom->setVertexAttribBinding(0, osg::Geometry::BIND_PER_VERTEX);
                polyGeom->setVertexAttribArray(1, polyGeom->getColorArray());
                polyGeom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);
                polyGeom->setVertexAttribArray(2, polyGeom->getNormalArray());
                polyGeom->setVertexAttribBinding(2, polyGeom->getNormalBinding());
            }
        }
    };
    
    
    class LightPosCallback : public osg::Uniform::Callback
    {
    public:
        LightPosCallback()
        {
        }
        virtual void operator()(osg::Uniform* uniform, osg::NodeVisitor* nv)
        {
            osg::Matrix m = lightPos->getMatrix();
            uniform->set(m.getTrans());
        }
    };
    
    osg::ref_ptr<osg::Node>  createlight()
    {
        osg::ref_ptr<osg::ShapeDrawable> sun_sd = new osg::ShapeDrawable;
        osg::ref_ptr<osg::Sphere> sun_sphere = new osg::Sphere;
        sun_sphere->setName("SunSphere");
        sun_sphere->setRadius(0.5);
        sun_sd->setShape(sun_sphere);
        sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
    
        osg::ref_ptr<osg::Geode> sun_geode = new osg::Geode;
        sun_geode->setName("SunGeode");
        sun_geode->addDrawable(sun_sd.get());
    
        return sun_geode;
    }
    
    
    class KeyboardEventHandler : public osgGA::GUIEventHandler
    {
    public:
    
        KeyboardEventHandler(){}
    
        virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&)
        {
            switch (ea.getEventType())
            {
            case(osgGA::GUIEventAdapter::KEYDOWN) :
                {
                    if (ea.getKey() == 'x')//绕x轴旋转
                    {
                        osg::Matrix trans = lightPos->getMatrix();
                        trans = trans * osg::Matrix::rotate(osg::PI_2 / 10, osg::X_AXIS);
                        lightPos->setMatrix(trans);
                    }
                    if (ea.getKey() == 'y')//绕y轴旋转
                    {
                        osg::Matrix trans = lightPos->getMatrix();
                        trans = trans * osg::Matrix::rotate(osg::PI_2 / 10, osg::Y_AXIS);
                        lightPos->setMatrix(trans);
                    }
                    if (ea.getKey() == 'z')//绕z轴旋转
                    {
                        osg::Matrix trans = lightPos->getMatrix();
                        trans = trans * osg::Matrix::rotate(osg::PI_2 / 10, osg::Z_AXIS);
                        lightPos->setMatrix(trans);
                    }
                }
            }
    
            return false;
        }
    };
    int main()
    {
        osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
        osg::ref_ptr<osg::Node> geode = osgDB::readNodeFile("cow.osg");//CreateNode();
    
        MyNodeVisitor visitor;
        geode->accept(visitor);
    
    
        osg::ref_ptr<osg::StateSet> stateSet = geode->getOrCreateStateSet();
    
        osg::ref_ptr<osg::Shader> vShader = new osg::Shader(osg::Shader::VERTEX, vertexShader);
        osg::ref_ptr<osg::Shader> fShader = new osg::Shader(osg::Shader::FRAGMENT, fragShader);
        osg::ref_ptr<osg::Program> program = new osg::Program;
        program->addShader(vShader.get());
        program->addShader(fShader.get());
    
        program->addBindAttribLocation("MCvertex", 0);
        program->addBindAttribLocation("MCnormal", 2);
    
    
    
        osg::ref_ptr<osg::Uniform> M4 = new osg::Uniform("LightPosition", osg::Vec3d(2, 0, 0));
        M4->setUpdateCallback(new LightPosCallback());
        stateSet->addUniform(M4.get());
    
        stateSet->setAttributeAndModes(program.get(), osg::StateAttribute::ON);
    
        lightPos = new osg::MatrixTransform;
        lightPos->setMatrix(osg::Matrix::translate(0, 0, 5));
        lightPos->addChild(createlight());
    
     osg::ref_ptr<osg::Group> root = new osg::Group;
        //root->addChild(osgDB::readNodeFile("d:/ah64_apache.3ds"));
        root->addChild(lightPos.get());
        root->addChild(geode);
    
    
        viewer->addEventHandler(new KeyboardEventHandler());
        viewer->setSceneData(root);
        viewer->setUpViewInWindow(35, 35, 1024, 800);
    
        viewer->realize();
        osg::ref_ptr<osg::State> state = viewer->getCamera()->getGraphicsContext()->getState();
        state->setUseModelViewAndProjectionUniforms(true);
    
    
        return viewer->run();
    
    }
  • 相关阅读:
    软件工程课程总结
    c++第五次作业
    软件工程第四次作业
    c++第四次作业
    软件工程第三次作业
    c++第三次作业
    软件工程基础第二次作业
    c++第二次作业
    c++第一次作业
    软件工程基础第一次作业
  • 原文地址:https://www.cnblogs.com/airduce/p/10062747.html
Copyright © 2020-2023  润新知