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.