Panda3D Manual: The Graphics Engine
<<prev | top | next>> |
The graphics engine is the heart of the rendering process. The `GraphicsEngine` class is ultimately responsible for all of the drawing and culling operations per frame. Normally, there is no need to create a GraphicsEngine, as Panda3D will create one for you at startup. This default GraphicsEngine is stored in `base.graphicsEngine`. Note also that the following interfaces are strictly for the advanced user. Normally, if you want to create a new window or an offscreen buffer for rendering, you would just use the `base.openWindow()` or `window.makeTextureBuffer()` interfaces, which handle all of the details for you automatically. However, please continue reading if you want to understand in detail how Panda manages windows and buffers, or if you have special needs that are not addressed by the above convenience methods. ## Rendering a frame There is one key interface to rendering each frame of the graphics simulation:
    base.graphicsEngine.renderFrame()
This method causes all open GraphicsWindows and GraphicsBuffers to render their contents for the current frame. In order for Panda3D to render anything, this method must be called once per frame. Normally, this is done automatically by the task "igloop", which is created when you start Panda. ## Using a GraphicsEngine to create windows and buffers In order to render in Panda3D, you need a GraphicsStateGuardian, and either a GraphicsWindow (for rendering into a window) or a GraphicsBuffer (for rendering offscreen). You cannot create or destroy these objects directly; instead, you must use interfaces on the GraphicsEngine to create them. Before you can create either of the above, you need to have a GraphicsPipe, which specifies the particular graphics API you want to use (e.g. OpenGL or DirectX). The default GraphicsPipe specified in your Config.prc file has already been created at startup, and can be accessed by `base.pipe`. Now that you have a GraphicsPipe and a GraphicsEngine, you can create a GraphicsStateGuardian object. This object corresponds to a single graphics context on the graphics API, e.g. a single OpenGL context. (The context owns all of the OpenGL or DirectX objects like display lists, vertex buffers, and texture objects.) You need to have at least one GraphicsStateGuardian before you can create a GraphicsWindow:
    myGsg=base.graphicsEngine.makeGsg(base.pipe)
Now that you have a GraphicsStateGuardian, you can use it to create an onscreen GraphicsWindow or an offscreen GraphicsBuffer:
    base.graphicsEngine.makeWindow(gsg, name, sort)
    base.graphicsEngine.makeBuffer(gsg, name, sort, xSize, ySize, wantTexture)
`gsg` is the GraphicsStateGuardian, `name` is an arbitrary name you want to assign to the window/buffer, and `sort` is an integer that determines the order in which the windows/buffers will be rendered. The buffer specific arguments `xSize` and `ySize` decide the dimensions of the buffer, and `wantTexture` should be set to `True` if you want to retrieve a texture from this buffer later on. You can also use `graphicsEngine.makeParasite(host,name,sort,xSize,ySize)`, where host is a GraphicsOutput object. It creates a buffer but it does not allocate room for itself. Instead it renders to the framebuffer of `host`. It effectively has `wantTexture` set to `True` so you can retrieve a texture from it later on. See The GraphicsOutput class and Graphics Buffers and Windows for more information.
    myWindow=base.graphicsEngine.makeWindow(myGsg, "Hello World", 0)
    myBuffer=base.graphicsEngine.makeBuffer(myGsg, "Hi World", 0, 800,600, True)
    myParasite=base.graphicsEngine.makeBuffer(myBuffer,"Im a leech", 0, 800, 600)
Note: if you want the buffers to be visible add `show-buffers true` to your configuration file. This causes the buffers to be opened as windows instead, which is useful while debugging. ## Sharing graphics contexts It is possible to share the same GraphicsStateGuardian among multiple different GraphicsWindows and/or GraphicsBuffers; if you do this, then the graphics context will be used to render into each window one at a time. This is particularly useful if the different windows will be rendering many of the same objects, since then the same texture objects and vertex buffers can be shared between different windows. It is also possible to use a different GraphicsStateGuardian for each different window. This means that if a particular texture is to be rendered in each window, it will have to be loaded into graphics memory twice, once in each context, which may be wasteful. However, there are times when this may be what you want to do, for instance if you have multiple graphics cards and you want to to render to both of them simultaneously. (Note that the actual support for simultaneously rendering to multiple graphics cards is currently unfinished in Panda at the time of this writing, but the API has been designed with this future path in mind.) ## Closing windows To close a specific window or buffer you use `removeWindow(window)`. To close all windows `removeAllWindows()`
    base.graphicsEngine.removeWindow(myWindow)
    base.graphicsEngine.removeAllWindows()
## More about GraphicsEngine Here is some other useful functionality of the `GraphicsEngine` class.
`getNumWindows()` | Returns the number of windows and buffers that this `GraphicsEngine` object is managing.
`isEmpty()` | Returns `True` if this `GraphicsEngine` is not managing any windows or buffers.
See API for advanced functionality of `GraphicsEngine` and `GraphicsStateGuardian` class.
<<prev | top | next>> |