Opengl隐藏了部分屏幕

时间:2017-03-22 10:55:37

标签: c opengl glfw

(代码片段。我知道它很难看,但我想让它变得更好才能让它更好,所以请不要过多关注结构)

我稍微修改了文档中存在的glfw示例,以便在按下右箭头键时旋转一个三角形,并绘制一个由其中一个顶点(在本例中为蓝色顶点)的位置描述的圆圈。 我只在初始化窗口时清除GL_COLOR_BUFFER_BIT以避免必须存储绘制线所需的所有坐标(在最终程序中它们将是数十万),这意味着每次都在屏幕上我按下右箭头,将三角形的“副本”绘制为旋转12度,绘制一条线,将旧的蓝色角度位置连接到新的角度位置。

现在的问题是我希望能够在保持画线的同时按下转义键GLFW_KEY_ESCAPE并“删除”三角形。

我尝试使用z缓冲区隐藏黑色矩形后面的三角形,但只显示最后画出的线条(我认为这是因为opengl不知道前一行的z,因为我不存储它们)。

有没有办法做我想要的,而不必存储所有的点坐标,然后清除整个屏幕并重新绘制线条?如果是这种情况,那么存储它们的最佳方式是什么?

以下是我到目前为止的部分代码。

bool check = 0;

Vertex blue = {0.f, 0.6f, 0.5f};
Vertex green = {0.6f,-0.4f, 0.5f};
Vertex red = {-0.6f, -0.4f, 0.5f};
Vertex line = {0.f, 0.6f, 0.f};
Vertex line2 = {0.f, 0.6f, 0.f};

static void
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        check = !check;
    if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
        line.x = line2.x;
        line.y = line2.y;
        rotation -= 12;
        rad = DegToRad(-12);
        double x = line.x*cos(rad) - line.y * sin(rad);
        double y = line.y * cos(rad) + line.x * sin(rad);
        line2.x = x;
        line2.y = y;
}

int main(void) {
    GLFWwindow *window;
    glfwSetErrorCallback(error_callback);
    if (!glfwInit())
        exit(EXIT_FAILURE);
    window = glfwCreateWindow(1280, 720, "Example", NULL, NULL);
    if (!window) {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, key_callback);
    glClear(GL_COLOR_BUFFER_BIT);
    while (!glfwWindowShouldClose(window)) {

        glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
        float ratio;
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        ratio = width / (float) height;
        glViewport(0, 0, width, height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
        glMatrixMode(GL_MODELVIEW);

        glLoadIdentity();
        glRotatef(rotation, 0.f, 0.f, 1.f);
        glBegin(GL_TRIANGLES);
        glColor3f(1.f, 0.f, 0.f);
        glVertex3f(red.x, red.y, red.z);
        glColor3f(0.f, 1.f, 0.f);
        glVertex3f(green.x, green.y, green.z);
        glColor3f(0.f, 0.f, 1.f);
        glVertex3f(blue.x, blue.y, blue.z);
        glEnd();

        glLoadIdentity();
        glLineWidth(1.0);
        glColor3f(1.0, 0.0, 0.0);
        glBegin(GL_LINES);
        glVertex3f(line.x, line.y, line.z);
        glVertex3f(line2.x, line2.y, line2.z);
        glEnd();

        if (check){
            //hide the triangles but not the lines
         }

        glEnd();


        glfwSwapBuffers(window);
        glfwPollEvents();

    }

    glfwDestroyWindow(window);
    glfwTerminate();
    exit(EXIT_SUCCESS);
}

1 个答案:

答案 0 :(得分:2)

  

仅在初始化窗口时清除GL_COLOR_BUFFER_BIT

那就是你的问题。在OpenGL中惯用的是始终以主帧缓冲区颜色位的清晰操作开始。也就是说,因为当操作系统要求重绘时,您不知道窗口主帧缓冲区的状态。对于所有你知道它可能已经被背景中的猫图片替换而没有你的程序知道它。说真的:如果你有一个猫视频正在运行,操作系统觉得需要重新安排你的窗口的主帧缓冲存储器,这就是你可能最终得到的结果。

  

有没有办法做我想要的,而不必存储所有的点坐标,然后清除整个屏幕并只重绘线条?

对于所有意图和目的:不。理论上,人们可以想出一个由一系列复杂的模板缓冲操作来实现的装置来实现它,但这会咆哮一个非常错误的树。

这是你可以尝试的东西:像你一样绘制一堆三角形,然后调整窗口大小以便没有任何剩余,然后将其调整回原来的大小......你看到问题在哪里?有办法解决这个特殊问题,但这不是你应该做的。

正确的是重绘一切。如果你觉得那样慢,你必须优化你的绘图过程。在当前的硬件上,每秒可以生成1亿个三角形的数量级。