osg使用shader动态修改纹理坐标

#include <osg/Node>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Texture2D>
#include <osg/DrawPixels>
#include <osg/PolygonOffset>
#include <osg/Geode>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgText/Text>

#include <osgViewer/Viewer>

#include <osg/ShapeDrawable>

#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgDBd.lib")
#pragma comment(lib,"osgTextd.lib")
#pragma comment(lib,"osgViewerd.lib")
#endif

class TextureCoordUpdateCallback : public osg::NodeCallback
{
public:

    TextureCoordUpdateCallback(double delay = 1.0) :
        _delay(delay),
        _prevTime(0.0)
    {
    }

    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        if (nv->getFrameStamp())
        {
            double currTime = nv->getFrameStamp()->getSimulationTime();
            if (currTime - _prevTime > _delay)
            {
                osg::Geode* geode = node->asGeode();
                osg::Geometry* geom = geode->getDrawable(0)->asGeometry();
                // 获取纹理坐标数组
                osg::Array* tmp = geom->getTexCoordArray(0);
                osg::Vec2Array* coorArray = (osg::Vec2Array*) tmp;
                auto it = coorArray->begin();
                for (; it < coorArray->end(); it++)
                {
                    // 动起来
                    it->x() += 0.001;
                }
                // 更新纹理坐标数组
                geom->setTexCoordArray(0, coorArray);

                // record time
                _prevTime = currTime;
            }
        }
    }


protected:
    double                          _delay;
    double                          _prevTime;

};


osg::Node* createPyramidModel()
{
    // create the root node which will hold the model.
    osg::Group* root = new osg::Group();

    // turn off lighting
    root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);

    osg::Geode* pyramidGeode = new osg::Geode();
    osg::Geometry* pyramidGeometry = new osg::Geometry();
    pyramidGeode->setUpdateCallback(new TextureCoordUpdateCallback(0.01));
    pyramidGeode->setDataVariance(osg::Object::DYNAMIC);
    pyramidGeode->addDrawable(pyramidGeometry);
    root->addChild(pyramidGeode);

    osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
    pyramidVertices->push_back(osg::Vec3(0, 0, 0)); // 左前 
    pyramidVertices->push_back(osg::Vec3(10, 0, 0)); // 右前 
    pyramidVertices->push_back(osg::Vec3(10, 10, 0)); // 右后 
    pyramidVertices->push_back(osg::Vec3(0, 10, 0)); // 左后 
    pyramidVertices->push_back(osg::Vec3(5, 5, 10)); // 塔尖
    pyramidGeometry->setVertexArray(pyramidVertices);
    osg::DrawElementsUInt* pyramidBase = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidBase->push_back(3);
    pyramidBase->push_back(2);
    pyramidBase->push_back(1);
    pyramidBase->push_back(0);
    pyramidGeometry->addPrimitiveSet(pyramidBase);
    osg::DrawElementsUInt* pyramidFaceOne = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceOne->push_back(0);
    pyramidFaceOne->push_back(1);
    pyramidFaceOne->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceOne);
    osg::DrawElementsUInt* pyramidFaceTwo = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceTwo->push_back(1);
    pyramidFaceTwo->push_back(2);
    pyramidFaceTwo->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);
    osg::DrawElementsUInt* pyramidFaceThree = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceThree->push_back(2);
    pyramidFaceThree->push_back(3);
    pyramidFaceThree->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceThree);
    osg::DrawElementsUInt* pyramidFaceFour = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
    pyramidFaceFour->push_back(3);
    pyramidFaceFour->push_back(0);
    pyramidFaceFour->push_back(4);
    pyramidGeometry->addPrimitiveSet(pyramidFaceFour);

    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //红色    
    colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //绿色    
    colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //蓝色    
    colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); //白色
    pyramidGeometry->setColorArray(colors);
    pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

    osg::Vec3Array* normals = new osg::Vec3Array(1);
    (*normals)[0].set(0.0f, -1.0f, 0.0f);
    pyramidGeometry->setNormalArray(normals, osg::Array::BIND_OVERALL);

    osg::Vec2Array* texcoords = new osg::Vec2Array(5);
    (*texcoords)[0].set(0.00f, 0.0f);
    (*texcoords)[1].set(0.25f, 0.0f);
    (*texcoords)[2].set(0.50f, 0.0f);
    (*texcoords)[3].set(0.75f, 0.0f);
    (*texcoords)[4].set(0.50f, 1.0f);
    pyramidGeometry->setTexCoordArray(0, texcoords);

    // set up the texture state.
    osg::Texture2D* texture = new osg::Texture2D;
    texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
    texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
    texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
    texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
    texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
    texture->setImage(osgDB::readImageFile("Images/road.png"));
    osg::StateSet* stateset = pyramidGeometry->getOrCreateStateSet();
    stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);

    return root;
}

