basilisk-engine 0.1.42__py3-none-any.whl → 0.1.43__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of basilisk-engine might be problematic. Click here for more details.

Files changed (98) hide show
  1. basilisk/__init__.py +26 -26
  2. basilisk/audio/sound.py +27 -27
  3. basilisk/bsk_assets/cube.obj +48 -48
  4. basilisk/collisions/broad/broad_aabb.py +102 -102
  5. basilisk/collisions/broad/broad_bvh.py +137 -137
  6. basilisk/collisions/collider.py +95 -95
  7. basilisk/collisions/collider_handler.py +225 -225
  8. basilisk/collisions/narrow/contact_manifold.py +95 -95
  9. basilisk/collisions/narrow/dataclasses.py +34 -34
  10. basilisk/collisions/narrow/deprecated.py +46 -46
  11. basilisk/collisions/narrow/epa.py +91 -91
  12. basilisk/collisions/narrow/gjk.py +66 -66
  13. basilisk/collisions/narrow/graham_scan.py +24 -24
  14. basilisk/collisions/narrow/helper.py +29 -29
  15. basilisk/collisions/narrow/line_intersections.py +106 -106
  16. basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
  17. basilisk/config.py +53 -53
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +178 -178
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +169 -171
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +70 -70
  25. basilisk/generic/input_validation.py +82 -82
  26. basilisk/generic/math.py +17 -17
  27. basilisk/generic/matrices.py +35 -35
  28. basilisk/generic/meshes.py +72 -72
  29. basilisk/generic/quat.py +142 -142
  30. basilisk/generic/quat_methods.py +7 -7
  31. basilisk/generic/raycast_result.py +26 -26
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input_output/IO_handler.py +91 -91
  34. basilisk/input_output/clock.py +49 -49
  35. basilisk/input_output/keys.py +43 -43
  36. basilisk/input_output/mouse.py +90 -90
  37. basilisk/input_output/path.py +14 -14
  38. basilisk/mesh/cube.py +33 -33
  39. basilisk/mesh/mesh.py +233 -233
  40. basilisk/mesh/mesh_from_data.py +150 -150
  41. basilisk/mesh/model.py +271 -271
  42. basilisk/mesh/narrow_aabb.py +89 -89
  43. basilisk/mesh/narrow_bvh.py +91 -91
  44. basilisk/mesh/narrow_primative.py +23 -23
  45. basilisk/nodes/helper.py +28 -28
  46. basilisk/nodes/node.py +709 -709
  47. basilisk/nodes/node_handler.py +97 -97
  48. basilisk/particles/particle_handler.py +64 -64
  49. basilisk/particles/particle_renderer.py +93 -93
  50. basilisk/physics/impulse.py +112 -112
  51. basilisk/physics/physics_body.py +43 -43
  52. basilisk/physics/physics_engine.py +35 -35
  53. basilisk/render/batch.py +103 -103
  54. basilisk/render/bloom.py +118 -124
  55. basilisk/render/camera.py +260 -260
  56. basilisk/render/chunk.py +113 -108
  57. basilisk/render/chunk_handler.py +167 -167
  58. basilisk/render/frame.py +130 -128
  59. basilisk/render/framebuffer.py +192 -212
  60. basilisk/render/image.py +120 -120
  61. basilisk/render/image_handler.py +120 -120
  62. basilisk/render/light.py +96 -96
  63. basilisk/render/light_handler.py +58 -58
  64. basilisk/render/material.py +232 -232
  65. basilisk/render/material_handler.py +133 -133
  66. basilisk/render/post_process.py +180 -180
  67. basilisk/render/shader.py +135 -134
  68. basilisk/render/shader_handler.py +109 -94
  69. basilisk/render/sky.py +119 -121
  70. basilisk/scene.py +287 -288
  71. basilisk/shaders/batch.frag +293 -293
  72. basilisk/shaders/batch.vert +117 -117
  73. basilisk/shaders/bloom_downsample.frag +23 -42
  74. basilisk/shaders/bloom_upsample.frag +33 -33
  75. basilisk/shaders/crt.frag +34 -34
  76. basilisk/shaders/draw.frag +27 -27
  77. basilisk/shaders/draw.vert +25 -25
  78. basilisk/shaders/filter.frag +22 -22
  79. basilisk/shaders/frame.frag +13 -13
  80. basilisk/shaders/frame.vert +13 -13
  81. basilisk/shaders/frame_hdr.frag +27 -27
  82. basilisk/shaders/geometry.frag +10 -10
  83. basilisk/shaders/geometry.vert +41 -41
  84. basilisk/shaders/normal.frag +62 -62
  85. basilisk/shaders/normal.vert +96 -96
  86. basilisk/shaders/particle.frag +81 -81
  87. basilisk/shaders/particle.vert +86 -86
  88. basilisk/shaders/sky.frag +23 -23
  89. basilisk/shaders/sky.vert +13 -13
  90. {basilisk_engine-0.1.42.dist-info → basilisk_engine-0.1.43.dist-info}/METADATA +89 -89
  91. basilisk_engine-0.1.43.dist-info/RECORD +111 -0
  92. {basilisk_engine-0.1.42.dist-info → basilisk_engine-0.1.43.dist-info}/WHEEL +1 -1
  93. basilisk/input/__init__.py +0 -0
  94. basilisk/input/mouse.py +0 -62
  95. basilisk/input/path.py +0 -14
  96. basilisk/shaders/bloom_frame.frag +0 -25
  97. basilisk_engine-0.1.42.dist-info/RECORD +0 -115
  98. {basilisk_engine-0.1.42.dist-info → basilisk_engine-0.1.43.dist-info}/top_level.txt +0 -0
