Opengl隐藏部分屏幕

Posted

技术标签:

【中文标题】Opengl隐藏部分屏幕【英文标题】:Opengl hide parts of the screen 【发布时间】:2017-03-22 10:55:37 【问题描述】:

(代码 sn-p。我知道它很丑,但我想在改进之前让它工作,所以请不要太在意结构)

我稍微修改了文档中的 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);

【问题讨论】:

那么你是想画一个线框吗? @Bartvbl 我的意图是画一个螺旋形图,为简单起见,我从一个简单的三角形开始画一个圆圈,一旦我可以让它正常工作就展开它 那你为什么不用线条来代替呢? 【参考方案1】:

我只在初始化窗口时清除 GL_COLOR_BUFFER_BIT

那是你的问题。 OpenGL 的惯用做法是始终从主帧缓冲区颜色位的清晰操作开始。也就是说,因为当操作系统要求重绘时,您不知道窗口主帧缓冲区的状态。据你所知,它可能在你的程序不知道的情况下被背景中的猫图片替换。说真的:如果您正在运行猫视频并且操作系统认为需要重新排列窗口的主帧缓冲区内存,那么您最终可能会遇到这种情况。

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

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

您可以尝试以下方法:像您一样绘制一堆三角形,然后将窗口缩小到没有任何残留物,然后将其调整回原来的大小……您明白问题出在哪里了吗?有一种方法可以解决这个特殊问题,但这不是你应该在这里做的。

正确的做法是重新绘制所有内容。如果你觉得这会变慢,你必须优化你的绘图过程。在当前这一代硬件上,每秒可以产生大约 1 亿个三角形。

【讨论】:

好的,谢谢,我想我正在寻找确认它不能“轻松”完成而不是继续思考这个问题 xD

以上是关于Opengl隐藏部分屏幕的主要内容,如果未能解决你的问题,请参考以下文章

在 iPhone 上加载 openGL 游戏的屏幕?

OpenGL工作流程

OpenGL-渲染流程

正在渲染opengl的随机屏幕片段-这表明啥错误?

使用 Qt5 进行屏幕外渲染(openGL)

Opengl 透明部分被渲染为黑色