basilisk-engine 0.1.0__py3-none-any.whl → 0.1.1__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 (55) hide show
  1. basilisk/collisions/broad/broad_aabb.py +8 -1
  2. basilisk/collisions/broad/broad_bvh.py +8 -1
  3. basilisk/collisions/collider.py +15 -6
  4. basilisk/collisions/collider_handler.py +70 -68
  5. basilisk/collisions/narrow/contact_manifold.py +9 -10
  6. basilisk/collisions/narrow/dataclasses.py +27 -0
  7. basilisk/collisions/narrow/deprecated.py +47 -0
  8. basilisk/collisions/narrow/epa.py +11 -10
  9. basilisk/collisions/narrow/gjk.py +15 -14
  10. basilisk/collisions/narrow/helper.py +8 -7
  11. basilisk/collisions/narrow/sutherland_hodgman.py +52 -0
  12. basilisk/draw/draw_handler.py +5 -3
  13. basilisk/engine.py +14 -5
  14. basilisk/generic/abstract_custom.py +134 -0
  15. basilisk/generic/collisions.py +46 -0
  16. basilisk/generic/quat.py +77 -66
  17. basilisk/generic/vec3.py +91 -67
  18. basilisk/mesh/cube.py +20 -2
  19. basilisk/mesh/mesh.py +69 -54
  20. basilisk/mesh/mesh_from_data.py +106 -21
  21. basilisk/mesh/narrow_aabb.py +10 -1
  22. basilisk/mesh/narrow_bvh.py +9 -1
  23. basilisk/nodes/node.py +169 -30
  24. basilisk/nodes/node_handler.py +51 -30
  25. basilisk/particles/__init__.py +0 -0
  26. basilisk/particles/particle_handler.py +55 -0
  27. basilisk/particles/particle_renderer.py +87 -0
  28. basilisk/physics/impulse.py +7 -13
  29. basilisk/physics/physics_body.py +10 -2
  30. basilisk/physics/physics_engine.py +1 -2
  31. basilisk/render/batch.py +2 -2
  32. basilisk/render/camera.py +5 -0
  33. basilisk/render/chunk.py +19 -4
  34. basilisk/render/chunk_handler.py +33 -26
  35. basilisk/render/image.py +1 -1
  36. basilisk/render/image_handler.py +4 -3
  37. basilisk/render/light_handler.py +16 -11
  38. basilisk/render/material.py +25 -1
  39. basilisk/render/material_handler.py +22 -13
  40. basilisk/render/shader.py +7 -7
  41. basilisk/render/shader_handler.py +13 -12
  42. basilisk/render/sky.py +5 -3
  43. basilisk/scene.py +114 -32
  44. basilisk/shaders/batch.frag +40 -11
  45. basilisk/shaders/batch.vert +14 -7
  46. basilisk/shaders/normal.frag +5 -5
  47. basilisk/shaders/normal.vert +8 -3
  48. basilisk/shaders/particle.frag +72 -0
  49. basilisk/shaders/particle.vert +85 -0
  50. {basilisk_engine-0.1.0.dist-info → basilisk_engine-0.1.1.dist-info}/METADATA +5 -5
  51. basilisk_engine-0.1.1.dist-info/RECORD +95 -0
  52. basilisk/shaders/image.png +0 -0
  53. basilisk_engine-0.1.0.dist-info/RECORD +0 -88
  54. {basilisk_engine-0.1.0.dist-info → basilisk_engine-0.1.1.dist-info}/WHEEL +0 -0
  55. {basilisk_engine-0.1.0.dist-info → basilisk_engine-0.1.1.dist-info}/top_level.txt +0 -0
@@ -6,8 +6,8 @@ class PhysicsBody():
6
6
  mass: float
7
7
  """The mass of the physics body in kg"""
8
8
 
9
- def __init__(self, physics_engine, mass:float=1.0) -> None:
10
- self.physics_engine = physics_engine
9
+ def __init__(self, mass:float=1.0) -> None:
10
+ self.physics_engine = None
11
11
  self.mass = mass
12
12
 
13
13
  def get_delta_velocity(self, dt: float) -> glm.vec3:
