【问题标题】:How to correctly link open GL normal for OpenGL shaders如何正确链接 OpenGL 着色器的开放 GL 法线
【发布时间】:2014-03-27 21:50:11
【问题描述】:

我正在尝试在 OpenGL 2.1 和 Qt5 中渲染一个简单的地图。但我在非常基本的问题上失败了。我在这里介绍的是表面法线。

我有 4 个由单个三角形几何构成的对象。简单来说,geoetry 是一个动态分配的 Vertex 数组,其中一个顶点是两个 QVector3D 的组合,这是 Qt 中预定义的 3D 位置类。

struct Vertex
{
    QVector3D position;
    QVector3D normal;
};

我通过使用从该顶点到下一个或上一个顶点的两个向量的叉积来计算顶点的法线。通过调试或将结果打印到控制台,结构的正常计算似乎很好。

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) 
...

但是当我将数据提供给着色器时,结果很荒谬!这是在每个位置用正常值着色的多边形的图片:

与法线贴图一样,红色=x,绿色=y,蓝色=z。黑色方块的左上角是世界的起源。如您所见,某个点的法线似乎只是该点的位置,没有 z 值。你能提示我可能出了什么问题,知道绘画代码是:

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);

其中边界是多边形的几何连通分量。 programQOpenGLShaderProgramQt abstraction for shader programs。每个边界都绑定到一个缓冲区对象。缓冲区对象编号存储在数组m_bufferObjects 中。多边形“边界”在数组m_boundaries 中存储为struct。它们有两个字段:data,指向循环顶点数组开始的指针,以及sizeOfData,多边形的点数。

【问题讨论】:

  • 将图片上传到 imgur.com 或类似网站,我会将其编辑到您的问题中。
  • 嗯,我清理了代码,现在我设法获得了看起来有些正确的 z 坐标,但没有更多的 x-y 坐标。代码如下:int vertexNormal = program.attributeLocation("vertexNormal"); int normalOffset = (GLbyte const*)(&amp;m_boundaries[i].data-&gt;normal) - (GLbyte const*)(m_boundaries[i].data) ; glVertexAttribPointer( vertexNormal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLbyte const*)(normalOffset) ); glEnableVertexAttribArray( vertexNormal );
  • 这里是原图:i57.tinypic.com/33e0rps.png

标签: c++ qt opengl qt5


【解决方案1】:

在我解决你真正的问题之前,这里有一些可能无关但同样错误的东西:

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

您使用的是自定义顶点属性,因此使用那些旧的固定功能管道客户端状态位置绝对没有意义。请改用glEnableVertexAttribArray(location_index)

更新

所以我终于来仔细看看你的代码,你的问题是 Qt 的抽象层和原始 OpenGL 命令的使用的混合。从本质上讲,您的问题归结为您在拨打QOpenGLShaderProgram::setAttribArray 之后调用glVertexAttribPointer 时绑定了VBO。

一个问题是,setAttribArray 在内部为您调用了glVertexAttribPointer,因此您自己对它的调用是多余的,并且会覆盖 Qt 所做的任何事情。更严重的问题是,您确实有一个由glBindBuffer 绑定的 VBO,因此对glVertexAttribPointer 的调用实际上将字节偏移量放入 VBO 数据而不是指针(实际上,VBO 绑定传递了一个 0,其中指针术语是一个空指针将产生一个完全有效的数据偏移量)。看到我的这个答案,为什么这有点误导,实际上违反了 C 规范:https://stackoverflow.com/a/8284829/524368

最近的 OpenGL 版本实际上有一个新的 API 用于指定符合 C 语言规范的属性数组偏移量。

正确使用的 Qt 方法是QOpenGLShaderProgramm::setAttribBuffer。不幸的是,您的代码未显示 m_boundaries 的确切定义以及您对 glBufferDataglBufferSubData 的调用;如果有的话,我可以告诉你如何修改你的代码。

【讨论】:

  • 谢谢,这是一次让所有东西都能正常工作的无望尝试,我会删除它。
  • 非常感谢! Acutally 删除其中一个冗余代码以某种方式破坏了事情。我现在只使用 OpenGL2.1(我需要在旧计算机上工作)函数调用并且它可以工作:` int vertexLocation = program.attributeLocation("vertexPosition"); glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); glEnableVertexAttribArray(vertexLocation);`我在文档中看不到方法QOpenGLShaderProgram::setAttribBufferqt-project.org/doc/qt-5/qopenglshaderprogram.html。如果可以的话,我会投票更新的答案。
  • 顺便说一下,m_boundaries 就是这个结构:struct SizeAwareArrayPointer { size_t sizeOfData; Vertex* data; };
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 2012-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多