Skip to content

Commit 1662f9f

Browse files
committed
Docs: Some basic effect docs
1 parent 20ac58c commit 1662f9f

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

docs/source/effects.rst

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,111 @@ Effects
55
In order to draw something to the screen using this framework you need to make one or multiple effects.
66
An effect is an independent python package of a certain format.
77

8+
89
The Effect Package
910
^^^^^^^^^^^^^^^^^^
1011

11-
The effect package should have the following structure:
12+
The effect package should have the following structure (assuming our effect is named "cube".
13+
14+
.. code-block:: bash
15+
16+
cube
17+
├── effect.py
18+
├── shaders
19+
│   └── cube
20+
│   └── ...
21+
└── textures
22+
   └── cube
23+
└── ...
24+
25+
The ``effect.py`` module is where the draw logic for the effect resides. Directories at the
26+
same level are for resources for the effect. Notice that the resource directories contains
27+
another directory with the name of the effect. This is because these folders are added to
28+
a virtual directory (for each resource type) so we should place it in a directory to
29+
reduce the change of name collisions. Two effects with the texture ``texture.png`` in
30+
the root of their local ``textures/`` directory will cause the first effect to
31+
32+
Registry
33+
^^^^^^^^
34+
35+
For an effect to be recognised by the system it has to be registered
36+
in the ``EFFECTS`` tuple/list in your settings module.
37+
Simply add the full python path to the package. If our cube example
38+
above resides inside a ``myproject`` project package we need to add
39+
the string ``myproject.cube``. See :doc:`settings`.
40+
41+
You can always run a single effect by using the ``runeffect`` command.
42+
43+
.. code-block:: bash
44+
45+
./manage.py runeffect myproject.cube
46+
47+
If you have multiple effects you need to crate or use an existing :doc:`effectmanagers`
48+
that will decide what effect would be active at what time or state.
49+
50+
Resources
51+
^^^^^^^^^
52+
53+
Resource loading is baked into the effect class it self. Methods are inherited
54+
from the base ``Effect`` class such as ``get_shader`` and ``get_texture``.
1255

13-
The effect Module
56+
The Effect Module
1457
^^^^^^^^^^^^^^^^^
1558

59+
The effect module in an effect package needs to be named ``effect.py`` and
60+
reside in the root of the package. It can only contain a single effect
61+
class. The name of the class doesn't matter right now, but we are
62+
considering allowing multiple effects in the future, so giving it
63+
at least a descriptive name of that it represents is a good idea.
64+
65+
There are two important methods in an effect:
66+
- ``__init__()``
67+
- draw()
68+
69+
The **initializer** is called before resources are loaded. This is so the
70+
effects can register the what resources they need. The resource
71+
managers will return an empty object that will be populated when
72+
loading starts.
73+
74+
The **draw** method is called by the framework or from a your custom
75+
:doc:`effectmanagers` ever frame, or at least every frame the manager
76+
decides the effect should be active at least.
77+
78+
The standard effect example:
79+
80+
.. code-block:: bash
81+
82+
from demosys.effects import effect
83+
from demosys.opengl import geometry
84+
from OpenGL import GL
85+
# from pyrr import matrix44
86+
87+
class DefaultEffect(effect.Effect):
88+
"""Generated default effect"""
89+
def __init__(self):
90+
self.shader = self.get_shader("default/default.glsl")
91+
self.cube = geometry.cube(4.0, 4.0, 4.0)
92+
93+
@effect.bind_target
94+
def draw(self, time, frametime, target):
95+
GL.glEnable(GL.GL_DEPTH_TEST)
96+
97+
# Rotate and translate
98+
m_mv = self.create_transformation(rotation=(time * 1.2, time * 2.1, time * 0.25),
99+
translation=(0.0, 0.0, -8.0))
100+
101+
# Apply the rotation and translation from the system camera
102+
# m_mv = matrix44.multiply(m_mv, self.sys_camera.view_matrix)
103+
104+
# Create normal matrix from model-view
105+
m_normal = self.create_normal_matrix(m_mv)
106+
107+
# Draw the cube
108+
with self.cube.bind(self.shader) as shader:
109+
shader.uniform_mat4("m_proj", self.sys_camera.projection)
110+
shader.uniform_mat4("m_mv", m_mv)
111+
shader.uniform_mat3("m_normal", m_normal)
112+
self.cube.draw()
16113
17114
Effect Base Class
18115
^^^^^^^^^^^^^^^^^

docs/source/performance.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This is ignoring delays or blocks caused by OpenGL calls.
1212
How important performance is will of course depends on the project.
1313
Visualization for a scientific application doing some heavy
1414
calculations would probably not need to run at 60 fps.
15+
It's also not illegal to not care about performance and just have fun.
1516

1617
Probably the biggest enemy to performance in python is **memory allocation**.
1718

@@ -27,11 +28,13 @@ but this is not always easy to determine and will needs testing.
2728

2829
Try to do as much as possible on the GPU. Use features like transform
2930
feedback to alter buffer data and use your creativity to find efficient
30-
solitions.
31+
solutions.
3132

3233
Performance in rendering is not straight forward to measure in any language.
3334
Simply adding timers in the code will not really tell us much unless
3435
we also query OpenGL about the performance.
3536

37+
We could also try to compile your project with pypy, but we have not tested this (yet)
38+
3639
We can also strive to do more with less. Rendering, in the end, is really just
3740
about creating illusions.

0 commit comments

Comments
 (0)