@@ -32,5 +32,13 @@ class PhysicsBody():
32
32
  # TODO add torques
33
33
  return dw
34
34
 
35
+ @property
36
+ def physics_engine(self): return self._physics_engine
37
+
38
+ @physics_engine.setter
39
+ def physics_engine(self, value):
40
+ self._physics_engine = value
41
+ if value: value.add(self)
42
+
35
43
  def __repr__(self) -> str:
36
44
  return f'<Physics Body| {self.mass}>'
@@ -20,11 +20,10 @@ class PhysicsEngine():
20
20
  self.forces = forces if forces else []
21
21
  self.torques = torques if torques else []
22
22
 
23
- def add(self, mass: float) -> PhysicsBody:
23
+ def add(self, physics_body: PhysicsBody) -> PhysicsBody:
24
24
  """
25
25
  Adds a physics body to the physics engine and returns it
26
26
  """
27
- physics_body = PhysicsBody(self, mass)
28
27
  self.physics_bodies.append(physics_body)
29
28
  return physics_body
30
29
 
basilisk/render/batch.py CHANGED
@@ -23,7 +23,7 @@ class Batch():
23
23
  # Back references
24
24
  self.chunk = chunk
25
25
  self.ctx = chunk.chunk_handler.engine.ctx
26
- self.program = chunk.chunk_handler.program
26
+ self.program = self.chunk.get_program()
27
27
 
28
28
  # Set intial values
29
29
  self.vbo = None
@@ -35,7 +35,7 @@ class Batch():
35
35
  Returns True if batch was successful.
36
36
  """
37
37
 
38
- self.program = self.chunk.chunk_handler.program
38
+ self.program = self.chunk.get_program()
39
39
 
40
40
  # Empty list to contain all vertex data of models in the chunk
41
41
  batch_data = []
basilisk/render/camera.py CHANGED
@@ -85,6 +85,11 @@ class Camera:
85
85
  def get_params(self) -> tuple:
86
86
  return self.engine, self.position, self.yaw, self.pitch
87
87
 
88
+ def look_at(self, other) -> None:
89
+ forward = glm.normalize(other.position - self.position)
90
+ self.yaw = np.degrees(np.arctan2(forward.z, forward.x))
91
+ self.pitch = np.degrees(np.arctan2(forward.y, np.sqrt(forward.x ** 2 + forward.z ** 2)))
92
+
88
93
  def __repr__(self):
89
94
  return f'<Basilisk Camera | Position: {self.position}, Direction: {self.forward}>'
90
95
 
basilisk/render/chunk.py CHANGED
@@ -4,7 +4,7 @@ from .batch import Batch
4
4
  class Chunk():
5
5
  chunk_handler: ...
6
6
  """Back refrence to the parent chunk handler"""
7
- chunk_key: tuple
7
+ position: tuple
8
8
  """The position of the chunk. Used as a key in the chunk handler"""
9
9
  batch: Batch
10
10
  """Batched mesh of the chunk"""
@@ -13,7 +13,7 @@ class Chunk():
13
13
  static: bool
14
14
  """Type of node that the chunk recognizes"""
15
15
 
16
- def __init__(self, chunk_handler, chunk_key: tuple, static: bool) -> None:
16
+ def __init__(self, chunk_handler, position: tuple, static: bool, shader=None) -> None:
17
17
  """
18
18
  Basilisk chunk object.
19
19
  Contains references to all nodes in the chunk.
@@ -22,9 +22,11 @@ class Chunk():
22
22
 
23
23
  # Back references
24
24
  self.chunk_handler = chunk_handler
25
- self.chunk_key = chunk_key
26
25
 
26
+ # Chunk Attrbiutes
27
+ self.position = position
27
28
  self.static = static
29
+ self.shader = shader
28
30
 
29
31
  # Create empty batch
30
32
  self.batch = Batch(self)
@@ -70,12 +72,25 @@ class Chunk():
70
72
  Removes a node from the chunk
