2017-07-02 3 views
1

Actuellement, j'ai des problèmes en manipulant des uniformes sur les shaders GLSL. Si je n'ai qu'un seul objet dans la scène, l'uniforme fonctionne comme je l'espère. Cependant, pour plusieurs objets, l'uniforme n'est pas défini par objet, en d'autres termes, le dernier uniforme est utilisé pour représenter tous les objets de la scène.GLSL uniforme pour chaque objet

Comment puis-je gérer ce problème? Suit mon code 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); 

Le vertex shader:

#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; 
} 

Et le fragment shader:

#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

Un uniforme est lié à un programme de shaders pas un « objet ». Si vous utilisez le même programme pour tous les objets, vous devez définir l'uniforme avant de dessiner l'objet. – Rabbid76

+0

Salut @ Rabbid76, merci pour votre réponse. Pourriez-vous me donner un exemple? Comment puis-je réparer mon programme pour répondre à votre suggestion? –

Répondre

2

Un uniforme est lié à un programme de shaders ne pas un objet". Si vous utilisez le même programme pour tous les objets, vous devez définir l'uniforme avant de dessiner l'objet. Vous avez lié osg::StateSet au nœud racine du graphe de scène. Si la valeur de la variable uniforme change pour chaque retraitable, vous devez ajouter un osg::StateSet séparé à chaque noeud osg::Drawable.

Adapter votre méthode addSimpleObject comme ceci:

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); 
} 
+0

Salut @ Rabbid76, j'ai testé votre solution et cela a fonctionné! Merci beaucoup! –