每个对象的GLSL统一

时间:2017-07-02 01:48:20

标签: opengl glsl fragment-shader openscenegraph

目前我在GLSL着色器上处理制服时遇到问题。如果我在场景中只有一个物体,那么制服就像我期望的那样工作。但是,对于多个对象,不为每个对象设置制服,换句话说,最后一个制服用于表示所有场景对象。

我该如何处理这个问题?遵循我的C ++代码:

void addSimpleObject(osg::ref_ptr<osg::Group> root, osg::Vec3 position, float radius, float myUniform) {

    osg::ref_ptr<osg::Geode> geode = new osg::Geode();
    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(position, radius)));
    root->addChild(geode);
    root->getChild(0)->asGeode()->addDrawable(geode->getDrawable(0));

    osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
    stateset->addUniform(new osg::Uniform("myUniform", myUniform));
    root->setStateSet(stateset);
}


osg::ref_ptr<osg::Group> root = new osg::Group();
addSimpleObject(root, osg::Vec3(-3.0,  2.5, -10), 2, 0.5);
addSimpleObject(root, osg::Vec3( 3.0,  2.5, -10), 2, 1.5);
addSimpleObject(root, osg::Vec3( 0.0, -2.5, -10), 2, 1.0);

顶点着色器:

#version 130

out vec3 pos;
out vec3 normal;

void main() {
    pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
    normal = gl_NormalMatrix * gl_Normal;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

片段着色器:

#version 130

in vec3 pos;
in vec3 normal;

uniform float myUniform;

void main() {
    vec3 normNormal;

    normNormal = normalize(normal);

    if (myUniform > 0)
        normNormal = min(normNormal * myUniform, 1.0);

    ...
}

image output

1 个答案:

答案 0 :(得分:3)

制服绑定到着色器程序而不是“对象”。 如果对所有对象使用相同的程序,则必须在绘制对象之前设置制服。

您将osg::StateSet绑定到场景图的根节点。 如果统一变量的值对于每个drawable都要更改,则必须添加 每个osg::StateSet节点分隔osg::Drawable

像这样调整您的方法addSimpleObject

void addSimpleObject(osg::ref_ptr<osg::Group> root, osg::Vec3 position, float radius, float myUniform) {

    // create the drawable 
    osg::ref_ptr<osg::Drawable> drawable = new osg::ShapeDrawable(new osg::Sphere(position, radius))

    // crate the stateset and add the uniform
    osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
    stateset->addUniform(new osg::Uniform("myUniform", myUniform));

    // add the stateset tor the drawable
    drawable->setStateSet(stateset);

    if (root->getNumChildren() == 0) {
        osg::ref_ptr<osg::Geode> geode = new osg::Geode();
        root->addChild(geode);
    }
    root->getChild(0)->asGeode()->addDrawable(drawable);
}