71
73
  """
72
74
 
75
+ if node == None: return
76
+
73
77
  self.nodes.remove(node)
78
+ if self.batch and self.batch.vbo: self.batch.vbo.clear()
74
79
 
75
80
  return node
76
81
 
82
+ def get_program(self):
83
+ """
84
+ Gets the program of the chunks nodes' shader
85
+ """
86
+
87
+ shader = self.shader
88
+
89
+ if shader: return shader.program
90
+ return self.chunk_handler.engine.shader.program
91
+
77
92
  def __repr__(self) -> str:
78
- return f'<Basilisk Chunk | {self.chunk_key}, {len(self.nodes)} nodes, {'static' if self.static else 'dynamic'}>'
93
+ return f'<Basilisk Chunk | {self.position}, {len(self.nodes)} nodes, {"static" if self.static else "dynamic"}>'
79
94
 
80
95
  def __del__(self) -> None:
81
96
  """
@@ -15,8 +15,8 @@ class ChunkHandler():
15
15
  """Reference to the shader program used by batches"""
16
16
  chunks: list[dict]
17
17
  """List containing two dictionaries for dynamic and static chunks repsectivly"""
18
- updated_chunks: list[set]
19
- """List containing two dictionaries for recently updated dynamic and static chunks repsectivly"""
18
+ updated_chunks: set
19
+ """Set containing recently updated chunks"""
20
20
 
21
21
  def __init__(self, scene) -> None:
22
22
  # Reference to the scene hadlers and variables
@@ -31,8 +31,9 @@ class ChunkHandler():
31
31
  self.program = scene.engine.shader.program
32
32
 
33
33
  # List for the dynamic and static chunk dictionaries | [dyanmic: dict, static: dict]
34
- self.chunks = [{} , {} ]
35
- self.updated_chunks = [set(), set()]
34
+ self.shader_groups = {None : ({}, {})}
35
+ # self.chunks = [{}, {}]
36
+ self.updated_chunks = set()
36
37
 
37
38
 
38
39
  def render(self) -> None:
@@ -47,10 +48,12 @@ class ChunkHandler():
47
48
  chunk_keys = [(x, y, z) for x in range(*render_range_x) for y in range(*render_range_y) for z in range(*render_range_z)]
48
49
 
49
50
  # Loop through all chunks in view and render
50
- for chunk in chunk_keys:
51
- # Render the chunk if it exists
52
- if chunk in self.chunks[0]: self.chunks[0][chunk].render()
53
- if chunk in self.chunks[1]: self.chunks[1][chunk].render()
51
+ for shader, group in self.shader_groups.items():
52
+ if shader == None: shader = self.engine.shader
53
+ for chunk in chunk_keys:
54
+ # Render the chunk if it exists
55
+ if chunk in group[0]: group[0][chunk].render()
56
+ if chunk in group[1]: group[1][chunk].render()
54
57
 
55
58
 
56
59
  def update(self) -> None:
@@ -63,27 +66,24 @@ class ChunkHandler():
63
66
  # Loop through the set of updated chunk keys and update the chunk
64
67
  removes = []
65
68
 
66
- for chunk in self.updated_chunks[0]:
69
+ for chunk in self.updated_chunks:
67
70
  if chunk.update(): continue
68
- removes.append((0, chunk))
69
- for chunk in self.updated_chunks[1]:
70
- if chunk.update(): continue
71
- removes.append((1, chunk))
71
+ removes.append(chunk)
72
72
 
73
73
  # Remove any empty chunks
74
- for chunk_tuple in removes:
75
- if chunk_tuple[1] not in self.chunks[chunk_tuple[0]]: continue
76
- del self.chunks[chunk_tuple[0]][chunk_tuple[1]]
74
+ for chunk in removes:
75
+ del self.shader_groups[chunk.shader][chunk.static][chunk.position]
77
76
 
78
77
  # Clears the set of updated chunks so that they are not updated unless they are updated again
79
- self.updated_chunks = [set(), set()]
78
+ self.updated_chunks.clear()
80
79
 
81
80
  def update_all(self):
82
81
  self.program = self.scene.engine.shader.program
