1

everyone,

I am using vertex attribute in a vertex shader with OSG. I followed the routine which includes addBindAttribLocation and setVertexAttribArray. The problem is that if I use VBO, then the vertex attribute cannot be passed to vertex shader. Only if I use DisplayList, can the vertex attribute be passed to the vertex shader.

The code is shown below. In the code, I want to show the four vertices in different colors which is denoted by the vertAttrib:

osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(4);
osg::ref_ptr<osg::FloatArray> vertAttrib = new osg::FloatArray(4);
osg::ref_ptr<osg::DrawElementsUInt> pointIdx = new osg::DrawElementsUInt(osg::PrimitiveSet::POINTS, 4);
(*vertices)[0] = osg::Vec3(0, 0, 0); (*vertAttrib)[0] = 1; (*pointIdx)[0] = 0;
(*vertices)[1] = osg::Vec3(0, 1, 0); (*vertAttrib)[1] = 2; (*pointIdx)[1] = 1;
(*vertices)[2] = osg::Vec3(1, 1, 0); (*vertAttrib)[2] = 3; (*pointIdx)[2] = 2;
(*vertices)[3] = osg::Vec3(1, 0, 0); (*vertAttrib)[3] = 4; (*pointIdx)[3] = 3;

geometry = new osg::Geometry;
geometry->setUseVertexBufferObjects(true);
geometry->setUseDisplayList(false);

geometry->setVertexArray(vertices.get());
geometry->setVertexAttribArray(10, vertAttrib.get(), osg::Array::BIND_PER_VERTEX);
geometry->addPrimitiveSet(pointIdx.get());
static const char *vertSource = {
    "attribute float myAttrib;\n"
    "varying float attrib;\n"
    "void main()\n"
    "{\n"
    "   attrib = myAttrib;\n"
    "   gl_Position = ftransform();"
    "   gl_PointSize = 50.0;\n"
    "}\n"
};

static const char *fragSource = {
    "varying float attrib;\n"
    "void main()\n"
    "{\n"
    "   if(attrib < 1.2){\n"
    "      gl_FragColor = vec4(1.0, 0, 0, 1.0);\n"
    "   }else if(attrib <2.2){\n"
    "      gl_FragColor = vec4(0.0, 1.0, 0, 1.0);\n"
    "   }else if(attrib < 3.2){\n"
    "      gl_FragColor = vec4(0.0, 0, 1.0, 1.0);\n"
    "   }else{\n"
    "      gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
    "   }\n"
    "}\n"
};

osg::Geode* geode = new osg::Geode;
osg::StateSet* stateset = new osg::StateSet;

osg::ref_ptr<osg::Program> program;
osg::ref_ptr<osg::Shader> vertShader = new osg::Shader(osg::Shader::VERTEX, vertSource);
osg::ref_ptr<osg::Shader> fragShader = new osg::Shader(osg::Shader::FRAGMENT, fragSource);

program = new osg::Program;
program->addShader(vertShader.get());
program->addShader(fragShader.get());

program->addBindAttribLocation("myAttrib", 10);
stateset->setAttributeAndModes(program.get(), osg::StateAttribute::ON);
stateset->setMode(GL_VERTEX_PROGRAM_POINT_SIZE, osg::StateAttribute::ON);
geode->setStateSet(stateset);
geode->addDrawable(geometry.get());

The running result shows that the vertAttrib has never been correctly passed to the vertex shader and the four vertices are all in red. The fact is, I found that in the fragment shader, all the attribs' values are 0.

What am I missing? Any suggestions are appreciated! Thanks.

Jimmy Chen
  • 490
  • 3
  • 13

0 Answers0