@@ -1,134 +1,134 @@
1
- import moderngl as mgl
2
- from ..render.image_handler import ImageHandler
3
- from ..render.material import Material
4
- import numpy as np
5
-
6
-
7
- class MaterialHandler():
8
- engine: ...
9
- """Back reference to the parent engine"""
10
- ctx: mgl.Context
11
- """Back reference to the parent context"""
12
- materials: list[Material]
13
- """List containing all the materials in the engine"""
14
- data_texture: mgl.Texture
15
- """ModernGL texture containing all the material data for materials in the engine"""
16
- image_handler: ImageHandler=None
17
- """Handler for all images in the game"""
18
-
19
- def __init__(self, engine) -> None:
20
- """
21
- Handles all the materials introduced to an engine.
22
- Writes material information to the GPU
23
- """
24
-
25
- # Back references
26
- self.engine = engine
27
- self.ctx = engine.ctx
28
-
29
- # Initialize data
30
- self.materials = []
31
- self.data_texture = None
32
-
33
- self.image_handler = ImageHandler(engine)
34
-
35
- def add(self, material: Material) -> None:
36
- """
37
- Adds the given material to the handler if it is not already present
38
- """
39
-
40
- write = False
41
-
42
- if isinstance(material, Material): material = [material]
43
-
44
- for mtl in material:
45
- # Check that the material is not already in the scene
46
- if mtl in self.materials: continue
47
- # Update the material's handler
48
- mtl.material_handler = self
49
- # Add images
50
- if mtl.texture: self.image_handler.add(mtl.texture)
51
- if mtl.normal: self.image_handler.add(mtl.normal)
52
-
53
- # Add the material
54
- self.materials.append(mtl)
55
-
56
- write = True
57
-
58
-
59
- # Write materials
60
- if write: self.write(regenerate=True)
61
-
62
- def generate_material_texture(self) -> None:
63
- """
64
- Generates the texture that is used to write material data to the GPU
65
- """
66
-
67
- # Check that there are materials to write
68
- if len(self.materials) == 0: return
69
-
70
- # Release existing data texture
71
- if self.data_texture: self.data_texture.release()
72
-
73
- # Create empty texture data
74
- material_data = np.zeros(shape=(len(self.materials), 28), dtype="f4")
75
-
76
- # Get data from the materials
77
- for i, mtl in enumerate(self.materials):
78
- mtl.index = i
79
- material_data[i] = mtl.get_data()
80
-
81
- # Create texture from data
82
- material_data = np.ravel(material_data)
83
- self.data_texture = self.ctx.texture((1, len(material_data)), components=1, dtype='f4', data=material_data)
84
-
85
- def write(self, regenerate=False) -> None:
86
- """
87
- Writes all material data to relavent shaders
88
- """
89
-
90
- if regenerate: self.generate_material_texture()
91
-
92
- if not self.data_texture: return
93
-
94
- for shader in self.engine.shader_handler.shaders:
95
- if 'materialsTexture' not in shader.uniforms: continue
96
-
97
- shader.program['materialsTexture'] = 9
98
- self.data_texture.use(location=9)
99
-
100
- def get(self, identifier: str | int) -> any:
101
- """
102
- Gets the basilisk material with the given name or index
103
- Args:
104
- identifier: str | int
105
- The name string or index of the desired material
106
- """
107
-
108
- # Simply use index if given
109
- if isinstance(identifier, int): return self.materials[identifier]
110
-
111
- # Else, search the list for an image material the given name
112
- for material in self.materials:
113
- if material.name != identifier: continue
114
- return material
115
-
116
- # No matching material found
117
- return None
118
-
119
- def set_base(self):
120
- """
121
- Creates a base material
122
- """
123
-
124
- self.base = Material('Base')
125
- self.materials.append(self.base)
126
- self.generate_material_texture()
127
- self.write()
128
-
129
- def __del__(self) -> None:
130
- """
131
- Releases the material data texture
132
- """
133
-
1
+ import moderngl as mgl
2
+ from ..render.image_handler import ImageHandler
3
+ from ..render.material import Material
4
+ import numpy as np
5
+
6
+
7
+ class MaterialHandler():
8
+ engine: ...
9
+ """Back reference to the parent engine"""
10
+ ctx: mgl.Context
11
+ """Back reference to the parent context"""
12
+ materials: list[Material]
13
+ """List containing all the materials in the engine"""
14
+ data_texture: mgl.Texture
15
+ """ModernGL texture containing all the material data for materials in the engine"""
16
+ image_handler: ImageHandler=None
17
+ """Handler for all images in the game"""
18
+
19
+ def __init__(self, engine) -> None:
20
+ """
21
+ Handles all the materials introduced to an engine.
22
+ Writes material information to the GPU
23
+ """
24
+
25
+ # Back references
26
+ self.engine = engine
27
+ self.ctx = engine.ctx
28
+
29
+ # Initialize data
30
+ self.materials = []
31
+ self.data_texture = None
32
+
33
+ self.image_handler = ImageHandler(engine)
34
+
35
+ def add(self, material: Material) -> None:
36
+ """
37
+ Adds the given material to the handler if it is not already present
38
+ """
39
+
40
+ write = False
41
+
42
+ if isinstance(material, Material): material = [material]
43
+
44
+ for mtl in material:
45
+ # Check that the material is not already in the scene
46
+ if mtl in self.materials: continue
47
+ # Update the material's handler
48
+ mtl.material_handler = self
49
+ # Add images
50
+ if mtl.texture: self.image_handler.add(mtl.texture)
51
+ if mtl.normal: self.image_handler.add(mtl.normal)
52
+
53
+ # Add the material
54
+ self.materials.append(mtl)
55
+
56
+ write = True
57
+
58
+
59
+ # Write materials
60
+ if write: self.write(regenerate=True)
61
+
62
+ def generate_material_texture(self) -> None:
63
+ """
64
+ Generates the texture that is used to write material data to the GPU
65
+ """
66
+
67
+ # Check that there are materials to write
68
+ if len(self.materials) == 0: return
69
+
70
+ # Release existing data texture
71
+ if self.data_texture: self.data_texture.release()
72
+
73
+ # Create empty texture data
74
+ material_data = np.zeros(shape=(len(self.materials), 28), dtype="f4")
75
+
76
+ # Get data from the materials
77
+ for i, mtl in enumerate(self.materials):
78
+ mtl.index = i
79
+ material_data[i] = mtl.get_data()
80
+
81
+ # Create texture from data
82
+ material_data = np.ravel(material_data)
83
+ self.data_texture = self.ctx.texture((1, len(material_data)), components=1, dtype='f4', data=material_data)
84
+
85
+ def write(self, regenerate=False) -> None:
86
+ """
87
+ Writes all material data to relavent shaders
88
+ Uses bind slot 15
89
+ """
90
+
91
+ if regenerate: self.generate_material_texture()
92
+
93
+ if not self.data_texture: return
94
+
95
+ for shader in self.engine.shader_handler.shaders:
96
+ if 'materialsTexture' not in shader.uniforms: continue
97
+
98
+ shader.bind(self.data_texture, 'materialsTexture', 15)
99
+
100
+ def get(self, identifier: str | int) -> any:
101
+ """
102
+ Gets the basilisk material with the given name or index
103
+ Args:
104
+ identifier: str | int
105
+ The name string or index of the desired material
106
+ """
107
+
108
+ # Simply use index if given
109
+ if isinstance(identifier, int): return self.materials[identifier]
110
+
111
+ # Else, search the list for an image material the given name
112
+ for material in self.materials:
113
+ if material.name != identifier: continue
114
+ return material
115
+
116
+ # No matching material found
117
+ return None
118
+
119
+ def set_base(self):
120
+ """
121
+ Creates a base material
122
+ """
123
+
124
+ self.base = Material('Base')
125
+ self.materials.append(self.base)
126
+ self.generate_material_texture()
127
+ self.write()
128
+
129
+ def __del__(self) -> None:
130
+ """
131
+ Releases the material data texture
132
+ """
133
+
134
134
  if self.data_texture: self.data_texture.release()