83
- for chunk in self.chunks[0].values():
84
- self.updated_chunks[0].add(chunk)
85
- for chunk in self.chunks[1].values():
86
- self.updated_chunks[1].add(chunk)
82
+ for shader in self.shader_groups.values():
83
+ for chunk in shader[0].values():
84
+ self.updated_chunks.add(chunk)
85
+ for chunk in shader[1].values():
86
+ self.updated_chunks.add(chunk)
87
87
 
88
88
  def add(self, node: Node) -> Node:
89
89
  """
@@ -93,24 +93,31 @@ class ChunkHandler():
93
93
  # The key of the chunk the node will be added to
94
94
  chunk_size = self.engine.config.chunk_size
95
95
  chunk_key = (int(node.x // chunk_size), int(node.y // chunk_size), int(node.z // chunk_size))
96
+ shader = node.shader
97
+
98
+ if shader not in self.shader_groups:
99
+ self.shader_groups[shader] = ({}, {})
96
100
 
97
101
  # Ensure that the chunk exists
98
- if chunk_key not in self.chunks[node.static]:
99
- self.chunks[node.static][chunk_key] = Chunk(self, chunk_key, node.static)
102
+ if chunk_key not in self.shader_groups[shader][node.static]:
103
+ chunk = Chunk(self, chunk_key, node.static, shader)
104
+ self.shader_groups[shader][node.static][chunk_key] = chunk
100
105
 
101
106
  # Add the node to the chunk
102
- self.chunks[node.static][chunk_key].add(node)
107
+ self.shader_groups[shader][node.static][chunk_key].add(node)
103
108
 
104
109
  # Update the chunk
105
- self.updated_chunks[node.static].add(self.chunks[node.static][chunk_key])
110
+ self.updated_chunks.add(self.shader_groups[shader][node.static][chunk_key])
106
111
 
107
112
  return Node
108
113
 
109
- def remove(self, node) -> None:
114
+ def remove(self, node: Node) -> None:
110
115
  """
111
116
  Removes a node from the its chunk
112
117
  """
113
118
 
119
+ if node == None: return
120
+
114
121
  # Remove the node
115
122
  chunk = node.chunk
116
123
  chunk.remove(node)
basilisk/render/image.py CHANGED
@@ -7,7 +7,7 @@ import pygame as pg
7
7
  from PIL import Image as PIL_Image
8
8
 
9
9
 
10
- texture_sizes = (128, 256, 512, 1024, 2048)
10
+ texture_sizes = (8, 64, 512, 1024, 2048)
11
11
 
12
12
 
13
13
  class Image():
@@ -3,7 +3,7 @@ import glm
3
3
  import numpy as np
4
4
 
5
5
 
6
- texture_sizes = (128, 256, 512, 1024, 2048)
6
+ texture_sizes = (8, 64, 512, 1024, 2048)
7
7
 
8
8
 
9
9
  class ImageHandler():
@@ -73,7 +73,8 @@ class ImageHandler():
73
73
  self.texture_arrays[size] = self.ctx.texture_array(size=dim, components=4, data=array_data)
74
74
  # Texture OpenGl settings
75
75
  self.texture_arrays[size].build_mipmaps()
76
- self.texture_arrays[size].filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
76
+ if size > 32: self.texture_arrays[size].filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
77
+ else: self.texture_arrays[size].filter = (mgl.NEAREST, mgl.NEAREST)
77
78
  self.texture_arrays[size].anisotropy = 32.0
78
79
 
79
80
  def write(self, regenerate=False) -> None:
@@ -85,7 +86,7 @@ class ImageHandler():
85
86
 
86
87
  if not self.texture_arrays: return
87
88
 
88
- for shader in self.engine.scene.shader_handler.shaders.values():
89
+ for shader in self.engine.scene.shader_handler.shaders:
89
90
  if 'textureArrays[5]' not in shader.uniforms: continue
90
91
 
91
92
  for i, size in enumerate(texture_sizes):
@@ -38,17 +38,22 @@ class LightHandler():
38
38
  Writes all the lights in a scene to the given shader program
39
39
  """
40
40
 
41
- if not program: program = self.engine.shader.program
41
+ # if not program: program = self.engine.shader.program
42
42
 
