简体   繁体   English

在pyglet中使用opengl渲染3d场景无需事件循环

[英]Using opengl in pyglet to render 3d scene without event loop

Ok so I've spent an embarrassing amount of time on this problem and still am fairly confused.好吧,我在这个问题上花了很多时间,但仍然很困惑。 I'm hoping someone can provide some guidance, resources, similar projects, etc. I am unsure that what I am doing is the right way to go about this problem.我希望有人可以提供一些指导、资源、类似项目等。我不确定我正在做的关于这个问题的正确方法是 go。

Background:背景:

I am working on a project where I am developing an imitation of rocket league (a video game) so that I can run reinforcement learning algorithms on the game (I can't run the game itself because it would be too slow).我正在做一个项目,我正在开发一个模拟火箭联盟(视频游戏)的游戏,这样我就可以在游戏中运行强化学习算法(我不能运行游戏本身,因为它太慢了)。 The imitation needs to comply with OpenAI Gym's API, which essentially demands a step method (which takes in the actions the AI determines necessary at that timestep and outputs the state of the game after the timestep), and a render method.模拟需要遵循 OpenAI Gym 的 API,它本质上需要一个 step 方法(它接受 AI 在该时间步确定必要的动作,并在该时间步后输出游戏的 state),以及一个渲染方法。 I have enough of the game implemented that I am currently working on the render method.我已经实现了足够的游戏,我目前正在研究渲染方法。 I want to package this and release it on pypi, so I chose pyglet to implement the graphics because I read it is fairly portable.我想package这个在pypi上发布,所以我选择了pyglet来实现图形,因为我看它是相当可移植的。

Problem:问题:

I don't think I can use an event loop to run my graphics.我不认为我可以使用事件循环来运行我的图形。 The way this api is set-up and used is that the user first instantiates the environment (the video game) and then sets up a loop in which they run the step function of the environment and optionally choose to also place the render method in that same loop depending on whether or not they want to see their AI's actions during that run.设置和使用此 api 的方式是用户首先实例化环境(视频游戏),然后设置一个循环,在其中运行环境的步骤 function 并可选择将渲染方法也放置在该循环中相同的循环取决于他们是否想在运行期间看到他们的 AI 的动作。 An example usage is available under environments on this page .页面上的环境下提供了一个示例用法。 So I can't use an event loop because it would stop execution of the user's loop.所以我不能使用事件循环,因为它会停止执行用户循环。 Instead I need to instantiate a window on the first call of render, and then update it with the state of the game on every subsequent call.相反,我需要在第一次调用渲染时实例化一个 window,然后在每次后续调用时用游戏的 state 更新它。

My current solution:我目前的解决方案:

    def render():
        if self.window is None:
            self.window = pyglet.window.Window(width, height)
        self.window.clear()
        self.window.dispatch_events()
          ... describe current 3d scence
        self.window.flip()

Problem cont:问题续:

My current solution feels a bit hacky which I don't love, but more of a problem is that I can't figure out how to implement user input for this solution.我目前的解决方案感觉有点老套,我不喜欢,但更多的问题是我不知道如何为这个解决方案实现用户输入。 I would like to be able to pan and move the camera all around the scene so that I view the 3-dimensional shape of objects, but I don't know how to implement that without the event loop and on_key_press decorator.我希望能够在场景周围平移和移动相机,以便查看对象的 3 维形状,但我不知道如何在没有事件循环和 on_key_press 装饰器的情况下实现它。

Also:还:

I am struggling to find good resources for 3d programming with OpenGL functions (the game is 3d).我正在努力寻找具有 OpenGL 功能的 3d 编程的好资源(游戏是 3d)。 I was wondering if anyone knew of a good place to learn that without all complexity I found on https://learnopengl.com/ .我想知道是否有人知道我在https://learnopengl.com/上找到的没有所有复杂性的好地方。 I don't even know if pyglet/opengl is the right way to go about solving this problem.我什至不知道 pyglet/opengl 是否是 go 解决这个问题的正确方法。 I know very little about 3d graphics and am open to any suggestions.我对 3d 图形知之甚少,愿意接受任何建议。

So for anyone with a similar problem looking for the solution, here is what I determined:因此,对于任何有类似问题寻找解决方案的人,这是我确定的:

If you need to render events but not give up control flow to pyglet.app.run() or any other event loop, custom or otherwise, it is possible to still listen for user actions.如果您需要呈现事件但不放弃控制流到 pyglet.app.run() 或任何其他事件循环,自定义或其他方式,仍然可以监听用户操作。 The following code is an example pseudo-implementation for a class that renders its state each time the render() function is called, with user input optionally changing that state. Be warned that this is far optimal from an efficiency perspective, and you should always use pyglet.app.run() when possible, but this instance demanded an alternative solution.以下代码是 class 的示例伪实现,每次调用 render() function 时都会呈现其 state,用户输入可选择更改该 state。请注意,从效率的角度来看,这是最佳选择,您应该始终尽可能使用 pyglet.app.run() ,但此实例需要替代解决方案。

class Env:
    # ...lots of other class stuff
    def render(self):
        if self.window is None:
            self.window = pyglet.window.Window(width, height)

            @self.window.event
            def on_close():
                self.window.close()

            @self.window.event
            def on_key_press(key, mod):
                # ...do stuff on key press

        pyglet.clock.tick()
        self.window.clear()
        self.window.dispatch_events()

        # ...transform, update, create all objects that need to be rendered

        self.window.flip()


env = Env()
for _ in range(100):
    env.doStuff()
    env.render()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM