I am trying to do a simple map rendered in OpenGL 2.1 and Qt5. But I'm failing on very basic issues. The one I'm presenting here is surface normals.
I have 4 object made of a single triangle geometry. A geoetry to make simple, is a dynamically allocated array of Vertex
, where a Vertex is a couple of two QVector3D
, a 3D position class predefined in Qt.
struct Vertex
{
QVector3D position;
QVector3D normal;
};
I'm computing the normal at a vertex by using the cross product of the two vectors from that vertex to the next or previous vertex. Normal computation for the structure seems fine, by debugging or printing results to the console.
QVector3D(-2, -2, -2) has normal QVector3D(0, 0, 1)
QVector3D(2, -2, -2) has normal QVector3D(0, 0, 1)
QVector3D(-2, 2, -2) has normal QVector3D(0, 0, 1)
...
But when I feed the data to the shaders, the result are absurd! Here is a picture of the polygons colored with the normal value at each position:
As in normal maps, red=x, green=y and blue=z. The top left corner of the black square is the origin of the world. As you can see the normal at some point seems to simply be the position at that point, without the z-value. Can you hint me what might be wrong, knowing the painting code is :
glUseProgram(program.programId());
glEnableClientState(GL_NORMAL_ARRAY);
program.setUniformValue("modelViewProjectionMatrix", viewCamera);
program.setUniformValue("entityBaseColor", QColor(0,120,233));
program.setUniformValue("sunColor", QColor("white"));
program.setUniformValue("sunBrightness", 1.0f);
static QVector3D tmpSunDir = QVector3D(0.2,-0.2,1.0).normalized();
program.setUniformValue("sunDir",tmpSunDir);
for( size_t i = 0; i < m_numberOfBoundaries; ++i)
{
glBindBuffer(GL_ARRAY_BUFFER, m_bufferObjects[i]);
int vertexLocation = program.attributeLocation("vertexPosition");
program.setAttributeArray( vertexLocation, GL_FLOAT, &(m_boundaries[i].data->position), sizeof(Vertex) );
program.enableAttributeArray(vertexLocation);
glVertexAttribPointer( vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0 );
int vertexNormal = program.attributeLocation("vertexNormal");
program.setAttributeArray( vertexNormal, GL_FLOAT, &(m_boundaries[i].data->normal), sizeof(Vertex) );
program.enableAttributeArray(vertexNormal);
glVertexAttribPointer( vertexNormal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0 );
glDrawArrays( GL_POLYGON, 0, m_boundaries[i].sizeOfData );
}
glDisableClientState(GL_NORMAL_ARRAY);
where a boundary is a geometrically connected component of the polygon. program
is a QOpenGLShaderProgram
, an Qt abstraction for shader programs. Each boundary is bound to a buffer object. The buffer object numbers are stored in the array m_bufferObjects
. Polygon “boundaries” are stored as struct
in the array m_boundaries
. They have two fields : data
, a pointer to the start of the array of vertices for the loop, and sizeOfData
, the number of points for the polygon.