43
- if directional and self.directional_lights and 'numDirLights' in self.engine.shader.uniforms:
43
+ for shader in self.scene.shader_handler.shaders:
44
+ if 'numDirLights' not in shader.uniforms: continue
45
+
46
+ program = shader.program
44
47
 
45
- program['numDirLights'].write(glm.int32(len(self.directional_lights)))
48
+ if directional and self.directional_lights and 'numDirLights' in self.engine.shader.uniforms:
46
49
 
47
- for i, light in enumerate(self.directional_lights):
48
- program[f'dirLights[{i}].direction'].write(light.direction)
49
- program[f'dirLights[{i}].intensity'].write(glm.float32(light.intensity))
50
- program[f'dirLights[{i}].color' ].write(light.color / 255.0)
51
- program[f'dirLights[{i}].ambient' ].write(glm.float32(light.ambient))
52
-
53
- if point:
54
- ...
50
+ program['numDirLights'].write(glm.int32(len(self.directional_lights)))
51
+
52
+ for i, light in enumerate(self.directional_lights):
53
+ program[f'dirLights[{i}].direction'].write(light.direction)
54
+ program[f'dirLights[{i}].intensity'].write(glm.float32(light.intensity))
55
+ program[f'dirLights[{i}].color' ].write(light.color / 255.0)
56
+ program[f'dirLights[{i}].ambient' ].write(glm.float32(light.ambient))
57
+
58
+ if point:
59
+ ...
@@ -41,7 +41,7 @@ class Material():
41
41
  clearcoat_gloss: float
42
42
  """The glossiness of the clearcoat layer. 0 For a satin appearance, 1 for a gloss appearance"""
43
43
 
