目前我在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);
...
}
答案 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);
}