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.
- basilisk/collisions/broad/broad_aabb.py +8 -1
- basilisk/collisions/broad/broad_bvh.py +8 -1
- basilisk/collisions/collider.py +15 -6
- basilisk/collisions/collider_handler.py +70 -68
- basilisk/collisions/narrow/contact_manifold.py +9 -10
- basilisk/collisions/narrow/dataclasses.py +27 -0
- basilisk/collisions/narrow/deprecated.py +47 -0
- basilisk/collisions/narrow/epa.py +11 -10
- basilisk/collisions/narrow/gjk.py +15 -14
- basilisk/collisions/narrow/helper.py +8 -7
- basilisk/collisions/narrow/sutherland_hodgman.py +52 -0
- basilisk/draw/draw_handler.py +5 -3
- basilisk/engine.py +14 -5
- basilisk/generic/abstract_custom.py +134 -0
- basilisk/generic/collisions.py +46 -0
- basilisk/generic/quat.py +77 -66
- basilisk/generic/vec3.py +91 -67
- basilisk/mesh/cube.py +20 -2
- basilisk/mesh/mesh.py +69 -54
- basilisk/mesh/mesh_from_data.py +106 -21
- basilisk/mesh/narrow_aabb.py +10 -1
- basilisk/mesh/narrow_bvh.py +9 -1
- basilisk/nodes/node.py +169 -30
- basilisk/nodes/node_handler.py +51 -30
- basilisk/particles/__init__.py +0 -0
- basilisk/particles/particle_handler.py +55 -0
- basilisk/particles/particle_renderer.py +87 -0
- basilisk/physics/impulse.py +7 -13
- basilisk/physics/physics_body.py +10 -2
- basilisk/physics/physics_engine.py +1 -2
- basilisk/render/batch.py +2 -2
- basilisk/render/camera.py +5 -0
- basilisk/render/chunk.py +19 -4
- basilisk/render/chunk_handler.py +33 -26
- basilisk/render/image.py +1 -1
- basilisk/render/image_handler.py +4 -3
- basilisk/render/light_handler.py +16 -11
- basilisk/render/material.py +25 -1
- basilisk/render/material_handler.py +22 -13
- basilisk/render/shader.py +7 -7
- basilisk/render/shader_handler.py +13 -12
- basilisk/render/sky.py +5 -3
- basilisk/scene.py +114 -32
- basilisk/shaders/batch.frag +40 -11
- basilisk/shaders/batch.vert +14 -7
- basilisk/shaders/normal.frag +5 -5
- basilisk/shaders/normal.vert +8 -3
- basilisk/shaders/particle.frag +72 -0
- basilisk/shaders/particle.vert +85 -0
- {basilisk_engine-0.1.0.dist-info → basilisk_engine-0.1.1.dist-info}/METADATA +5 -5
- basilisk_engine-0.1.1.dist-info/RECORD +95 -0
- basilisk/shaders/image.png +0 -0
- basilisk_engine-0.1.0.dist-info/RECORD +0 -88
- {basilisk_engine-0.1.0.dist-info → basilisk_engine-0.1.1.dist-info}/WHEEL +0 -0
- {basilisk_engine-0.1.0.dist-info → basilisk_engine-0.1.1.dist-info}/top_level.txt +0 -0
basilisk/scene.py
CHANGED
|
@@ -12,7 +12,9 @@ from .collisions.collider_handler import ColliderHandler
|
|
|
12
12
|
from .draw.draw_handler import DrawHandler
|
|
13
13
|
from .render.sky import Sky
|
|
14
14
|
from .render.frame import Frame
|
|
15
|
-
|
|
15
|
+
from .particles.particle_handler import ParticleHandler
|
|
16
|
+
from .nodes.node import Node
|
|
17
|
+
from .generic.collisions import moller_trumbore
|
|
16
18
|
|
|
17
19
|
class Scene():
|
|
18
20
|
engine: any
|
|
@@ -43,6 +45,7 @@ class Scene():
|
|
|
43
45
|
"""
|
|
44
46
|
|
|
45
47
|
self.node_handler.update()
|
|
48
|
+
self.particle.update()
|
|
46
49
|
self.camera.update()
|
|
47
50
|
self.collider_handler.resolve_collisions()
|
|
48
51
|
|
|
@@ -53,39 +56,50 @@ class Scene():
|
|
|
53
56
|
|
|
54
57
|
self.frame.use()
|
|
55
58
|
self.shader_handler.write()
|
|
56
|
-
self.sky.render()
|
|
59
|
+
if self.sky: self.sky.render()
|
|
57
60
|
self.node_handler.render()
|
|
61
|
+
self.particle.render()
|
|
58
62
|
self.draw_handler.render()
|
|
59
63
|
|
|
60
64
|
if self.engine.headless: return
|
|
61
65
|
self.frame.render()
|
|
62
66
|
|
|
63
|
-
def
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
material: Material=None,
|
|
70
|
-
velocity: glm.vec3=None,
|
|
71
|
-
rotational_velocity: glm.quat=None,
|
|
72
|
-
physics: bool=False,
|
|
73
|
-
mass: float=None,
|
|
74
|
-
collisions: bool=False,
|
|
75
|
-
collider: str=None,
|
|
76
|
-
static_friction: float=None,
|
|
77
|
-
kinetic_friction: float=None,
|
|
78
|
-
elasticity: float=None,
|
|
79
|
-
collision_group : float=None,
|
|
80
|
-
name: str='',
|
|
81
|
-
tags: list[str]=None,
|
|
82
|
-
static: bool=None):
|
|
67
|
+
def add(self, bsk_object: ...) -> ...:
|
|
68
|
+
"""
|
|
69
|
+
Adds an object to the scene. Can pass in any scene objects:
|
|
70
|
+
Argument overloads:
|
|
71
|
+
object: Node - Adds the given node to the scene.
|
|
72
|
+
"""
|
|
83
73
|
|
|
84
|
-
if
|
|
85
|
-
|
|
74
|
+
if isinstance(bsk_object, type(None)):
|
|
75
|
+
# Considered well defined behavior
|
|
76
|
+
return
|
|
77
|
+
elif isinstance(bsk_object, Node):
|
|
78
|
+
# Add a node to the scene
|
|
79
|
+
return self.node_handler.add(bsk_object)
|
|
80
|
+
# Light
|
|
81
|
+
|
|
82
|
+
# Mesh
|
|
83
|
+
|
|
84
|
+
else:
|
|
85
|
+
raise ValueError(f'scene.add: Incompatable object add type {type(bsk_object)}')
|
|
86
|
+
|
|
87
|
+
return None
|
|
86
88
|
|
|
87
|
-
|
|
89
|
+
def remove(self, bsk_object):
|
|
90
|
+
"""
|
|
91
|
+
Removes the given baskilsk object from the scene
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
if isinstance(bsk_object, type(None)):
|
|
95
|
+
# Considered well defined behavior
|
|
96
|
+
return
|
|
97
|
+
elif isinstance(bsk_object, Node):
|
|
98
|
+
self.node_handler.remove(bsk_object)
|
|
99
|
+
else:
|
|
100
|
+
raise ValueError(f'scene.remove: Incompatable object remove type {type(bsk_object)}')
|
|
88
101
|
|
|
102
|
+
return None
|
|
89
103
|
|
|
90
104
|
def set_engine(self, engine: any) -> None:
|
|
91
105
|
"""
|
|
@@ -97,14 +111,84 @@ class Scene():
|
|
|
97
111
|
|
|
98
112
|
self.camera = FreeCamera()
|
|
99
113
|
self.shader_handler = ShaderHandler(self)
|
|
114
|
+
self.material_handler = MaterialHandler(self)
|
|
115
|
+
self.light_handler = LightHandler(self)
|
|
100
116
|
self.physics_engine = PhysicsEngine()
|
|
101
117
|
self.node_handler = NodeHandler(self)
|
|
118
|
+
self.particle = ParticleHandler(self)
|
|
102
119
|
self.collider_handler = ColliderHandler(self)
|
|
103
|
-
self.material_handler = MaterialHandler(self)
|
|
104
|
-
self.light_handler = LightHandler(self)
|
|
105
120
|
self.draw_handler = DrawHandler(self)
|
|
106
121
|
self.frame = Frame(self)
|
|
107
122
|
self.sky = Sky(self.engine)
|
|
123
|
+
|
|
124
|
+
def raycast(self, position: glm.vec3=None, forward: glm.vec3=None, max_distance: float=1e5, has_collisions: bool=None, has_physics: bool=None, tags: list[str]=[]) -> tuple[Node, glm.vec3]:
|
|
125
|
+
"""
|
|
126
|
+
Ray cast from any posiiton and forward vector and returns the nearest node. If no position or forward is given, uses the scene camera's current position and forward
|
|
127
|
+
"""
|
|
128
|
+
if not position: position = self.camera.position
|
|
129
|
+
if not forward: forward = self.camera.forward
|
|
130
|
+
forward = glm.normalize(forward)
|
|
131
|
+
|
|
132
|
+
# if we are filtering for collisions, use the broad BVH to improve performance
|
|
133
|
+
if has_collisions:
|
|
134
|
+
colliders = self.collider_handler.bvh.get_line_collided(position, forward)
|
|
135
|
+
nodes = [collider.node for collider in colliders]
|
|
136
|
+
|
|
137
|
+
def is_valid(node: Node) -> bool:
|
|
138
|
+
return all([
|
|
139
|
+
has_collisions is None or bool(node.collider) == has_collisions,
|
|
140
|
+
has_physics is None or bool(node.physics_body) == has_physics,
|
|
141
|
+
all(tag in node.tags for tag in tags)
|
|
142
|
+
])
|
|
143
|
+
|
|
144
|
+
nodes: list[Node] = list(filter(lambda node: is_valid(node), nodes))
|
|
145
|
+
|
|
146
|
+
# if we are not filtering for collisions, filter nodes and
|
|
147
|
+
else: nodes = self.node_handler.get_all(collisions=has_collisions, physics=has_physics, tags=tags)
|
|
148
|
+
|
|
149
|
+
# determine closest node
|
|
150
|
+
best_distance, best_point, best_node = max_distance, None, None
|
|
151
|
+
position_two = position + forward
|
|
152
|
+
for node in nodes:
|
|
153
|
+
|
|
154
|
+
inv_mat = glm.inverse(node.model_matrix)
|
|
155
|
+
relative_position = inv_mat * position
|
|
156
|
+
relative_forward = glm.normalize(inv_mat * position_two - relative_position)
|
|
157
|
+
|
|
158
|
+
triangles = [node.mesh.indices[i] for i in node.mesh.get_line_collided(relative_position, relative_forward)]
|
|
159
|
+
|
|
160
|
+
for triangle in triangles:
|
|
161
|
+
intersection = moller_trumbore(relative_position, relative_forward, [node.mesh.points[i] for i in triangle])
|
|
162
|
+
if not intersection: continue
|
|
163
|
+
intersection = node.model_matrix * intersection
|
|
164
|
+
distance = glm.length(intersection - position)
|
|
165
|
+
if distance < best_distance:
|
|
166
|
+
best_distance = distance
|
|
167
|
+
best_point = intersection
|
|
168
|
+
best_node = node
|
|
169
|
+
|
|
170
|
+
return best_node, best_point
|
|
171
|
+
|
|
172
|
+
def raycast_mouse(self, position: tuple[int, int] | glm.vec2, max_distance: float=1e5, has_collisions: bool=None, has_pshyics: bool=None, tags: list[str]=[]) -> tuple[Node, glm.vec3]:
|
|
173
|
+
"""
|
|
174
|
+
Ray casts from the mouse position with respect to the camera. Returns the nearest node that was clicked, if none was clicked, returns None.
|
|
175
|
+
"""
|
|
176
|
+
# derive forward vector from mouse click position
|
|
177
|
+
position = glm.vec2(position)
|
|
178
|
+
inv_proj, inv_view = glm.inverse(self.camera.m_proj), glm.inverse(self.camera.m_view)
|
|
179
|
+
ndc = glm.vec4(2 * position[0] / self.engine.win_size[0] - 1, 1 - 2 * position[1] / self.engine.win_size[1], 1, 1)
|
|
180
|
+
point = inv_proj * ndc
|
|
181
|
+
point /= point.w
|
|
182
|
+
forward = glm.normalize(glm.vec3(inv_view * glm.vec4(point.x, point.y, point.z, 0)))
|
|
183
|
+
|
|
184
|
+
return self.raycast(
|
|
185
|
+
position=self.camera.position,
|
|
186
|
+
forward=forward,
|
|
187
|
+
max_distance=max_distance,
|
|
188
|
+
has_collisions=has_collisions,
|
|
189
|
+
has_physics=has_pshyics,
|
|
190
|
+
tags=tags
|
|
191
|
+
)
|
|
108
192
|
|
|
109
193
|
@property
|
|
110
194
|
def camera(self): return self._camera
|
|
@@ -121,9 +205,7 @@ class Scene():
|
|
|
121
205
|
|
|
122
206
|
@sky.setter
|
|
123
207
|
def sky(self, value: Sky):
|
|
124
|
-
if not value:
|
|
125
|
-
|
|
126
|
-
raise TypeError(f'Scene: Invalid sky type: {type(value)}. Expected type bsk.Sky')
|
|
208
|
+
if not isinstance(value, Sky) and not isinstance(value, type(None)):
|
|
209
|
+
raise TypeError(f'Scene: Invalid sky type: {type(value)}. Expected type bsk.Sky or None')
|
|
127
210
|
self._sky = value
|
|
128
|
-
self._sky.write()
|
|
129
|
-
|
|
211
|
+
if value: self._sky.write()
|
basilisk/shaders/batch.frag
CHANGED
|
@@ -31,6 +31,10 @@ struct Material {
|
|
|
31
31
|
vec2 albedoMap;
|
|
32
32
|
int hasNormalMap;
|
|
33
33
|
vec2 normalMap;
|
|
34
|
+
int hasRoughnessMap;
|
|
35
|
+
vec2 roughnessMap;
|
|
36
|
+
int hasAoMap;
|
|
37
|
+
vec2 aoMap;
|
|
34
38
|
};
|
|
35
39
|
|
|
36
40
|
struct LightResult {
|
|
@@ -92,7 +96,7 @@ float AnisotropicSmithGGX(float ndots, float sdotx, float sdoty, float ax, float
|
|
|
92
96
|
|
|
93
97
|
// Diffuse model as outlined by Burley: https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf
|
|
94
98
|
// Much help from Acerola's video on the topic: https://www.youtube.com/watch?v=KkOkx0FiHDA&t=570s
|
|
95
|
-
LightResult PrincipledDiffuse(DirectionalLight light, Material mtl, vec3 albedo, vec3 N, vec3 V, vec3 X, vec3 Y) {
|
|
99
|
+
LightResult PrincipledDiffuse(DirectionalLight light, Material mtl, vec3 albedo, float roughness, vec3 N, vec3 V, vec3 X, vec3 Y) {
|
|
96
100
|
|
|
97
101
|
LightResult result;
|
|
98
102
|
|
|
@@ -123,7 +127,7 @@ LightResult PrincipledDiffuse(DirectionalLight light, Material mtl, vec3 albedo,
|
|
|
123
127
|
// Diffuse
|
|
124
128
|
float FL = SchlickFresnel(cos_theta_l);
|
|
125
129
|
float FV = SchlickFresnel(cos_theta_V);
|
|
126
|
-
float Fss90 = cos_theta_D * cos_theta_D *
|
|
130
|
+
float Fss90 = cos_theta_D * cos_theta_D * roughness;
|
|
127
131
|
float Fd90 = 0.5 + 2.0 * Fss90;
|
|
128
132
|
|
|
129
133
|
float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
|
|
@@ -133,7 +137,7 @@ LightResult PrincipledDiffuse(DirectionalLight light, Material mtl, vec3 albedo,
|
|
|
133
137
|
float ss = 1.25 * (Fss * ((1 / (cos_theta_l + cos_theta_V)) - 0.5) + 0.5);
|
|
134
138
|
|
|
135
139
|
// Specular
|
|
136
|
-
float alpha =
|
|
140
|
+
float alpha = roughness * roughness;
|
|
137
141
|
float aspect = sqrt(1.0 - 0.9 * mtl.anisotropic);
|
|
138
142
|
float alpha_x = max(0.001, alpha / aspect);
|
|
139
143
|
float alpha_y = max(0.001, alpha * aspect);
|
|
@@ -143,7 +147,7 @@ LightResult PrincipledDiffuse(DirectionalLight light, Material mtl, vec3 albedo,
|
|
|
143
147
|
float Ds = AnisotropicGTR2(ndoth, hdotx, hdoty, alpha_x, alpha_y);
|
|
144
148
|
|
|
145
149
|
// Geometric Attenuation
|
|
146
|
-
float GalphaSquared = pow(0.5 +
|
|
150
|
+
float GalphaSquared = pow(0.5 + roughness * 0.5, 2);
|
|
147
151
|
float GalphaX = max(0.001, GalphaSquared / aspect);
|
|
148
152
|
float GalphaY = max(0.001, GalphaSquared * aspect);
|
|
149
153
|
float G = AnisotropicSmithGGX(cos_theta_l, ldotx, ldoty, GalphaX, GalphaY);
|
|
@@ -192,15 +196,39 @@ vec3 getNormal(Material mtl, mat3 TBN){
|
|
|
192
196
|
return normal;
|
|
193
197
|
}
|
|
194
198
|
|
|
199
|
+
float getAo(Material mtl, vec2 uv) {
|
|
200
|
+
float ao;
|
|
201
|
+
if (bool(mtl.hasAoMap)){
|
|
202
|
+
ao = texture(textureArrays[int(round(mtl.aoMap.x))].array, vec3(uv, round(mtl.aoMap.y))).a;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
ao = 1.0;
|
|
206
|
+
}
|
|
207
|
+
return ao;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
float getRoughness(Material mtl, vec2 uv) {
|
|
211
|
+
float roughness;
|
|
212
|
+
if (bool(mtl.hasRoughnessMap)){
|
|
213
|
+
roughness = texture(textureArrays[int(round(mtl.roughnessMap.x))].array, vec3(uv, round(mtl.roughnessMap.y))).a;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
roughness = mtl.roughness;
|
|
217
|
+
}
|
|
218
|
+
return roughness;
|
|
219
|
+
}
|
|
220
|
+
|
|
195
221
|
void main() {
|
|
196
222
|
float gamma = 2.2;
|
|
197
223
|
vec3 viewDir = vec3(normalize(cameraPosition - position));
|
|
198
224
|
|
|
199
225
|
// Get lighting vectors
|
|
200
|
-
vec3 albedo
|
|
201
|
-
vec3 normal
|
|
202
|
-
|
|
203
|
-
|
|
226
|
+
vec3 albedo = getAlbedo(mtl, uv, gamma);
|
|
227
|
+
vec3 normal = getNormal(mtl, TBN);
|
|
228
|
+
float ao = getAo(mtl, uv);
|
|
229
|
+
float roughness = getRoughness(mtl, uv);
|
|
230
|
+
vec3 tangent = TBN[0];
|
|
231
|
+
vec3 bitangent = TBN[1];
|
|
204
232
|
|
|
205
233
|
// Orthogonalize the tangent and bitangent according to the mapped normal vector
|
|
206
234
|
tangent = tangent - dot(normal, tangent) * normal;
|
|
@@ -224,17 +252,18 @@ void main() {
|
|
|
224
252
|
// Add result from each directional light in the scene
|
|
225
253
|
for (int i = 0; i < numDirLights; i++) {
|
|
226
254
|
// Caculate the light for the directional light
|
|
227
|
-
LightResult dirLightResult = PrincipledDiffuse(dirLights[i], mtl, albedo, N, V, X, Y);
|
|
255
|
+
LightResult dirLightResult = PrincipledDiffuse(dirLights[i], mtl, albedo, roughness, N, V, X, Y);
|
|
228
256
|
vec3 lightFactor = dirLights[i].intensity * dirLights[i].color;
|
|
229
257
|
// Add each lobe
|
|
230
|
-
lightResult.diffuse += dirLightResult.diffuse
|
|
231
|
-
lightResult.specular += dirLightResult.specular
|
|
258
|
+
lightResult.diffuse += dirLightResult.diffuse * lightFactor;
|
|
259
|
+
lightResult.specular += dirLightResult.specular * lightFactor;
|
|
232
260
|
lightResult.clearcoat += dirLightResult.clearcoat * lightFactor;
|
|
233
261
|
}
|
|
234
262
|
|
|
235
263
|
lightResult.specular = min(vec3(1.0), lightResult.specular);
|
|
236
264
|
lightResult.specular *= mix(vec3(1.0), reflect_sky, mtl.metallicness) * luminance(reflect_sky);
|
|
237
265
|
lightResult.diffuse *= mix(vec3(1.0), ambient_sky, 0.25);
|
|
266
|
+
lightResult.diffuse *= ao;
|
|
238
267
|
|
|
239
268
|
vec3 finalColor = albedo * 0.3 * mix(vec3(1.0), reflect_sky, mtl.metallicness);
|
|
240
269
|
finalColor += (lightResult.diffuse + lightResult.specular + lightResult.clearcoat);
|
basilisk/shaders/batch.vert
CHANGED
|
@@ -34,6 +34,10 @@ struct Material {
|
|
|
34
34
|
vec2 albedoMap;
|
|
35
35
|
int hasNormalMap;
|
|
36
36
|
vec2 normalMap;
|
|
37
|
+
int hasRoughnessMap;
|
|
38
|
+
vec2 roughnessMap;
|
|
39
|
+
int hasAoMap;
|
|
40
|
+
vec2 aoMap;
|
|
37
41
|
};
|
|
38
42
|
flat out Material mtl;
|
|
39
43
|
|
|
@@ -83,11 +87,10 @@ void main() {
|
|
|
83
87
|
uv = in_uv;
|
|
84
88
|
|
|
85
89
|
// Get the material
|
|
86
|
-
int mtl_size =
|
|
90
|
+
int mtl_size = 25;
|
|
87
91
|
int materialID = int(obj_material);
|
|
92
|
+
|
|
88
93
|
mtl.color = vec3(texelFetch(materialsTexture, ivec2(0, 0 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 1 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 2 + materialID * mtl_size), 0).r);
|
|
89
|
-
|
|
90
|
-
|
|
91
94
|
mtl.roughness = texelFetch(materialsTexture, ivec2(0, 3 + materialID * mtl_size), 0).r;
|
|
92
95
|
mtl.subsurface = texelFetch(materialsTexture, ivec2(0, 4 + materialID * mtl_size), 0).r;
|
|
93
96
|
mtl.sheen = texelFetch(materialsTexture, ivec2(0, 5 + materialID * mtl_size), 0).r;
|
|
@@ -99,10 +102,14 @@ void main() {
|
|
|
99
102
|
mtl.clearcoat = texelFetch(materialsTexture, ivec2(0, 11 + materialID * mtl_size), 0).r;
|
|
100
103
|
mtl.clearcoatGloss = texelFetch(materialsTexture, ivec2(0, 12 + materialID * mtl_size), 0).r;
|
|
101
104
|
|
|
102
|
-
mtl.hasAlbedoMap
|
|
103
|
-
mtl.albedoMap
|
|
104
|
-
mtl.hasNormalMap
|
|
105
|
-
mtl.normalMap
|
|
105
|
+
mtl.hasAlbedoMap = int(texelFetch(materialsTexture, ivec2(0, 13 + materialID * mtl_size), 0).r);
|
|
106
|
+
mtl.albedoMap = vec2(texelFetch(materialsTexture, ivec2(0, 14 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 15 + materialID * mtl_size), 0).r);
|
|
107
|
+
mtl.hasNormalMap = int(texelFetch(materialsTexture, ivec2(0, 16 + materialID * mtl_size), 0).r);
|
|
108
|
+
mtl.normalMap = vec2(texelFetch(materialsTexture, ivec2(0, 17 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 18 + materialID * mtl_size), 0).r);
|
|
109
|
+
mtl.hasRoughnessMap = int(texelFetch(materialsTexture, ivec2(0, 19 + materialID * mtl_size), 0).r);
|
|
110
|
+
mtl.roughnessMap = vec2(texelFetch(materialsTexture, ivec2(0, 20 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 21 + materialID * mtl_size), 0).r);
|
|
111
|
+
mtl.hasAoMap = int(texelFetch(materialsTexture, ivec2(0, 22 + materialID * mtl_size), 0).r);
|
|
112
|
+
mtl.aoMap = vec2(texelFetch(materialsTexture, ivec2(0, 23 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 24 + materialID * mtl_size), 0).r);
|
|
106
113
|
|
|
107
114
|
// Set the fragment position
|
|
108
115
|
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
|
basilisk/shaders/normal.frag
CHANGED
|
@@ -24,8 +24,11 @@ struct Material {
|
|
|
24
24
|
vec2 albedoMap;
|
|
25
25
|
int hasNormalMap;
|
|
26
26
|
vec2 normalMap;
|
|
27
|
+
int hasRoughnessMap;
|
|
28
|
+
vec2 roughnessMap;
|
|
29
|
+
int hasAoMap;
|
|
30
|
+
vec2 aoMap;
|
|
27
31
|
};
|
|
28
|
-
|
|
29
32
|
in vec2 uv;
|
|
30
33
|
in mat3 TBN;
|
|
31
34
|
|
|
@@ -33,7 +36,7 @@ in mat3 TBN;
|
|
|
33
36
|
flat in Material mtl;
|
|
34
37
|
|
|
35
38
|
// Uniforms
|
|
36
|
-
uniform
|
|
39
|
+
uniform textArray textureArrays[5];
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
vec3 getNormal(Material mtl, mat3 TBN){
|
|
@@ -52,9 +55,6 @@ void main() {
|
|
|
52
55
|
// Get lighting vectors
|
|
53
56
|
vec3 normal = getNormal(mtl, TBN);
|
|
54
57
|
|
|
55
|
-
// Lighting variables
|
|
56
|
-
vec3 N = normalize(normal);
|
|
57
|
-
|
|
58
58
|
// Output fragment color
|
|
59
59
|
fragColor = vec4(normal, 1.0);
|
|
60
60
|
}
|
basilisk/shaders/normal.vert
CHANGED
|
@@ -33,6 +33,10 @@ struct Material {
|
|
|
33
33
|
vec2 albedoMap;
|
|
34
34
|
int hasNormalMap;
|
|
35
35
|
vec2 normalMap;
|
|
36
|
+
int hasRoughnessMap;
|
|
37
|
+
vec2 roughnessMap;
|
|
38
|
+
int hasAoMap;
|
|
39
|
+
vec2 aoMap;
|
|
36
40
|
};
|
|
37
41
|
flat out Material mtl;
|
|
38
42
|
|
|
@@ -81,11 +85,12 @@ void main() {
|
|
|
81
85
|
uv = in_uv;
|
|
82
86
|
|
|
83
87
|
// Get the material
|
|
84
|
-
int mtl_size =
|
|
88
|
+
int mtl_size = 25;
|
|
89
|
+
mtl = Material(vec3(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, vec2(0), 0, vec2(0), 0, vec2(0), 0, vec2(0));
|
|
85
90
|
int materialID = int(obj_material);
|
|
86
91
|
|
|
87
|
-
mtl.hasNormalMap
|
|
88
|
-
mtl.normalMap
|
|
92
|
+
mtl.hasNormalMap = int(texelFetch(materialsTexture, ivec2(0, 16 + materialID * mtl_size), 0).r);
|
|
93
|
+
mtl.normalMap = vec2(texelFetch(materialsTexture, ivec2(0, 17 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 18 + materialID * mtl_size), 0).r);
|
|
89
94
|
|
|
90
95
|
// Set the fragment position
|
|
91
96
|
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#version 330 core
|
|
2
|
+
out vec4 fragColor;
|
|
3
|
+
|
|
4
|
+
in vec2 uv;
|
|
5
|
+
in vec3 position;
|
|
6
|
+
in mat3 TBN;
|
|
7
|
+
|
|
8
|
+
struct textArray {
|
|
9
|
+
sampler2DArray array;
|
|
10
|
+
};
|
|
11
|
+
uniform textArray textureArrays[5];
|
|
12
|
+
|
|
13
|
+
struct Material {
|
|
14
|
+
vec3 color;
|
|
15
|
+
float roughness;
|
|
16
|
+
float subsurface;
|
|
17
|
+
float sheen;
|
|
18
|
+
float sheenTint;
|
|
19
|
+
float anisotropic;
|
|
20
|
+
float specular;
|
|
21
|
+
float metallicness;
|
|
22
|
+
float specularTint;
|
|
23
|
+
float clearcoat;
|
|
24
|
+
float clearcoatGloss;
|
|
25
|
+
|
|
26
|
+
int hasAlbedoMap;
|
|
27
|
+
vec2 albedoMap;
|
|
28
|
+
int hasNormalMap;
|
|
29
|
+
vec2 normalMap;
|
|
30
|
+
int hasRoughnessMap;
|
|
31
|
+
vec2 roughnessMap;
|
|
32
|
+
int hasAoMap;
|
|
33
|
+
vec2 aoMap;
|
|
34
|
+
};
|
|
35
|
+
flat in Material mtl;
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
vec3 getColor(Material mtl, vec2 uv, float gamma) {
|
|
39
|
+
vec3 albedo = mtl.color;
|
|
40
|
+
if (bool(mtl.hasAlbedoMap)){
|
|
41
|
+
albedo *= pow(texture(textureArrays[int(round(mtl.albedoMap.x))].array, vec3(uv, round(mtl.albedoMap.y))).rgb, vec3(gamma));
|
|
42
|
+
}
|
|
43
|
+
return albedo;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
vec3 getNormal(Material mtl, mat3 TBN){
|
|
47
|
+
// Isolate the normal vector from the TBN basis
|
|
48
|
+
vec3 normal = TBN[2];
|
|
49
|
+
// Apply normal map if the material has one
|
|
50
|
+
if (bool(mtl.hasNormalMap)) {
|
|
51
|
+
normal = texture(textureArrays[int(round(mtl.normalMap.x))].array, vec3(uv, round(mtl.normalMap.y))).rgb * 2.0 - 1.0;
|
|
52
|
+
normal = normalize(TBN * normal);
|
|
53
|
+
}
|
|
54
|
+
// Return vector
|
|
55
|
+
return normal;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void main()
|
|
59
|
+
{
|
|
60
|
+
// Texture and normal data
|
|
61
|
+
float gamma = 2.2;
|
|
62
|
+
vec3 color = getColor(mtl, uv, gamma);
|
|
63
|
+
vec3 normal = getNormal(mtl, TBN);
|
|
64
|
+
|
|
65
|
+
// Simple light calculations
|
|
66
|
+
vec3 light = normalize(vec3(1.5, 2, 1));
|
|
67
|
+
float diff = abs(dot(normal, light));
|
|
68
|
+
|
|
69
|
+
// Get color and gamma correction
|
|
70
|
+
fragColor = vec4(color * (.2 + diff), 1.0);
|
|
71
|
+
fragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma));
|
|
72
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#version 330 core
|
|
2
|
+
|
|
3
|
+
layout (location = 0) in vec3 in_position;
|
|
4
|
+
layout (location = 1) in vec2 in_uv;
|
|
5
|
+
layout (location = 2) in vec3 in_normal;
|
|
6
|
+
layout (location = 3) in vec3 in_tangent;
|
|
7
|
+
layout (location = 4) in vec3 in_bitangent;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
in vec3 in_instance_pos;
|
|
11
|
+
in float in_instance_mtl;
|
|
12
|
+
in float scale;
|
|
13
|
+
in float life;
|
|
14
|
+
|
|
15
|
+
out vec2 uv;
|
|
16
|
+
out mat3 TBN;
|
|
17
|
+
|
|
18
|
+
uniform mat4 projectionMatrix;
|
|
19
|
+
uniform mat4 viewMatrix;
|
|
20
|
+
uniform sampler2D materialsTexture;
|
|
21
|
+
|
|
22
|
+
struct Material {
|
|
23
|
+
vec3 color;
|
|
24
|
+
float roughness;
|
|
25
|
+
float subsurface;
|
|
26
|
+
float sheen;
|
|
27
|
+
float sheenTint;
|
|
28
|
+
float anisotropic;
|
|
29
|
+
float specular;
|
|
30
|
+
float metallicness;
|
|
31
|
+
float specularTint;
|
|
32
|
+
float clearcoat;
|
|
33
|
+
float clearcoatGloss;
|
|
34
|
+
|
|
35
|
+
int hasAlbedoMap;
|
|
36
|
+
vec2 albedoMap;
|
|
37
|
+
int hasNormalMap;
|
|
38
|
+
vec2 normalMap;
|
|
39
|
+
int hasRoughnessMap;
|
|
40
|
+
vec2 roughnessMap;
|
|
41
|
+
int hasAoMap;
|
|
42
|
+
vec2 aoMap;
|
|
43
|
+
};
|
|
44
|
+
flat out Material mtl;
|
|
45
|
+
|
|
46
|
+
// Function to get the model matrix from node position, rotation, and scale
|
|
47
|
+
mat4 getModelMatrix(vec3 pos, float scale) {
|
|
48
|
+
mat4 translation = mat4(
|
|
49
|
+
scale, 0 , 0 , 0,
|
|
50
|
+
0 , scale, 0 , 0,
|
|
51
|
+
0 , 0 , scale, 0,
|
|
52
|
+
pos.x, pos.y, pos.z, 1
|
|
53
|
+
);
|
|
54
|
+
return translation;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Function to get the TBN matrix for normal mapping
|
|
58
|
+
mat3 getTBN(mat4 modelMatrix, vec3 normal, vec3 tangent, vec3 bitangent){
|
|
59
|
+
vec3 T = normalize(vec3(modelMatrix * vec4(tangent, 0.0)));
|
|
60
|
+
vec3 B = normalize(vec3(modelMatrix * vec4(bitangent, 0.0)));
|
|
61
|
+
vec3 N = normalize(vec3(modelMatrix * vec4(normal, 0.0)));
|
|
62
|
+
return mat3(T, B, N);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
void main() {
|
|
66
|
+
// Set the model matrix
|
|
67
|
+
mat4 modelMatrix = getModelMatrix(in_instance_pos, scale * life);
|
|
68
|
+
|
|
69
|
+
// Set out variables
|
|
70
|
+
TBN = getTBN(modelMatrix, in_normal, in_tangent, in_bitangent);
|
|
71
|
+
uv = in_uv;
|
|
72
|
+
|
|
73
|
+
// Material Data
|
|
74
|
+
int mtl_size = 25;
|
|
75
|
+
int materialID = int(in_instance_mtl);
|
|
76
|
+
mtl = Material(vec3(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, vec2(0), 0, vec2(0), 0, vec2(0), 0, vec2(0));
|
|
77
|
+
mtl.color = vec3(texelFetch(materialsTexture, ivec2(0, 0 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 1 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 2 + materialID * mtl_size), 0).r);
|
|
78
|
+
mtl.hasAlbedoMap = int(texelFetch(materialsTexture, ivec2(0, 13 + materialID * mtl_size), 0).r);
|
|
79
|
+
mtl.albedoMap = vec2(texelFetch(materialsTexture, ivec2(0, 14 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 15 + materialID * mtl_size), 0).r);
|
|
80
|
+
mtl.hasNormalMap = int(texelFetch(materialsTexture, ivec2(0, 16 + materialID * mtl_size), 0).r);
|
|
81
|
+
mtl.normalMap = vec2(texelFetch(materialsTexture, ivec2(0, 17 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 18 + materialID * mtl_size), 0).r);
|
|
82
|
+
|
|
83
|
+
// Send position to the frag
|
|
84
|
+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
|
|
85
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: basilisk-engine
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Python 3D Framework
|
|
5
5
|
Home-page: https://basilisk-website.vercel.app/
|
|
6
6
|
Author: Name
|
|
@@ -24,10 +24,10 @@ Basilisk Engine is a Python package for effortless 3D rendering and simulation.
|
|
|
24
24
|
Basilisk Engine uses a versatile and efficient physically based rendering pipeline, allowing for photorealistic and stylized rendering in real-time.
|
|
25
25
|
|
|
26
26
|
<p align="center">
|
|
27
|
-
<img src="mud.png" alt="mud" width="400"/>
|
|
28
|
-
<img src="foil.png" alt="foil" width="400"/>
|
|
29
|
-
<img src="cloth.png" alt="mud" width="400"/>
|
|
30
|
-
<img src="floor.png" alt="mud" width="400"/>
|
|
27
|
+
<img src="images/mud.png" alt="mud" width="400"/>
|
|
28
|
+
<img src="images/foil.png" alt="foil" width="400"/>
|
|
29
|
+
<img src="images/cloth.png" alt="mud" width="400"/>
|
|
30
|
+
<img src="images/floor.png" alt="mud" width="400"/>
|
|
31
31
|
</p>
|
|
32
32
|
|
|
33
33
|
## Physics
|