[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Gnu3dkit-dev] Rendering Pattern
From: |
Philippe C . D . Robert |
Subject: |
Re: [Gnu3dkit-dev] Rendering Pattern |
Date: |
Wed, 6 Nov 2002 22:46:11 +0100 |
Hi,
sorry for the late answer, I am quite busy these days...:-|
What you usually have is 3 or more stages, APP, CULL and DRAW. They can
be processed in parallel by different threads to gain scalability -
this then of course results in some latency.
So what I have in mind is the following scenario (explained for a given
frame n):
- The APP traverses the scene and updates it where required. Bounding
volumes to give a name are computed/updated at this stage, and
delegates are called here as well.
- The CULL stagee then takes over and - depending on the current state
of the scene/bounding volumes - culls away the parts which are not
visible. Delegates are thereby informed/asked if required. The result
of this stage is not a scene graph or some modified flags on it but
another optimised representation of the scene which is only used for
optimised drawing. This has to be done this way, I guess, because of
latency awareness which is required when using multiple threads.
- The DRAW stage then processes the list of items to be drawn as
generated by the respective CULL stage. This might be something like a
compiled G3DNodeList. Only this stage deals with the renderer and thus
indirectly interfaces with the lowlevel graphics API.
Now all this is done via a G3DRenderAction, a subclass of G3DAction. I
am not yet exactly sure how the API will look like here, though. Esp.
since many classes are involved, some of them dealing with latency
awareness.
Moreover, other actions can be built by developers to process a scene
for custom needs. These will be performed in the APP thread unless
custom thread management is done, of course.
I hope this was somehow understandable...:-)
-Phil
PS: It is way to early to talk about optimisations wrt ObjC features
such as IMPs and so on...:-)
On Sunday, November 3, 2002, at 08:42 Uhr, Brent Gulanowski wrote:
I'm formulating a high level discussion of the interaction between the
renderer module and Render Kit. I want to visualize the communications
pattern. At any time, RK holds all of the scene in its tree. The
renderer needs only some of the information in the tree. Also, it only
needs that information briefly. Some data will be repackaged for
delivery to the pipeline, and/or some will be used to recurse over the
tree.
1. The renderer informs the scene iterator that it is ready to receive
rendering submissions
2. The scene (scene rep?) provides a bounding region for a child of
the scene [1]
-----
version A
3. The renderer blanket accepts the region, accepts conditionally, or
rejects outright the region
4. The scene submits all rendering information for the region
version B
3. The renderer conditionally accepts the region
4. scene iterator recurses into the node in question
version C
3. The renderer blanket rejects the region
4. (scene iterator marks the region as culled?)
-----
5. scene iterator moves to next region at same level of tree (next
sibling of parent node)
6. repeat from step 2 for current node, or signal end of submissions
Optimization opportunities
This pattern requires the renderer to directly message the scene only
once. The scene then responds once for each undetermined region, and a
second time when a region is blanket accepted, plus any submission
messages. It is the unknown number of submission messages that
concerns me. I wonder if we could removed the need for the second
message from the scene, the message containing the rendering
information, by providing some means of direct (or more direct) access
to the data in the boundary submission message.
If we have a single array of primitives, perhaps we could just provide
a const pointer to the array. If we still have a non-trivial sub-tree
to deal with, could we provide two IMPs and object with the bounding
info? The first IMP would return the object's rendering submission,
and the second would return the next object. The renderer could
quickly iterate over the various arrays if RK controlled which node
was provided on each call to the second IMP. I admit that my knowledge
of using IMPs is poor.
If the renderer needed to cease accepting rendering submissions (some
time limit was reached, perhaps), it could blanket reject all other
region boundary submissions.
Because every node in the scene is the same class, we have an
opportunity to forgo messaging between node objects and access
bounding region information directly. This could either be done from a
class method or an instance method. If we can arrange a way of
providing the renderer with quick access into the data it needs, we
can reduce the messaging overhead dramatically. I guess there should
always be a message-based fallback approach.
------
[1] Is it safe to assume that some form of culling is inevitable? Or,
can we insist that the renderer performs a CULL action, even if that
action is to do nothing? I think it affects the communication process
enough to require it. I feel that culling is not meaningful outside of
drawing -- so culling is really a sub-task of drawing. But I assume
that cull state for objects is non-persistent. If we cull based solely
on hierarchical bounding boxes, I can't see how to have persistent
cull state. You need non-overlapping world divisions to be able to
assume that a world region that was hidden is still hidden (e.g.:
because it's next closest neighbour to the viewer is still being
culled).
If we cull based on a particular world division type, we need to
provide that division type in the scene. The converse is that if we
don't provide a division type in the scene, we can't use it for
culling in the renderer.
--
Brent Gulanowski address@hidden
http://inkubator.idevgames.com/
Working together to make great software.
_______________________________________________
Gnu3dkit-dev mailing list
address@hidden
http://mail.gnu.org/mailman/listinfo/gnu3dkit-dev
--
Philippe C.D. Robert
http://www.nice.ch/~phip