You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用vector存储顶点属性时仅渲染单个矩形的问题求助

问题分析

你现在的核心问题是:当把多个矩形的顶点合并到一个vector后,绘制时仍然只使用了对应单个矩形的索引数量(6个),所以只会渲染第一个矩形。

原来循环调用descriptRender时,每次只传单个矩形的顶点,用6个索引刚好绘制这个矩形;现在合并所有顶点后,索引数组和绘制调用的参数都没有适配多矩形的情况。

具体问题点
  1. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 这里的第二个参数固定为6,只会绘制6个索引对应的三角形,也就是第一个矩形的两个三角形,后面的顶点根本没被用到。
  2. 传入的indices数组是针对单个矩形的,没有为后续的矩形生成偏移后的索引(比如第二个矩形的顶点索引应该从4开始,而不是0)。
修复方案

方案1:动态生成适配多矩形的索引数组

在render函数里,根据积累的顶点数量生成对应的索引数组,每个矩形对应6个偏移后的索引:

void engine::render(sectors* walls, int size, player player, trig math, unsigned VAO, unsigned VBO, unsigned EBO, unsigned shaderProgram) {
    float wx[4];
    float wy[4];
    float wz[4];
    int SW2 = 400;
    int SH2 = 300;
    float ps = math.SIN[player.a];
    float pc = math.COS[player.a];

    std::vector<float> points;
    std::vector<unsigned int> indices;
    int vertexCount = 0; // 记录当前已添加的顶点数(每个顶点对应2个float)

    for (int i = 0; i < size; i++) {
        int x1 = walls[i].x1 - player.x;
        int y1 = walls[i].y1 - player.y;

        int x2 = walls[i].x2 - player.x;
        int y2 = walls[i].y2 - player.y;
        // 旋转计算
        wx[0] = x1 * pc - y1 * ps;
        wy[0] = y1 * pc + x1 * ps;
        wz[0] = 0 - player.z;
        wz[2] = walls[i].z - player.z;
        wx[1] = x2 * pc - y2 * ps;
        wy[1] = y2 * pc + x2 * ps;
        wz[1] = 0 - player.z;
        wz[3] = walls[i].z - player.z;

        if (wy[0] > 0 && wy[1] > 0) {
            // 添加当前矩形的4个顶点
            points.push_back(wx[0] / wy[0]);
            points.push_back(wz[0] / wy[0]);
            points.push_back(wx[1] / wy[1]);
            points.push_back(wz[1] / wy[1]);
            points.push_back(wx[0] / wy[0]);
            points.push_back(wz[2] / wy[0]);
            points.push_back(wx[1] / wy[1]);
            points.push_back(wz[3] / wy[1]);

            // 为当前矩形生成偏移后的索引
            indices.push_back(vertexCount + 0);
            indices.push_back(vertexCount + 1);
            indices.push_back(vertexCount + 2);
            indices.push_back(vertexCount + 1);
            indices.push_back(vertexCount + 3);
            indices.push_back(vertexCount + 2);

            vertexCount += 4;
        }
    }

    if (!points.empty()) {
        descriptRender(points, indices.data(), indices.size(), VAO, VBO, EBO, shaderProgram);
    }
}

然后修改descriptRender函数,适配动态的索引数量:

void engine::descriptRender(std::vector<float> points, unsigned int* indices, unsigned int indexCount, unsigned int VAO, unsigned int VBO, unsigned int EBO, unsigned int shaderProgram) {
    glUseProgram(shaderProgram);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(float), points.data(), GL_STREAM_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(unsigned int), indices, GL_STREAM_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);

    glBindVertexArray(0);
    glUseProgram(0);
    std::cout << points.size() << std::endl;
}

方案2:改用glDrawArrays简化绘制(无需索引)

如果你的顶点顺序符合GL_TRIANGLE_STRIP的要求(比如每个矩形的4个顶点按左下-右下-左上-右上排列),可以直接用无索引绘制,省去索引数组的维护:
修改descriptRender函数:

void engine::descriptRender(std::vector<float> points, unsigned int VAO, unsigned int VBO, unsigned int shaderProgram) {
    glUseProgram(shaderProgram);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(float), points.data(), GL_STREAM_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    // 总顶点数为points.size()/2,每个矩形4个顶点用TRIANGLE_STRIP绘制
    glDrawArrays(GL_TRIANGLE_STRIP, 0, points.size() / 2);

    glBindVertexArray(0);
    glUseProgram(0);
    std::cout << points.size() << std::endl;
}

同时render函数不需要处理索引,直接调用修改后的descriptRender即可。

额外建议
  • 尽量不要每次渲染都调用glBufferData,可以改用glBufferSubData更新部分数据,提升性能。
  • 顶点属性指针和启用操作可以只在初始化VAO时执行一次,VAO会保存这些状态,无需每次渲染重复设置。

内容的提问来源于stack exchange,提问作者prarthik krishnan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:05:40