osg中运用Shader(osg初级篇2)

关于shader的概念,可以参见我的另一篇博客《opengl版本发展史及各种概念的厘清》,这里列举一个例子,用来实现一个特效,屏幕的左半部显示为红色。首先我们准备好两个shader程序:


static const char* gl3_VertexShader = {
    "#version 330 core\n"
    "in vec4 osg_Vertex;\n"
    "in vec4 osg_Color;\n"
    "in vec4 osg_MultiTexCoord0;\n"
    "uniform mat4 osg_ModelViewProjectionMatrix;\n"
    "out vec2 texCoord;\n"
    "out vec4 vertexColor;\n"
    "void main(void)\n"
    "{\n"
    "    gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n"
    "    texCoord = osg_MultiTexCoord0.xy;\n"
    "    vertexColor = osg_Color; \n"
    "}\n"
};

static const char* gl3_FragmentShader = {
    "#version 330 core\n"
    "uniform sampler2D baseTexture;\n"
    "in vec2 texCoord;\n"
    "in vec4 vertexColor;\n"
    "out vec4 color;\n"
    "void main(void)\n"
    "{\n"
    "    color = vertexColor * texture(baseTexture, texCoord);\n"
    "}\n"
};

这两段代码是OSG提供的默认的shader功能,从stateset中摘抄过来的。为了实现屏幕的左半部显示为红色的特效,我们重新定义一个fragment shader


static const char* sh1 = {
    "#version 330 core\n"
    "uniform sampler2D baseTexture;\n"
    "in vec2 texCoord;\n"
    "in vec4 vertexColor;\n"
    "out vec4 color;\n"
    "void main(void)\n"
    "{\n"
    "    color = vertexColor * texture(baseTexture, texCoord);\n"
    "    if(texCoord.x < 0.5){\n"
    "        color = vec4(1,0,0,1);\n"
    "    }\n"
    "}\n"
};

OSG中与shader相关的有两个类:osg::Program 和 osg::Shader.  osg::shader与具体的顶点shader或fragment shader 相关,而Program类封装了shader的编译链接等工作。使用这两个类的方法特别简单

        /*set default shaders*/
        osg::ref_ptr<osg::Program> program = new osg::Program;
        program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_VertexShader));
        program->addShader(new osg::Shader(osg::Shader::FRAGMENT, sh1));
        stateset->setAttribute(program.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
        stateset->setTextureAttributeAndModes(0, _texture2D, osg::StateAttribute::ON);
        stateset->setTextureAttributeAndModes(1, _depthTexture, osg::StateAttribute::ON);

上面的代码段使用了两种shader,vertex shader 与 fragment shader总是成对出现。stateset是某个node的状态集,我门对上篇博客《osg中实现HUD(OSG初级篇1)》的代码进行修改,验证本article的结论,完整代码如下:

static const char* gl3_VertexShader = {
    "#version 330 core\n"
    "in vec4 osg_Vertex;\n"
    "in vec4 osg_Color;\n"
    "in vec4 osg_MultiTexCoord0;\n"
    "uniform mat4 osg_ModelViewProjectionMatrix;\n"
    "out vec2 texCoord;\n"
    "out vec4 vertexColor;\n"
    "void main(void)\n"
    "{\n"
    "    gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex;\n"
    "    texCoord = osg_MultiTexCoord0.xy;\n"
    "    vertexColor = osg_Color; \n"
    "}\n"
};

static const char* gl3_FragmentShader = {
    "#version 330 core\n"
    "uniform sampler2D baseTexture;\n"
    "in vec2 texCoord;\n"
    "in vec4 vertexColor;\n"
    "out vec4 color;\n"
    "void main(void)\n"
    "{\n"
    "    color = vertexColor * texture(baseTexture, texCoord);\n"
    "}\n"
};

static const char* sh1 = {
    "#version 330 core\n"
    "uniform sampler2D baseTexture;\n"
    "in vec2 texCoord;\n"
    "in vec4 vertexColor;\n"
    "out vec4 color;\n"
    "void main(void)\n"
    "{\n"
    "    color = vertexColor * texture(baseTexture, texCoord);\n"
    "    if(texCoord.x < 0.5){\n"
    "        color = vec4(1,0,0,1);\n"
    "    }\n"
    "}\n"
};




osg::Geometry* createQuad(int screen_width, int screen_heigh, float z) {
    osg::Geometry* polyGeom = new osg::Geometry();
    polyGeom->setSupportsDisplayList(false);
    osg::Vec3Array* vertices = new osg::Vec3Array;
    osg::Vec2Array* texcoords = new osg::Vec2Array;
    osg::Vec4Array* colors = new osg::Vec4Array;

    /*four vertex*/
    vertices->push_back(osg::Vec3d(0, 0, z));
    texcoords->push_back(osg::Vec2f(0, 0));

    vertices->push_back(osg::Vec3d(screen_width, 0, z));
    texcoords->push_back(osg::Vec2f(1, 0));

    vertices->push_back(osg::Vec3d(screen_width, screen_heigh, z));
    texcoords->push_back(osg::Vec2f(1, 1));

    vertices->push_back(osg::Vec3d(0, screen_heigh, z));
    texcoords->push_back(osg::Vec2f(0, 1));
    /*four vertex*/
    colors->push_back(osg::Vec4f(1.0,1.0,1.0,1.0));
    colors->setBinding(osg::Array::BIND_OVERALL);

    /*set vertex array and tex coord array*/
    polyGeom->setVertexArray(vertices);
    polyGeom->setTexCoordArray(0, texcoords);
    polyGeom->setColorArray(colors);
    polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, vertices->size()));
    return polyGeom;
}



int
main(int argc, char** argv)
{

    // initialize a viewer:
    osgViewer::Viewer viewer;
    ///*create effect*/
    viewer.setUpViewAcrossAllScreens();
    osgViewer::Viewer::Windows windows;
    viewer.getWindows(windows);
    int screen_width = windows[0]->getTraits()->width;
    int screen_heigh = windows[0]->getTraits()->height;



    osg::Camera* camera = new osg::Camera;
    camera->setName("Hud Camera");
    // set the projection matrix
    camera->setProjectionMatrixAsOrtho2D(0, screen_width, 0, screen_heigh);
    camera->setViewport(0, 0, screen_width, screen_heigh);
    // set the view matrix
    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    camera->setViewMatrix(osg::Matrix::identity());
    camera->setClearColor(osg::Vec4(1, 0.5, 0.5, 0.5));
  
    /*create quad */
    osg::Geode* _geode = new osg::Geode();
    _geode->setName("GeodeOfHUD");
    osg::Geometry* polyGeom = createQuad(screen_width, screen_heigh, -100);
    polyGeom->setName("PolyGeomOfHUD_");
    _geode->addDrawable(polyGeom);
   
    osg::StateSet* stateset = _geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    /*set default shaders*/
    osg::ref_ptr<osg::Program> program = new osg::Program;
    program->addShader(new osg::Shader(osg::Shader::VERTEX, gl3_VertexShader));
    program->addShader(new osg::Shader(osg::Shader::FRAGMENT, sh1));
    stateset->setAttribute(program.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
    camera->addChild(_geode);
    viewer.setSceneData(camera);

    int r = viewer.run();
    return r;
}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值