gpt4 book ai didi

c++ - 如何正确链接 OpenGL 着色器的开放式 GL 法线

转载 作者:行者123 更新时间:2023-11-28 02:52:39 29 4
gpt4 key购买 nike

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

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

struct Vertex
{
QVector3D position;
QVector3D normal;
};

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

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

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

unexpected rendering result

与法线贴图一样,红色=x、绿色=y 和蓝色=z。黑色方 block 的左上角是世界的原点。如您所见,法线在某个点似乎只是该点的位置,没有 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);

其中边界是多边形的几何连接组件。 程序是一个QOpenGLShaderProgram,一个Qt abstraction for shader programs .每个边界都绑定(bind)到一个缓冲区对象。缓冲区对象编号存储在数组 m_bufferObjects 中。多边形“边界”作为 struct 存储在数组 m_boundaries 中。它们有两个字段:data,一个指向循环顶点数组起点的指针,以及 sizeOfData,多边形的点数。

最佳答案

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

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

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

更新

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

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

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

要使用的正确 Qt 方法是 QOpenGLShaderProgramm::setAttribBuffer。不幸的是,您的代码没有显示 m_boundaries 的确切定义以及您对 glBufferDataglBufferSubData 的调用;如果我有,我可以指导您如何更改您的代码。

关于c++ - 如何正确链接 OpenGL 着色器的开放式 GL 法线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22683567/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com