转换 OpenGL 固定功能代码以使用着色器

问题描述 投票:0回答:1

我正在将固定函数(使用显示列表)OpenGL 实现转换为使用 OpenGL 现代方法(着色器)

该应用程序是一个雷达扫描转换器,它将矩形纹理映射到我的顶点网格(如果有意义的话)。纹理大小为2k * 2k

(我正在使用 Qt OpenGl 包装类)

显示列表为每个雷达辐条及其相邻辐条创建一个四边带。因此将有 2k 个四边形条带进行渲染。代码如下

glNewList(displayList, GL_COMPILE);
glEnable(GL_TEXTURE_2D);
GLuint texture = m_radarView->texture()->textureId();
glBindTexture(GL_TEXTURE_2D, texture);

for(uint azimuth = 0 ; azimuth < azimuthSamples;  ++azimuth)
{
    auto azimuth2 = azimuth+1;

    if (azimuth2 >= azimuthSamples)
        azimuth2 = 0;

    glBegin(GL_QUAD_STRIP);
    GLfloat atex = (azimuth * atexd) + (atexd / 2.0), atex2 = azimuth2 != 0 ? (azimuth2 * atexd) + (atexd / 2.0) : 1.0;
    const QList<QPointF> &line1 = watcher->resultAt(azimuth), &line2 = watcher->resultAt(azimuth2);
    for(int range = 0; range < rangeSamples; range++)
    {
        glTexCoord2f((rtexd * range) + (rtexd / 2.0), atex);
        glVertex3f(line1.at(range).x(), line1.at(range).y(), 0.0);
        glTexCoord2f((rtexd * range) + (rtexd / 2.0), atex2);
        glVertex3f(line2.at(range).x(), line2.at(range).y(), 0.0);
    }
    glEnd();
}
glBindTexture(GL_TEXTURE_2D, 0);
glEndList();

我渲染成这样

glCallList(displayList);

这工作正常(显示任意目标放大)

所以我尝试使用现代方法着色器、VBO 和 VAO 来复制这一点

m_vao = new QOpenGLVertexArrayObject(this);
m_vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);

m_vao->create();
m_vbo->setUsagePattern(QOpenGLBuffer::DynamicDraw);
m_vbo->create();

auto numVertices = textureSize().width() * textureSize().height() * 2;
auto verticesSize = numVertices * sizeof(QVector2D);
auto textureSize = numVertices * sizeof(QVector2D);
auto textureOffset = verticesSize;

m_vao->bind();
m_vbo->bind();

//the VAO must be bound here - this is part of the VAO state
m_vbo->allocate(verticesSize + textureSize);

shaderProgram()->bind();
const int vertexLocation = 1;
shaderProgram()->enableAttributeArray(vertexLocation);
shaderProgram()->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 2);
const int texLocation = 2;
shaderProgram()->enableAttributeArray(texLocation);
shaderProgram()->setAttributeBuffer(texLocation, GL_FLOAT, textureOffset, 2);

m_vao->release();
m_vbo->release();
shaderProgram()->release();

创建顶点和纹理坐标并写入VBO(与displayList实现类似的循环

//map each cartesian point to a texture coordinate - one quad strip for each azimuth spoke
for(uint azimuth = 0 ; azimuth < azimuthSamples;  ++azimuth)
{
    auto azimuth2 = azimuth+1;

    if (azimuth2 >= azimuthSamples)
        azimuth2 = 0;

    const QList<QPointF> &line1 = watcher->resultAt(azimuth), &line2 = watcher->resultAt(azimuth2);

    auto atex = (azimuth * atexd) + (atexd / 2.0), atex2 = azimuth2 != 0 ? (azimuth2 * atexd) + (atexd / 2.0) : 1.0;

    for (uint range = 0; range < rangeSamples; ++range)
    {
        vertices.append(QVector2D(line1.at(range).x(), line1.at(range).y()));
        textCords.append(QVector2D((rtexd * range) + (rtexd / 2.0), atex));
        vertices.append(QVector2D(line2.at(range).x(), line2.at(range).y()));
        textCords.append(QVector2D((rtexd * range) + (rtexd / 2.0), atex2));
        Q_ASSERT(textCords.last().x()<=1.0 && textCords.last().y()<=1.0);
    }
}

m_vbo->bind();
auto verticesSize = vertices.size() * sizeof(QVector2D);
auto textureSize = textCords.size() * sizeof(QVector2D);
m_vbo->write(0, vertices.constData(), verticesSize);
m_vbo->write(verticesSize, textCords.constData(), textureSize);
m_vbo->release();

然后在渲染中

 shaderProgram()->bind();
 shaderProgram()->setUniformValue(shaderProgram()->uniformLocation("modelViewMatrix"), projection);

//explicitly set the texture unit 
shaderProgram()->setUniformValue("bscan", 0);
texture()->bind(); 
m_vao->bind();
**//is this correct ? should this be in a loop ?**
glDrawArrays(GL_QUAD_STRIP, 0, textureSize().width() * textureSize().height() * 2);
m_vao->release();
shaderProgram()->release();
texture()->release();

目标放大后的结果如下所示

正如你所看到的,它有点粗糙(放大镜使用线性正确设置,纹理是8位亮度格式)

应该

glDrawArrays(GL_QUAD_STRIP, 0, textureSize().width() * textureSize().height() * 2);

这可以循环执行(每个方位角轮辐一个)?

知道是什么原因造成的吗?

c++ qt opengl gldrawarrays
1个回答
0
投票

这应该在循环中调用 - 不知道它是如何工作的

glDrawArrays(GL_QUAD_STRIP, 0, textureSize().width() * textureSize().height() * 2);

每个四边形条一次

auto verticesPerQuadStrip = texture()->height() * 2;
for (int i = 0; i < textureSize().width(); ++i)
    glDrawArrays(GL_QUAD_STRIP, i * verticesPerQuadstrip, verticesPerQuadstrip);
© www.soinside.com 2019 - 2024. All rights reserved.