简体   繁体   English

如何正确链接OpenGL着色器的打开GL法线

[英]How to correctly link open GL normal for OpenGL shaders

I am trying to do a simple map rendered in OpenGL 2.1 and Qt5. 我正在尝试在OpenGL 2.1和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. 我有4个由三角形几何体组成的物体。 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. 简单的geoetry是一个动态分配的Vertex数组,其中Vertex是两个QVector3D ,Qt中预定义的3D位置类。

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. 与法线贴图一样,红色= x,绿色= y,蓝色= 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. 正如你所看到的那样,某些点处的法线似乎只是那个点的位置,没有z值。 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 . program是一个QOpenGLShaderProgram ,是着色器程序Qt抽象 Each boundary is bound to a buffer object. 每个边界都绑定到缓冲区对象。 The buffer object numbers are stored in the array m_bufferObjects . 缓冲区对象编号存储在数组m_bufferObjects Polygon “boundaries” are stored as struct in the array m_boundaries . 多边形“边界”作为struct存储在数组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. 它们有两个字段: data ,指向循环顶点数组起点的指针,以及sizeOfData ,即多边形的点数。

Until I get to the real problem of yours, here's something, probably unrelated but just as wrong: 在我找到你的真正问题之前,这里有些东西,可能是无关的,但同样是错误的:

glEnableClientState(GL_NORMAL_ARRAY);
/*...*/
glDisableClientState(GL_NORMAL_ARRAY);

You're using self defined vertex attributes, so it makes absolutely no sense to use those old fixed function pipeline client state locations. 您正在使用自定义顶点属性,因此使用那些旧的固定功能管道客户端状态位置绝对没有意义。 Use glEnableVertexAttribArray(location_index) instead, 请改用glEnableVertexAttribArray(location_index)

Update 更新

So I finally came around to take a closer look at your code and your problem is the mix of Qt's abstraction layer and use of raw OpenGL commands. 所以我终于来看看你的代码,你的问题是Qt的抽象层和原始OpenGL命令的混合使用。 Essentially your problem boils down to that you have a VBO bound when making calls to QOpenGLShaderProgram::setAttribArray followed by a call of glVertexAttribPointer . 基本上你的问题归结为你在调用QOpenGLShaderProgram::setAttribArray然后调用glVertexAttribPointer时绑定了一个VBO。

One problem is, that setAttribArray internally makes the call of glVertexAttribPointer for you, so your own call to it is redundant and overwrites whatever Qt's stuff did. 一个问题是, setAttribArray内部为你调用glVertexAttribPointer ,所以你自己调用它是多余的,并覆盖任何Qt的东西。 The more severe problem is, that you do have a VBO bound by glBindBuffer , so calls to glVertexAttribPointer actually take an byte offset into the VBO data instead of a pointer (in fact with a VBO bound passing a 0, which in pointer terms was a null pointer will yield a perfectly valid data offset). 更严重的问题是,你确实有一个由glBindBuffer绑定的VBO,所以对glVertexAttribPointer调用实际上是将一个字节偏移量放入VBO数据而不是一个指针(事实上,VBO绑定传递一个0,在指针术语中是一个空指针将产生完全有效的数据偏移量)。 See this answer by me, why this is all a bit misleading and actually violates the C specification: https://stackoverflow.com/a/8284829/524368 我看到这个答案,为什么这有点误导,实际上违反了C规范: https//stackoverflow.com/a/8284829/524368

Recent OpenGL versions actually have a new API for specifying attrib array offsets that conform to the C language specification. 最近的OpenGL版本实际上有一个新的API,用于指定符合C语言规范的attrib数组偏移量。

The correct Qt method to use would be QOpenGLShaderProgramm::setAttribBuffer . 要使用的正确Qt方法是QOpenGLShaderProgramm::setAttribBuffer Unfortunately your code shows not the exact definition of m_boundaries and your call to glBufferData or glBufferSubData ; 不幸的是,你的代码没有显示m_boundaries的确切定义以及你对glBufferDataglBufferSubData调用; if I had that I could give you instructions on how to alter your code. 如果我有,我可以给你关于如何改变你的代码的说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM