OSG 砖块 shader 例子 GLSL

 按键 x y z 可以调节灯光位置

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Shape>
#include <osg/Shapedrawable>
#include <osg/MatrixTransform>
 
static char * vertexShader = {
    "#version 140        \n"
    "in vec4 MCvertex; \n"
    "in vec3 MCnormal;        \n"
    "in vec3 osg_SimulationTime;        \n"
    "uniform mat4 osg_ModelViewMatrix;    \n"
    "uniform mat4 osg_ModelViewProjectionMatrix;\n"
    "uniform mat3 osg_NormalMatrix;\n"
    "uniform vec3 LightPosition ;\n"
    "const float SpecularContribution = 0.3;\n"
    "const float DiffuseContribution = 1.0 - SpecularContribution;\n"
    "out float LightIntensity;\n"
    "out vec2 MCposition;\n"
    "void main()\n"
    "{\n"
    "      vec3 ecPosition = vec3(osg_ModelViewMatrix * MCvertex);        \n"
    "      vec3 tnorm = normalize(osg_NormalMatrix * MCnormal);        \n"
    "      vec3 lightVec = normalize(vec3(LightPosition[0],LightPosition[1],LightPosition[2]*osg_SimulationTime) - ecPosition);    \n"
    "      vec3 reflectVec = reflect(-lightVec, tnorm);        \n"
    "      vec3 viewVec = normalize(-ecPosition);    \n"
    "      float diffuse = max(dot(lightVec, tnorm), 0.0);    \n"
    "      float spec = 0.0;        \n"
    "      if (diffuse > 0.0)    \n"
    "   {\n"
    "          spec = max(dot(reflectVec, viewVec), 0.0);\n"
    "          spec = pow(spec, 16.0);\n"
    "     }\n"
    "      LightIntensity = DiffuseContribution * diffuse + SpecularContribution * spec;\n"
    "      MCposition = MCvertex.xy;\n"
    "      gl_Position = osg_ModelViewProjectionMatrix * MCvertex;\n"
    "} \n"
};
 
 
static char * fragShader = {
    " #version 140 \n"
    " uniform vec3 BrickColor = vec3(0,1,1), MortarColor = vec3(1,0,1);\n"
    " uniform vec2 BrickSize = vec2(0.3,0.15);\n"
    " uniform vec2 BrickPct = vec2(0.9,0.85);\n"
    " in vec2 MCposition;\n"
    " in float LightIntensity;\n"
    " out vec4 FragColor;\n"
    " void main()\n"
    " {\n"
    "     vec3 color;\n"
    "     vec2 position, useBrick;\n"
    "    position = MCposition / BrickSize;\n"
    "      if (fract(position.y * 0.5) > 0.5)\n"
    "                position.x += 0.5;\n"
    "        position = fract(position);\n"
    "        useBrick = step(position, BrickPct);\n"
    "        color = mix(MortarColor, BrickColor, useBrick.x * useBrick.y);\n"
    "        color *= LightIntensity;\n"
    "        FragColor = vec4(color, 1.0);\n"
    "}\n"
};
osg::Node *  CreateNode()
{
    osg::Geode * geode = new osg::Geode;
    osg::Geometry* polyGeom = new osg::Geometry();
    osg::Vec3Array* vertices = new osg::Vec3Array();
    vertices->push_back(osg::Vec3(-10, 0, 0));
    vertices->push_back(osg::Vec3(10, 0, 0));
    vertices->push_back(osg::Vec3(0, 10, 10));
    polyGeom->setVertexArray(vertices);
 
 
    osg::ref_ptr<osg::Vec4Array> colorsArray = new osg::Vec4Array;
    colorsArray->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    colorsArray->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
    colorsArray->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
    polyGeom->setColorArray(colorsArray.get());
    polyGeom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
 
    osg::Vec3Array* normals = new osg::Vec3Array;
    normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
    normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
    normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
    polyGeom->setNormalArray(normals);
    polyGeom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
 
 
    polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, 3));
 
    polyGeom->setVertexAttribArray(0, vertices);
    polyGeom->setVertexAttribBinding(0, osg::Geometry::BIND_PER_VERTEX);
    polyGeom->setVertexAttribArray(1, colorsArray.get());
    polyGeom->setVertexAttribBinding(1, osg::Geometry::BIND_PER_VERTEX);
    polyGeom->setVertexAttribArray(2, normals);
    polyGeom->setVertexAttribBinding(2, osg::Geometry::BIND_PER_VERTEX);
 
    geode->addDrawable(polyGeom);
    return geode;
}
 
 
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::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::Node * createlight()
{
    osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
    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::Geode* sun_geode = new osg::Geode;
    sun_geode->setName("SunGeode");
    sun_geode->addDrawable(sun_sd);
 
    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::Group * root = new osg::Group;
    //root->addChild(osgDB::readNodeFile("d:/ah64_apache.3ds"));
    root->addChild(lightPos);
    root->addChild(geode);
 
 
    viewer->addEventHandler(new KeyboardEventHandler());
    viewer->setSceneData(root);
    viewer->setUpViewInWindow(35, 35, 1024, 800);
 
    viewer->realize();
    osg::State* state = viewer->getCamera()->getGraphicsContext()->getState();
    state->setUseModelViewAndProjectionUniforms(true);
 
 
    return viewer->run();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值