@@ -1,181 +1,181 @@
1
- import numpy as np
2
- import moderngl as mgl
3
- from .shader import Shader
4
- from .image import Image
5
- from .framebuffer import Framebuffer
6
-
7
- class PostProcess:
8
- engine: ...
9
- """Reference to the parent engine"""
10
- ctx: mgl.Context
11
- """Reference to the parent context"""
12
- shader: Shader
13
- """Shader object used by the post process"""
14
- vao: mgl.VertexArray
15
- """Screenspace render vao"""
16
- fbo: Framebuffer=None
17
-
18
- def __init__(self, engine, shader_path: str=None, size: tuple=None, components: int=4, filter=(mgl.LINEAR, mgl.LINEAR)) -> None:
19
- """
20
- Object to apply post processing to a texture
21
- """
22
-
23
- # Reference attributes
24
- self.engine = engine
25
- self.ctx = engine.ctx
26
-
27
- # Size of the destination
28
- self.size = size if size else engine.win_size
29
- self.components = components
30
-
31
- # Load default fragment if none given
32
- if not (isinstance(shader_path, str) or isinstance(shader_path, type(None))):
33
- raise ValueError(f'PostProces.apply: Invalid post process source type {type(shader_path)}. Expected string path destination of fragment shader.')
34
- frag = shader_path if shader_path else self.engine.root + f'/shaders/frame.frag'
35
-
36
- # Load Shaders
37
- self.shader = Shader(self.engine, self.engine.root + f'/shaders/frame.vert', frag)
38
- self.engine.shader_handler.add(self.shader)
39
-
40
- # Load VAO
41
- self.vbo = self.ctx.buffer(np.array([[-1, -1, 0, 0, 0], [1, -1, 0, 1, 0], [1, 1, 0, 1, 1], [-1, 1, 0, 0, 1], [-1, -1, 0, 0, 0], [1, 1, 0, 1, 1]], dtype='f4'))
42
- self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
43
-
44
- # Temporary render destination
45
- self.fbo = Framebuffer(engine, self.size, components)
46
-
47
- # Filter settings
48
- self.filter = filter
49
- self.fbo.texture.filter = self.filter
50
-
51
-
52
- def apply(self, sources: list[tuple[str, mgl.Texture]] | list[tuple[str, Image]] | list[tuple[str, Framebuffer]], destination: mgl.Texture | Image | Framebuffer=None) -> mgl.Texture | Image | Framebuffer:
53
- """
54
- Applies a post process shader to a texture source.
55
- Returns the modified texture or renders to the destination if given
56
- """
57
-
58
- # Write all the given sources to the GPU
59
- self._write_sources(sources)
60
-
61
- # Get the redner target
62
- if isinstance(destination, Framebuffer) or isinstance(destination, type(self.engine.frame)): fbo = destination
63
- elif isinstance(destination, mgl.Texture): fbo = self.ctx.framebuffer([destination], None)
64
- elif isinstance(destination, Image): fbo = self.ctx.framebuffer([destination.texture], None)
65
-
66
- # Apply the post process
67
- fbo.use()
68
- fbo.clear()
69
- self.vao.render()
70
-
71
- # Simply return the given fbo if provided
72
- if isinstance(destination, Framebuffer) or isinstance(destination, type(self.engine.frame)): return destination
73
-
74
- # Else, need to release the data and return the texture
75
- texture = fbo.color_attachments[0]
76
- fbo.release()
77
- return texture
78
-
79
-
80
- def resize(self, size: tuple=None):
81
- """
82
- Resize the post process
83
- """
84
-
85
- self.size = size if size else self.engine.win_size
86
-
87
- def _write_sources(self, sources: list[tuple[str, mgl.Texture]] | list[tuple[str, Image]] | list[tuple[str, Framebuffer]]):
88
- """
89
- Writes all given source images to the GPU
90
- """
91
-
92
- for i, source in enumerate(sources):
93
- # Get the name and data
94
- name, data = source
95
-
96
- # Extract the needed data
97
- if isinstance(data, mgl.Texture): texture = data
98
- elif isinstance(data, Image) or isinstance(data, Framebuffer) or isinstance(data, type(self.engine.frame)): texture = data.texture
99
- else: raise ValueError(f'PostProces.apply: Invalid postprocess source type {type(source)}')
100
-
101
- # Write the texture
102
- self.shader.program[name] = i
103
- texture.use(location=i)
104
-
105
- def _render_post_process(self, source: mgl.Texture):
106
- # Clear and use the fbo as a render target
107
- self.fbo.use()
108
- self.fbo.clear()
109
-
110
- # Load the source texture to the shader
111
- for i, src in enumerate(source):
112
- self.shader.program[src[0]] = i
113
- src[1].use(location=i)
114
-
115
- # Apply the post process
116
- self.vao.render()
117
-
118
-
119
- def _apply_to_framebuffer(self, source: Framebuffer, detination: Framebuffer=None) -> Framebuffer:
120
- """
121
- Applies a post process to a bsk.Framebuffer
122
- """
123
-
124
- # Create a blank framebuffer
125
- if not detination or detination.size != self.size:
126
- fbo = Framebuffer(self.engine, self.size, self.components)
127
- old_filter = None
128
- fbo.texture.filter = self.filter
129
- else:
130
- fbo = detination
131
- old_filter = fbo.texture_filter
132
- fbo.texture.filter = self.filter
133
-
134
- # Load the source texture to the shader
135
- for i, src in enumerate(source):
136
- self.shader.program[src[0]] = i
137
- src[1].texture.use(location=i)
138
-
139
- fbo.use()
140
- fbo.clear()
141
- # Apply the post process
142
- self.vao.render()
143
-
144
- # Reset filter if needed
145
- if old_filter: fbo.texture.filter = old_filter
146
-
147
- # Return the fbo for the user
148
- return fbo
149
-
150
- def _apply_to_texture(self, source: mgl.Texture, destination: mgl.Texture) -> mgl.Texture:
151
- """
152
- Applies a post process to a mgl.Texture
153
- """
154
-
155
- # Render the post processs with the given texture
156
- self._render_post_process(source)
157
-
158
- # Make a deep copy of the modified texture
159
- texture = self.ctx.texture(self.fbo.size, self.fbo.components, self.fbo.data)
160
-
161
- return texture
162
-
163
- def _apply_to_image(self, source: Image, destination: Image) -> Image:
164
- """
165
- Applies a post process to a bsk.Image
166
- """
167
-
168
- # Create a texture from the image data
169
- texture = self.ctx.texture(self.fbo.size, self.fbo.components, source.data)
170
-
171
- # Render the post processs with the given texture
172
- self._render_post_process(source)
173
-
174
- # Make an image from the texture
175
- image = Image()
176
- return image
177
-
178
- def __del__(self):
179
- if self.vao: self.vao.release()
180
- if self.vbo: self.vbo.release()
1
+ import numpy as np
2
+ import moderngl as mgl
3
+ from .shader import Shader
4
+ from .image import Image
5
+ from .framebuffer import Framebuffer
6
+
7
+ class PostProcess:
8
+ engine: ...
9
+ """Reference to the parent engine"""
10
+ ctx: mgl.Context
11
+ """Reference to the parent context"""
12
+ shader: Shader
13
+ """Shader object used by the post process"""
14
+ vao: mgl.VertexArray
15
+ """Screenspace render vao"""
16
+ fbo: Framebuffer=None
17
+
18
+ def __init__(self, engine, shader_path: str=None, size: tuple=None, components: int=4, filter=(mgl.LINEAR, mgl.LINEAR)) -> None:
19
+ """
20
+ Object to apply post processing to a texture
21
+ """
22
+
23
+ # Reference attributes
24
+ self.engine = engine
25
+ self.ctx = engine.ctx
26
+
27
+ # Size of the destination
28
+ self.size = size if size else engine.win_size
29
+ self.components = components
30
+
31
+ # Load default fragment if none given
32
+ if not (isinstance(shader_path, str) or isinstance(shader_path, type(None))):
33
+ raise ValueError(f'PostProces.apply: Invalid post process source type {type(shader_path)}. Expected string path destination of fragment shader.')
34
+ frag = shader_path if shader_path else self.engine.root + f'/shaders/frame.frag'
35
+
36
+ # Load Shaders
37
+ self.shader = Shader(self.engine, self.engine.root + f'/shaders/frame.vert', frag)
38
+ self.engine.shader_handler.add(self.shader)
39
+
40
+ # Load VAO
41
+ self.vbo = self.ctx.buffer(np.array([[-1, -1, 0, 0, 0], [1, -1, 0, 1, 0], [1, 1, 0, 1, 1], [-1, 1, 0, 0, 1], [-1, -1, 0, 0, 0], [1, 1, 0, 1, 1]], dtype='f4'))
42
+ self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
43
+
44
+ # Temporary render destination
45
+ self.fbo = Framebuffer(engine, self.size, components)
46
+
47
+ # Filter settings
48
+ self.filter = filter
49
+ self.fbo.texture.filter = self.filter
50
+
51
+
52
+ def apply(self, sources: list[tuple[str, mgl.Texture]] | list[tuple[str, Image]] | list[tuple[str, Framebuffer]], destination: mgl.Texture | Image | Framebuffer=None) -> mgl.Texture | Image | Framebuffer:
53
+ """
54
+ Applies a post process shader to a texture source.
55
+ Returns the modified texture or renders to the destination if given
56
+ """
57
+
58
+ # Write all the given sources to the GPU
59
+ self._write_sources(sources)
60
+
61
+ # Get the redner target
62
+ if isinstance(destination, Framebuffer) or isinstance(destination, type(self.engine.frame)): fbo = destination
63
+ elif isinstance(destination, mgl.Texture): fbo = self.ctx.framebuffer([destination], None)
64
+ elif isinstance(destination, Image): fbo = self.ctx.framebuffer([destination.texture], None)
65
+
66
+ # Apply the post process
67
+ fbo.use()
68
+ fbo.clear()
69
+ self.vao.render()
70
+
71
+ # Simply return the given fbo if provided
72
+ if isinstance(destination, Framebuffer) or isinstance(destination, type(self.engine.frame)): return destination
73
+
74
+ # Else, need to release the data and return the texture
75
+ texture = fbo.color_attachments[0]
76
+ fbo.release()
77
+ return texture
78
+
79
+
80
+ def resize(self, size: tuple=None):
81
+ """
82
+ Resize the post process
83
+ """
84
+
85
+ self.size = size if size else self.engine.win_size
86
+
87
+ def _write_sources(self, sources: list[tuple[str, mgl.Texture]] | list[tuple[str, Image]] | list[tuple[str, Framebuffer]]):
88
+ """
89
+ Writes all given source images to the GPU
90
+ """
91
+
92
+ for i, source in enumerate(sources):
93
+ # Get the name and data
94
+ name, data = source
95
+
96
+ # Extract the needed data
97
+ if isinstance(data, mgl.Texture): texture = data
98
+ elif isinstance(data, Image) or isinstance(data, Framebuffer) or isinstance(data, type(self.engine.frame)): texture = data.texture
99
+ else: raise ValueError(f'PostProces.apply: Invalid postprocess source type {type(source)}')
100
+
101
+ # Write the texture
102
+ self.shader.program[name] = i
103
+ texture.use(location=i)
104
+
105
+ def _render_post_process(self, source: mgl.Texture):
106
+ # Clear and use the fbo as a render target
107
+ self.fbo.use()
108
+ self.fbo.clear()
109
+
110
+ # Load the source texture to the shader
111
+ for i, src in enumerate(source):
112
+ self.shader.program[src[0]] = i
113
+ src[1].use(location=i)
114
+
115
+ # Apply the post process
116
+ self.vao.render()
117
+
118
+
119
+ def _apply_to_framebuffer(self, source: Framebuffer, detination: Framebuffer=None) -> Framebuffer:
120
+ """
121
+ Applies a post process to a bsk.Framebuffer
122
+ """
123
+
124
+ # Create a blank framebuffer
125
+ if not detination or detination.size != self.size:
126
+ fbo = Framebuffer(self.engine, self.size, self.components)
127
+ old_filter = None
128
+ fbo.texture.filter = self.filter
129
+ else:
130
+ fbo = detination
131
+ old_filter = fbo.texture_filter
132
+ fbo.texture.filter = self.filter
133
+
134
+ # Load the source texture to the shader
135
+ for i, src in enumerate(source):
136
+ self.shader.program[src[0]] = i
137
+ src[1].texture.use(location=i)
138
+
139
+ fbo.use()
140
+ fbo.clear()
141
+ # Apply the post process
142
+ self.vao.render()
143
+
144
+ # Reset filter if needed
145
+ if old_filter: fbo.texture.filter = old_filter
146
+
147
+ # Return the fbo for the user
148
+ return fbo
149
+
150
+ def _apply_to_texture(self, source: mgl.Texture, destination: mgl.Texture) -> mgl.Texture:
151
+ """
152
+ Applies a post process to a mgl.Texture
153
+ """
154
+
155
+ # Render the post processs with the given texture
156
+ self._render_post_process(source)
157
+
158
+ # Make a deep copy of the modified texture
159
+ texture = self.ctx.texture(self.fbo.size, self.fbo.components, self.fbo.data)
160
+
161
+ return texture
162
+
163
+ def _apply_to_image(self, source: Image, destination: Image) -> Image:
164
+ """
165
+ Applies a post process to a bsk.Image
166
+ """
167
+
168
+ # Create a texture from the image data
169
+ texture = self.ctx.texture(self.fbo.size, self.fbo.components, source.data)
170
+
171
+ # Render the post processs with the given texture
172
+ self._render_post_process(source)
173
+
174
+ # Make an image from the texture
175
+ image = Image()
176
+ return image
177
+
178
+ def __del__(self):
179
+ if self.vao: self.vao.release()
180
+ if self.vbo: self.vbo.release()
181
181
  if self.fbo: self.fbo.__del__()