如何使用 opengl 和 pyglet 设置剪切平面

Posted

技术标签:

【中文标题】如何使用 opengl 和 pyglet 设置剪切平面【英文标题】:How to set clipping planes with opengl and pyglet 【发布时间】:2018-06-12 18:24:57 【问题描述】:

我正在对我的代码的一个问题进行故障排除,即如果任何图元的深度值不为零,它将不会在屏幕上呈现。我怀疑它被剪掉了。

有没有一种简单的 Pythonic 方法可以在 pyglet 中设置我的剪切平面?

这是我目前的代码:

import pyglet
from pyglet.gl import *
import pywavefront
from camera import FirstPersonCamera


def drawloop(win,camera):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    #glClearColor(255,255,255,255)
    glLoadIdentity()
    camera.draw()

    pyglet.graphics.draw(2, pyglet.gl.GL_POINTS,
    ('v3f', (10.0, 15.0, 0.0, 30.0, 35.0, 150.0))
    )
    glPointSize(20.)
    return pyglet.event.EVENT_HANDLED


def main():
    win = pyglet.window.Window()
    win.set_exclusive_mouse(True)
    win.clear()
    camera = FirstPersonCamera(win)
    @win.event
    def on_draw(): 
        drawloop(win,camera)
    def on_update(delta_time):
        camera.update(delta_time)
    pyglet.clock.schedule(on_update)
    pyglet.app.run()

if __name__ == '__main__':
    main()

我在这里使用FirstPersonCamera sn-p:

https://gist.github.com/mr-linch/f6dacd2a069887a47fbc

【问题讨论】:

如何改进我的问题,使其更容易回答? 【参考方案1】:

我正在对我的代码的一个问题进行故障排除,即如果任何图元的深度值不为零,它将不会在屏幕上呈现。我怀疑它被剪掉了。

你必须建立一个投影矩阵来解决这个问题。要么设置正交投影矩阵,要么设置透视投影矩阵。

投影矩阵描述了从场景上的 3D 点到视口上的 2D 点的映射。它从眼睛空间变换到剪辑空间,剪辑空间中的坐标通过除以剪辑坐标的w 分量转换为标准化设备坐标(NDC)。 NDC 在 (-1,-1,-1) 到 (1,1,1) 的范围内。 超出裁剪空间的每个几何图形都会被裁剪。

在正交投影中,视图空间中的坐标线性映射到剪辑空间坐标,剪辑空间坐标等于标准化设备坐标,因为w 分量为 1(对于笛卡尔输入坐标)。 left、right、bottom、top、near 和 far 的值定义了一个框。盒子体积内的所有几何图形在视口上都是“可见的”。

在透视投影中,投影矩阵描述了从针孔相机看到的世界中的 3D 点到视口的 2D 点的映射。 相机平截头体(截断的金字塔)中的眼睛空间坐标映射到立方体(标准化设备坐标)。

要设置投影矩阵,投影矩阵堆栈必须由glMatrixMode 选择。

可以通过glOrhto设置正交投影:

w, h = 640, 480 # default pyglet window size

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho( -w/2, w/2, -h/2, h/2, -1000.0, 1000.0) # [near, far] = [-1000, 1000]

glMatrixMode(GL_MODELVIEW)
....

可以通过gluPerspective设置透视投影:

w, h = 640, 480 # default pyglet window size

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective( 90.0, 640.0/480, 0.1, 1000.0) # fov = 90 degrees; [near, far] = [0.1, 1000]

glMatrixMode(GL_MODELVIEW)
....

我建议使用以下坐标来“查看”上述两种情况下的点:

例如:

pyglet.graphics.draw(2, pyglet.gl.GL_POINTS,
    ('v3f', (-50.0, -20.0, -200.0, 40.0, 20.0, -250.0)))
glPointSize(20.0)

【讨论】:

好的,据我所知,你的答案有效,给我几分钟时间详细了解发生了什么然后我会接受。出于好奇,gluPerspective() 是如何融入这里的?我尝试将其用于此目的,但失败了,您有什么想法吗? @zython 我添加了一些位图以进行澄清。 Transform the modelMatrix 是一个 c++ 问题,但也许答案也有帮助。

以上是关于如何使用 opengl 和 pyglet 设置剪切平面的主要内容,如果未能解决你的问题,请参考以下文章

在 OS X 上的 pyglet 中启用 OpenGL 核心配置文件

实现 pyglet 会破坏我曾经工作的帧缓冲区 OpenGL 代码

C ++ / OpenGL - 2D - 如何在矩形边界框中剪切圆

如何在 OpenGL ES 2 或 3 上进行剪切平面?

如何使用 pyglet 播放流音频?

iOS 上的 OpenGL ES 1.1:没有剪切平面?