static char * fragShader = {
    "varying vec4 color;\n"
    "uniform sampler2D baseTex;\n"
    "uniform int osg_FrameNumber;\n"//当前OSG程序运行的帧数;
    "uniform float osg_FrameTime;\n"//当前OSG程序的运行总时间;
    "uniform float osg_DeltaFrameTime;\n"//当前OSG程序运行每帧的间隔时间;
    "uniform mat4 osg_ViewMatrix;\n"//当前OSG摄像机的观察矩阵;
    "uniform mat4 osg_ViewMatrixInverse;\n"// 当前OSG摄像机观察矩阵的逆矩阵。
    "void main(void){\n"
    "vec2 coord = gl_TexCoord[0].xy+vec2(0,osg_FrameTime*0.8);"
    "   gl_FragColor = texture2D(baseTex, coord);\n"
    "}\n"
};
osg::Node* createCone()
{
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    osg::ref_ptr<osg::Cone> cone = new osg::Cone(osg::Vec3(0, 0, 0), 1.0f, 5);
    osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable(cone.get());
    geode->addDrawable(shapeDrawable.get());

    // set up the texture state.
    osg::Texture2D* texture = new osg::Texture2D;
    //texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
    texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
    texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
    texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
    texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
    texture->setImage(osgDB::readImageFile("Images/test.jpg"));

    osg::StateSet* stateset = shapeDrawable->getOrCreateStateSet();
    stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
    osg::Program * program = new osg::Program;
    program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragShader));
    stateset->addUniform(new osg::Uniform("baseTex", 0));
    stateset->setAttributeAndModes(program, osg::StateAttribute::ON);

    return geode.release();
}
int main(int, char **)
{
    // construct the viewer.
    osgViewer::Viewer viewer;

    // add model to viewer.
    //viewer.setSceneData(createPyramidModel());
    viewer.setSceneData(createCone());

    return viewer.run();
}

 

转载于:https://www.cnblogs.com/coolbear/p/7662899.html

以下是一个简单的osg实现动态线的Shader代码示例: ``` // 顶点Shader const char* vsCode = "#version 120\n" "attribute vec3 aPosition;\n" "void main()\n" "{\n" " gl_Position = gl_ModelViewProjectionMatrix * vec4(aPosition, 1.0);\n" "}\n"; // 片段Shader const char* fsCode = "#version 120\n" "uniform vec4 uColor;\n" "void main()\n" "{\n" " gl_FragColor = uColor;\n" "}\n"; // 创建osg::Program和osg::Shader osg::ref_ptr<osg::Program> program = new osg::Program(); osg::ref_ptr<osg::Shader> vs = new osg::Shader(osg::Shader::VERTEX, vsCode); osg::ref_ptr<osg::Shader> fs = new osg::Shader(osg::Shader::FRAGMENT, fsCode); // 将Shader添加到Program中 program->addShader(vs); program->addShader(fs); // 创建osg::Geometry osg::ref_ptr<osg::Geometry> geom = new osg::Geometry(); // 创建osg::Vec3Array osg::ref_ptr<osg::Vec3Array> verts = new osg::Vec3Array(); verts->push_back(osg::Vec3(0.0f, 0.0f, 0.0f)); verts->push_back(osg::Vec3(1.0f, 0.0f, 0.0f)); // 将osg::Vec3Array设置为Geometry的顶点数据 geom->setVertexArray(verts.get()); // 设置Geometry的绘制模式为GL_LINE_STRIP geom->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, verts->size())); // 创建osg::Vec4Array osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(); colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 将osg::Vec4Array设置为Geometry的颜色数据 geom->setColorArray(colors.get()); geom->setColorBinding(osg::Geometry::BIND_OVERALL); // 设置Geometry的Shader程序 geom->getOrCreateStateSet()->setAttributeAndModes(program.get(), osg::StateAttribute::ON); // 设置Geometry的ColorUniform osg::ref_ptr<osg::Uniform> colorUniform = new osg::Uniform("uColor", osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); geom->getOrCreateStateSet()->addUniform(colorUniform.get()); ``` 此代码将创建一个包含两个点的动态线,并在此线上应用上述Shader程序。这将使线条以红色呈现。要添加更多的线段,只需添加更多的点到osg::Vec3Array中,并将GL_LINE_STRIP修改为GL_LINES。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值