44
- def __init__(self, name: str=None, color: tuple=(255.0, 255.0, 255.0), texture: Image=None, normal: Image=None,
44
+ def __init__(self, name: str=None, color: tuple=(255.0, 255.0, 255.0), texture: Image=None, normal: Image=None, roughness_map: Image=None, ao_map: Image=None,
45
45
  roughness: float=0.7, subsurface: float=0.2, sheen: float=0.5, sheen_tint: float=0.5,
46
46
  anisotropic: float=0.0, specular: float=1.0, metallicness: float=0.0, specular_tint: float=0.0,
47
47
  clearcoat: float=0.5, clearcoat_gloss: float=0.25) -> None:
@@ -67,6 +67,8 @@ class Material():
67
67
  self.color = color
68
68
  self.texture = texture
69
69
  self.normal = normal
70
+ self.roughness_map = roughness_map
71
+ self.ao_map = ao_map
70
72
  self.roughness = roughness
71
73
  self.subsurface = subsurface
72
74
  self.sheen = sheen
@@ -96,6 +98,14 @@ class Material():
96
98
  if self.normal: data.extend([1, self.normal.index.x, self.normal.index.y])
97
99
  else: data.extend([0, 0, 0])
98
100
 
101
+ # Add roughness data
102
+ if self.roughness_map: data.extend([1, self.roughness_map.index.x, self.roughness_map.index.y])
103
+ else: data.extend([0, 0, 0])
104
+
105
+ # Add ao data
106
+ if self.ao_map: data.extend([1, self.ao_map.index.x, self.ao_map.index.y])
107
+ else: data.extend([0, 0, 0])
108
+
99
109
  return data
100
110
 
101
111
  def __repr__(self) -> str:
@@ -109,6 +119,10 @@ class Material():
109
119
  @property
110
120
  def normal(self): return self._normal
111
121
  @property
122
+ def roughness_map(self): return self._roughness_map
123
+ @property
124
+ def ao_map(self): return self._ao_map
125
+ @property
112
126
  def roughness(self): return self._roughness
113
127
  @property
114
128
  def subsurface(self): return self._subsurface
@@ -145,6 +159,16 @@ class Material():
145
159
  self._normal = validate_image("Material", "normal map", value)
146
160
  if self.material_handler: self.material_handler.write(regenerate=True)
147
161
 
162
+ @roughness_map.setter
163
+ def roughness_map(self, value: Image | None):
164
+ self._roughness_map = validate_image("Material", "roughness_map", value)
165
+ if self.material_handler: self.material_handler.write(regenerate=True)
166
+
167
+ @ao_map.setter
168
+ def ao_map(self, value: Image | None):
169
+ self._ao_map = validate_image("Material", "ao_map map", value)
170
+ if self.material_handler: self.material_handler.write(regenerate=True)
171
+
148
172
  @roughness.setter
149
173
  def roughness(self, value: float | int | glm.float32):
150
174
  self._roughness = validate_float("Material", "roughness", value)
@@ -39,18 +39,27 @@ class MaterialHandler():
39
39
  Adds the given material to the handler if it is not already present
40
40
  """
41
41
 
42
- # Check that the material is not already in the scene
43
- if material in self.materials: return None
44
- # Update the material's handler
45
- material.material_handler = self
46
- # Add images
47
- if material.texture: self.image_handler.add(material.texture)
48
- if material.normal: self.image_handler.add(material.normal)
49
-
50
- # Add the material
51
- self.materials.append(material)
42
+ write = False
43
+
44
+ if isinstance(material, Material): material = [material]
45
+
46
+ for mtl in material:
47
+ # Check that the material is not already in the scene
48
+ if mtl in self.materials: continue
49
+ # Update the material's handler
50
+ mtl.material_handler = self
51
+ # Add images
52
+ if mtl.texture: self.image_handler.add(mtl.texture)
53
+ if mtl.normal: self.image_handler.add(mtl.normal)
54
+
55
+ # Add the material
56
+ self.materials.append(mtl)
57
+
58
+ write = True
59
+
60
+
52
61
  # Write materials
53
- self.write(regenerate=True)
62
+ if write: self.write(regenerate=True)
54
63
 
55
64
  def generate_material_texture(self) -> None:
56
65
  """
@@ -64,7 +73,7 @@ class MaterialHandler():
64
73
  if self.data_texture: self.data_texture.release()
65
74
 
66
75
  # Create empty texture data
67
- material_data = np.zeros(shape=(len(self.materials), 19), dtype="f4")
76
+ material_data = np.zeros(shape=(len(self.materials), 25), dtype="f4")
68
77
 
69
78
  # Get data from the materials
70
79
  for i, mtl in enumerate(self.materials):
@@ -84,7 +93,7 @@ class MaterialHandler():
84
93
 
85
94
  if not self.data_texture: return
86
95
 
87
- for shader in self.engine.scene.shader_handler.shaders.values():
96
+ for shader in self.engine.scene.shader_handler.shaders:
88
97
  if 'materialsTexture' not in shader.uniforms: continue
89
98
 
90
99
  shader.program['materialsTexture'] = 9
basilisk/render/shader.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import moderngl as mgl
2
-
2
+ import random
3
3
 
4
4
  attribute_mappings = {
5
5
  'in_position' : [0, 1, 2],
@@ -60,7 +60,10 @@ class Shader:
60
60
  self.fragment_shader = file.read()
61
61
 
62
62
  # Hash value for references
63
- self.hash = hash((self.vertex_shader, self.fragment_shader))
63
+ if vert == None and frag == None:
64
+ self.hash = hash((self.vertex_shader, self.fragment_shader, 'default'))
65
+ else:
66
+ self.hash = hash((self.vertex_shader, self.fragment_shader))
64
67
 
65
68
  # Create a string of all lines in both shaders
66
69
  lines = f'{self.vertex_shader}\n{self.fragment_shader}'.split('\n')
@@ -85,15 +88,12 @@ class Shader:
85
88
  # Create a program with shaders
86
89
  self.program = self.ctx.program(vertex_shader=self.vertex_shader, fragment_shader=self.fragment_shader)
87
90
 
88
- def use(self):
91
+ def set_main(self):
89
92
  """
90
93
  Selects a shader for use
91
94
  """
92
95
 
93
- self.engine.scene.shader_handler.add('default', self)
94
- self.engine.scene.light_handler.write()
95
- self.engine.scene.material_handler.write()
96
- self.engine.scene.sky.write()
96
+ self.engine.scene.shader_handler.add(self)
97
97
  self.engine.scene.node_handler.chunk_handler.update_all()
98
98
 
99
99
  def write(self, name: str, value) -> None:
@@ -10,7 +10,7 @@ class ShaderHandler:
10
10
  """Back reference to the parent scene"""
11
11
  ctx: mgl.Context
12
12
  """Back reference to the parent context"""
13
- shaders: list = []
13
+ shaders: set
14
14
  """Dictionary containing all the shaders"""
15
15
  uniform_values: dict = {}
16
16
  """Dictionary containing uniform values"""
@@ -26,27 +26,28 @@ class ShaderHandler:
26
26
  self.ctx = scene.engine.ctx
27
27
 
28
28
  # Initalize dictionaries
29
- self.shaders = {}
29
+ self.shaders = set()
30
+ self.add(self.engine.shader)
30
31
 
31
- root = self.engine.root
32
- self.add('default', self.engine.shader)
33
- self.add('draw', Shader(self.engine, root + '/shaders/draw.vert' , root + '/shaders/draw.frag' ))
34
- self.add('sky', Shader(self.engine, root + '/shaders/sky.vert' , root + '/shaders/sky.frag' ))
35
-
36
- def add(self, name: str, shader: Shader) -> None:
32
+ def add(self, shader: Shader) -> None:
37
33
  """
38
34
  Creates a shader program from a file name.
39
35
  Parses through shaders to identify uniforms and save for writting
40
36
  """
41
37
 
42
- if shader in self.shaders.values(): return
43
38
 
44
- self.shaders[name] = shader
39
+ if not shader: return None
40
+ if shader in self.shaders: return shader
41
+
42
+ self.shaders.add(shader)
45
43
 
46
44
  if self.scene.material_handler:
45
+ self.scene.light_handler.write()
47
46
  self.scene.material_handler.write()
48
47
  self.scene.material_handler.image_handler.write()
49
48
 
49
+ return shader
50
+
50
51
  def get_uniforms_values(self) -> None:
51
52
  """
52
53
  Gets uniforms from various parts of the scene.
@@ -67,7 +68,7 @@ class ShaderHandler:
67
68
 
68
69
  self.get_uniforms_values()
69
70
  for uniform in self.uniform_values:
70
- for shader in self.shaders.values():
71
+ for shader in self.shaders:
71
72
  if not uniform in shader.uniforms: continue # Does not write uniforms not in the shader
72
73
  shader.write(uniform, self.uniform_values[uniform])
73
74
 
@@ -76,4 +77,4 @@ class ShaderHandler:
76
77
  Releases all shader programs in handler
77
78
  """
78
79
 
79
- [shader.__del__() for shader in self.shaders.values()]
80
+ [shader.__del__() for shader in self.shaders]
basilisk/render/sky.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import numpy as np
2
2
  from PIL import Image as PIL_Image
3
+ from .shader import Shader
3
4
 
4
5
  class Sky:
5
6
  texture_cube=None
@@ -26,7 +27,7 @@ class Sky:
26
27
 
27
28
  def write(self):
28
29
  # Write the texture cube to the sky shader
29
- self.program['skyboxTexture'] = 8
30
+ self.shader.program['skyboxTexture'] = 8
30
31
  self.texture_cube.use(location = 8)
31
32
 
32
33
  shader = self.scene.engine.shader
@@ -106,8 +107,9 @@ class Sky:
106
107
 
107
108
  # Create a renderable vao
108
109
  self.vbo = self.ctx.buffer(vertex_data)
109
- self.program = self.scene.shader_handler.shaders['sky'].program
110
- self.vao = self.ctx.vertex_array(self.program, [(self.vbo, '3f', 'in_position')], skip_errors=True)
110
+ root = self.scene.engine.root
111
+ self.shader = self.scene.shader_handler.add(Shader(self.scene.engine, root + '/shaders/sky.vert', root + '/shaders/sky.frag'))
112
+ self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f', 'in_position')], skip_errors=True)
111
113
 
112
114
  def __del__(self):
113
115
  """