basilisk-engine 0.0.8__py3-none-any.whl → 0.1.0__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/__init__.py +3 -1
- basilisk/collisions/broad/broad_bvh.py +31 -2
- basilisk/collisions/collider.py +6 -5
- basilisk/collisions/collider_handler.py +87 -24
- basilisk/collisions/narrow/contact_manifold.py +92 -0
- basilisk/collisions/narrow/epa.py +13 -8
- basilisk/collisions/narrow/graham_scan.py +25 -0
- basilisk/collisions/narrow/helper.py +7 -1
- basilisk/collisions/narrow/line_intersections.py +107 -0
- basilisk/collisions/narrow/sutherland_hodgman.py +24 -0
- basilisk/draw/draw_handler.py +3 -3
- basilisk/engine.py +16 -3
- basilisk/generic/collisions.py +1 -2
- basilisk/generic/quat.py +10 -2
- basilisk/generic/vec3.py +9 -1
- basilisk/input/mouse.py +3 -3
- basilisk/nodes/node.py +48 -77
- basilisk/nodes/node_handler.py +8 -4
- basilisk/physics/impulse.py +119 -0
- basilisk/physics/physics_engine.py +1 -1
- basilisk/render/batch.py +2 -0
- basilisk/render/camera.py +30 -1
- basilisk/render/chunk_handler.py +10 -1
- basilisk/render/frame.py +2 -2
- basilisk/render/image_handler.py +14 -12
- basilisk/render/light_handler.py +2 -2
- basilisk/render/material.py +13 -13
- basilisk/render/material_handler.py +11 -7
- basilisk/render/shader.py +110 -0
- basilisk/render/shader_handler.py +18 -34
- basilisk/render/sky.py +4 -3
- basilisk/scene.py +3 -2
- basilisk/shaders/geometry.frag +9 -0
- basilisk/shaders/geometry.vert +42 -0
- basilisk/shaders/normal.frag +60 -0
- basilisk/shaders/normal.vert +92 -0
- {basilisk_engine-0.0.8.dist-info → basilisk_engine-0.1.0.dist-info}/METADATA +1 -1
- {basilisk_engine-0.0.8.dist-info → basilisk_engine-0.1.0.dist-info}/RECORD +40 -30
- {basilisk_engine-0.0.8.dist-info → basilisk_engine-0.1.0.dist-info}/WHEEL +0 -0
- {basilisk_engine-0.0.8.dist-info → basilisk_engine-0.1.0.dist-info}/top_level.txt +0 -0
basilisk/render/material.py
CHANGED
|
@@ -133,64 +133,64 @@ class Material():
|
|
|
133
133
|
@color.setter
|
|
134
134
|
def color(self, value: tuple | list | glm.vec3 | np.ndarray):
|
|
135
135
|
self._color = validate_glm_vec3("Material", "color", value)
|
|
136
|
-
if self.material_handler: self.material_handler.write()
|
|
136
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
137
137
|
|
|
138
138
|
@texture.setter
|
|
139
139
|
def texture(self, value: Image | None):
|
|
140
140
|
self._texture = validate_image("Material", "texture", value)
|
|
141
|
-
if self.material_handler: self.material_handler.write()
|
|
141
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
142
142
|
|
|
143
143
|
@normal.setter
|
|
144
144
|
def normal(self, value: Image | None):
|
|
145
145
|
self._normal = validate_image("Material", "normal map", value)
|
|
146
|
-
if self.material_handler: self.material_handler.write()
|
|
146
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
147
147
|
|
|
148
148
|
@roughness.setter
|
|
149
149
|
def roughness(self, value: float | int | glm.float32):
|
|
150
150
|
self._roughness = validate_float("Material", "roughness", value)
|
|
151
|
-
if self.material_handler: self.material_handler.write()
|
|
151
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
152
152
|
|
|
153
153
|
@subsurface.setter
|
|
154
154
|
def subsurface(self, value: float | int | glm.float32):
|
|
155
155
|
self._subsurface = validate_float("Material", "subsurface", value)
|
|
156
|
-
if self.material_handler: self.material_handler.write()
|
|
156
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
157
157
|
|
|
158
158
|
@sheen.setter
|
|
159
159
|
def sheen(self, value: float | int | glm.float32):
|
|
160
160
|
self._sheen = validate_float("Material", "sheen", value)
|
|
161
|
-
if self.material_handler: self.material_handler.write()
|
|
161
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
162
162
|
|
|
163
163
|
@sheen_tint.setter
|
|
164
164
|
def sheen_tint(self, value: float | int | glm.float32):
|
|
165
165
|
self._sheen_tint = validate_float("Material", "sheen tint", value)
|
|
166
|
-
if self.material_handler: self.material_handler.write()
|
|
166
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
167
167
|
|
|
168
168
|
@anisotropic.setter
|
|
169
169
|
def anisotropic(self, value: float | int | glm.float32):
|
|
170
170
|
self._anisotropic = validate_float("Material", "anisotropic", value)
|
|
171
|
-
if self.material_handler: self.material_handler.write()
|
|
171
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
172
172
|
|
|
173
173
|
@specular.setter
|
|
174
174
|
def specular(self, value: float | int | glm.float32):
|
|
175
175
|
self._specular = validate_float("Material", "specular", value)
|
|
176
|
-
if self.material_handler: self.material_handler.write()
|
|
176
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
177
177
|
|
|
178
178
|
@metallicness.setter
|
|
179
179
|
def metallicness(self, value: float | int | glm.float32):
|
|
180
180
|
self._metallicness = validate_float("Material", "metallicness", value)
|
|
181
|
-
if self.material_handler: self.material_handler.write()
|
|
181
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
182
182
|
|
|
183
183
|
@specular_tint.setter
|
|
184
184
|
def specular_tint(self, value: float | int | glm.float32):
|
|
185
185
|
self._specular_tint = validate_float("Material", "specular tint", value)
|
|
186
|
-
if self.material_handler: self.material_handler.write()
|
|
186
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
187
187
|
|
|
188
188
|
@clearcoat.setter
|
|
189
189
|
def clearcoat(self, value: float | int | glm.float32):
|
|
190
190
|
self._clearcoat = validate_float("Material", "clearcoat", value)
|
|
191
|
-
if self.material_handler: self.material_handler.write()
|
|
191
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
192
192
|
|
|
193
193
|
@clearcoat_gloss.setter
|
|
194
194
|
def clearcoat_gloss(self, value: float | int | glm.float32):
|
|
195
195
|
self._clearcoat_gloss = validate_float("Material", "clearcoat gloss", value)
|
|
196
|
-
if self.material_handler: self.material_handler.write()
|
|
196
|
+
if self.material_handler: self.material_handler.write(regenerate=True)
|
|
@@ -50,7 +50,7 @@ class MaterialHandler():
|
|
|
50
50
|
# Add the material
|
|
51
51
|
self.materials.append(material)
|
|
52
52
|
# Write materials
|
|
53
|
-
self.write()
|
|
53
|
+
self.write(regenerate=True)
|
|
54
54
|
|
|
55
55
|
def generate_material_texture(self) -> None:
|
|
56
56
|
"""
|
|
@@ -75,17 +75,20 @@ class MaterialHandler():
|
|
|
75
75
|
material_data = np.ravel(material_data)
|
|
76
76
|
self.data_texture = self.ctx.texture((1, len(material_data)), components=1, dtype='f4', data=material_data)
|
|
77
77
|
|
|
78
|
-
def write(self,
|
|
78
|
+
def write(self, regenerate=False) -> None:
|
|
79
79
|
"""
|
|
80
|
-
Writes all material data to
|
|
80
|
+
Writes all material data to relavent shaders
|
|
81
81
|
"""
|
|
82
82
|
|
|
83
|
-
if
|
|
83
|
+
if regenerate: self.generate_material_texture()
|
|
84
84
|
|
|
85
|
-
self.
|
|
85
|
+
if not self.data_texture: return
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
for shader in self.engine.scene.shader_handler.shaders.values():
|
|
88
|
+
if 'materialsTexture' not in shader.uniforms: continue
|
|
89
|
+
|
|
90
|
+
shader.program['materialsTexture'] = 9
|
|
91
|
+
self.data_texture.use(location=9)
|
|
89
92
|
|
|
90
93
|
def get(self, identifier: str | int) -> any:
|
|
91
94
|
"""
|
|
@@ -113,6 +116,7 @@ class MaterialHandler():
|
|
|
113
116
|
|
|
114
117
|
self.base = Material('Base')
|
|
115
118
|
self.materials.append(self.base)
|
|
119
|
+
self.generate_material_texture()
|
|
116
120
|
self.write()
|
|
117
121
|
|
|
118
122
|
def __del__(self) -> None:
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import moderngl as mgl
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
attribute_mappings = {
|
|
5
|
+
'in_position' : [0, 1, 2],
|
|
6
|
+
'in_uv' : [3, 4],
|
|
7
|
+
'in_normal' : [5, 6, 7],
|
|
8
|
+
'in_tangent' : [8, 9, 10],
|
|
9
|
+
'in_bitangent' : [11, 12, 13],
|
|
10
|
+
'obj_position' : [14, 15, 16],
|
|
11
|
+
'obj_rotation' : [17, 18, 19, 20],
|
|
12
|
+
'obj_scale' : [21, 22, 23],
|
|
13
|
+
'obj_material' : [24],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Shader:
|
|
18
|
+
program: mgl.Program=None
|
|
19
|
+
"""Shader program for the vertex and fragment shader"""
|
|
20
|
+
vertex_shader: str
|
|
21
|
+
"""String representation of the vertex shader"""
|
|
22
|
+
fragment_shader: str
|
|
23
|
+
"""String representation of the vertex shader"""
|
|
24
|
+
uniforms: list[str]=[]
|
|
25
|
+
"""List containg the names of all uniforms in the shader"""
|
|
26
|
+
attribute_indices: list[int]
|
|
27
|
+
"""List of indices that map all possible shader attributes to the ones used byu the shader"""
|
|
28
|
+
fmt: str
|
|
29
|
+
"""String representation of the format for building vaos"""
|
|
30
|
+
attributes: list[str]
|
|
31
|
+
"""List representation of the attributes for building vaos"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, engine, vert: str=None, frag: str=None) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Basilisk shader object. Contains shader program and shader attrbibute/uniform information
|
|
36
|
+
Args:
|
|
37
|
+
vert: str=None
|
|
38
|
+
Path to the vertex shader. Defaults to internal if none is given
|
|
39
|
+
frag: str=None
|
|
40
|
+
Path to the fragment shader. Defaults to internal if none is given
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
self.engine = engine
|
|
44
|
+
self.ctx = engine.ctx
|
|
45
|
+
|
|
46
|
+
# Default class attributes values
|
|
47
|
+
self.uniforms = []
|
|
48
|
+
self.attribute_indices = []
|
|
49
|
+
self.fmt = ''
|
|
50
|
+
self.attributes = []
|
|
51
|
+
|
|
52
|
+
# Default vertex and fragment shaders
|
|
53
|
+
if vert == None: vert = self.engine.root + '/shaders/batch.vert'
|
|
54
|
+
if frag == None: frag = self.engine.root + '/shaders/batch.frag'
|
|
55
|
+
|
|
56
|
+
# Read the shaders
|
|
57
|
+
with open(vert) as file:
|
|
58
|
+
self.vertex_shader = file.read()
|
|
59
|
+
with open(frag) as file:
|
|
60
|
+
self.fragment_shader = file.read()
|
|
61
|
+
|
|
62
|
+
# Hash value for references
|
|
63
|
+
self.hash = hash((self.vertex_shader, self.fragment_shader))
|
|
64
|
+
|
|
65
|
+
# Create a string of all lines in both shaders
|
|
66
|
+
lines = f'{self.vertex_shader}\n{self.fragment_shader}'.split('\n')
|
|
67
|
+
|
|
68
|
+
# Parse through shader to find uniforms and attributes
|
|
69
|
+
for line in lines:
|
|
70
|
+
tokens = line.strip().split(' ')
|
|
71
|
+
|
|
72
|
+
# Add uniforms
|
|
73
|
+
if tokens[0] == 'uniform' and len(tokens) > 2:
|
|
74
|
+
self.uniforms.append(tokens[-1][:-1])
|
|
75
|
+
|
|
76
|
+
# Add attributes
|
|
77
|
+
if tokens[0] == 'layout' and len(tokens) > 2 and 'in' in line:
|
|
78
|
+
self.attributes.append(tokens[-1][:-1])
|
|
79
|
+
|
|
80
|
+
if tokens[-1][:-1] not in attribute_mappings: continue
|
|
81
|
+
indices = attribute_mappings[tokens[-1][:-1]]
|
|
82
|
+
self.attribute_indices.extend(indices)
|
|
83
|
+
self.fmt += f'{len(indices)}f '
|
|
84
|
+
|
|
85
|
+
# Create a program with shaders
|
|
86
|
+
self.program = self.ctx.program(vertex_shader=self.vertex_shader, fragment_shader=self.fragment_shader)
|
|
87
|
+
|
|
88
|
+
def use(self):
|
|
89
|
+
"""
|
|
90
|
+
Selects a shader for use
|
|
91
|
+
"""
|
|
92
|
+
|
|
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()
|
|
97
|
+
self.engine.scene.node_handler.chunk_handler.update_all()
|
|
98
|
+
|
|
99
|
+
def write(self, name: str, value) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Writes a uniform to the shader program
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
self.program[name].write(value)
|
|
105
|
+
|
|
106
|
+
def __del__(self) -> int:
|
|
107
|
+
if self.program: self.program.release()
|
|
108
|
+
|
|
109
|
+
def __hash__(self) -> int:
|
|
110
|
+
return self.hash
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import moderngl as mgl
|
|
2
2
|
import glm
|
|
3
|
-
|
|
4
|
-
# Predefined uniforms that do not change each frame
|
|
5
|
-
single_frame_uniforms = ['m_proj']
|
|
3
|
+
from .shader import Shader
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
class ShaderHandler:
|
|
@@ -12,10 +10,8 @@ class ShaderHandler:
|
|
|
12
10
|
"""Back reference to the parent scene"""
|
|
13
11
|
ctx: mgl.Context
|
|
14
12
|
"""Back reference to the parent context"""
|
|
15
|
-
|
|
13
|
+
shaders: list = []
|
|
16
14
|
"""Dictionary containing all the shaders"""
|
|
17
|
-
shader_uniforms: dict = {}
|
|
18
|
-
"""Dictionary all the uniforms present in a shader"""
|
|
19
15
|
uniform_values: dict = {}
|
|
20
16
|
"""Dictionary containing uniform values"""
|
|
21
17
|
|
|
@@ -30,38 +26,26 @@ class ShaderHandler:
|
|
|
30
26
|
self.ctx = scene.engine.ctx
|
|
31
27
|
|
|
32
28
|
# Initalize dictionaries
|
|
33
|
-
self.
|
|
34
|
-
self.shader_uniforms = {}
|
|
29
|
+
self.shaders = {}
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
self.
|
|
38
|
-
self.
|
|
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' ))
|
|
39
35
|
|
|
40
|
-
def
|
|
36
|
+
def add(self, name: str, shader: Shader) -> None:
|
|
41
37
|
"""
|
|
42
38
|
Creates a shader program from a file name.
|
|
43
39
|
Parses through shaders to identify uniforms and save for writting
|
|
44
40
|
"""
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
with open(vert_path) as file:
|
|
48
|
-
vertex_shader = file.read()
|
|
49
|
-
with open(frag_path) as file:
|
|
50
|
-
fragment_shader = file.read()
|
|
51
|
-
|
|
52
|
-
# Create blank list for uniforms
|
|
53
|
-
self.shader_uniforms[name] = []
|
|
54
|
-
# Create a list of all lines in both shaders
|
|
55
|
-
lines = f'{vertex_shader}\n{fragment_shader}'.split('\n')
|
|
56
|
-
# Parse through shader to find uniform variables
|
|
57
|
-
for line in lines:
|
|
58
|
-
tokens = line.strip().split(' ')
|
|
59
|
-
if tokens[0] == 'uniform' and len(tokens) > 2:
|
|
60
|
-
self.shader_uniforms[name].append(tokens[2][:-1])
|
|
42
|
+
if shader in self.shaders.values(): return
|
|
61
43
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
self.
|
|
44
|
+
self.shaders[name] = shader
|
|
45
|
+
|
|
46
|
+
if self.scene.material_handler:
|
|
47
|
+
self.scene.material_handler.write()
|
|
48
|
+
self.scene.material_handler.image_handler.write()
|
|
65
49
|
|
|
66
50
|
def get_uniforms_values(self) -> None:
|
|
67
51
|
"""
|
|
@@ -83,13 +67,13 @@ class ShaderHandler:
|
|
|
83
67
|
|
|
84
68
|
self.get_uniforms_values()
|
|
85
69
|
for uniform in self.uniform_values:
|
|
86
|
-
for
|
|
87
|
-
if not uniform in
|
|
88
|
-
|
|
70
|
+
for shader in self.shaders.values():
|
|
71
|
+
if not uniform in shader.uniforms: continue # Does not write uniforms not in the shader
|
|
72
|
+
shader.write(uniform, self.uniform_values[uniform])
|
|
89
73
|
|
|
90
74
|
def release(self) -> None:
|
|
91
75
|
"""
|
|
92
76
|
Releases all shader programs in handler
|
|
93
77
|
"""
|
|
94
78
|
|
|
95
|
-
[
|
|
79
|
+
[shader.__del__() for shader in self.shaders.values()]
|
basilisk/render/sky.py
CHANGED
|
@@ -29,8 +29,9 @@ class Sky:
|
|
|
29
29
|
self.program['skyboxTexture'] = 8
|
|
30
30
|
self.texture_cube.use(location = 8)
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
shader = self.scene.engine.shader
|
|
33
|
+
if 'skyboxTexture' not in shader.uniforms: return
|
|
34
|
+
shader.program['skyboxTexture'] = 8
|
|
34
35
|
self.texture_cube.use(location = 8)
|
|
35
36
|
|
|
36
37
|
|
|
@@ -105,7 +106,7 @@ class Sky:
|
|
|
105
106
|
|
|
106
107
|
# Create a renderable vao
|
|
107
108
|
self.vbo = self.ctx.buffer(vertex_data)
|
|
108
|
-
self.program = self.scene.shader_handler.
|
|
109
|
+
self.program = self.scene.shader_handler.shaders['sky'].program
|
|
109
110
|
self.vao = self.ctx.vertex_array(self.program, [(self.vbo, '3f', 'in_position')], skip_errors=True)
|
|
110
111
|
|
|
111
112
|
def __del__(self):
|
basilisk/scene.py
CHANGED
|
@@ -42,8 +42,9 @@ class Scene():
|
|
|
42
42
|
Updates the physics and in the scene
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
-
self.camera.update()
|
|
46
45
|
self.node_handler.update()
|
|
46
|
+
self.camera.update()
|
|
47
|
+
self.collider_handler.resolve_collisions()
|
|
47
48
|
|
|
48
49
|
def render(self) -> None:
|
|
49
50
|
"""
|
|
@@ -78,7 +79,7 @@ class Scene():
|
|
|
78
79
|
collision_group : float=None,
|
|
79
80
|
name: str='',
|
|
80
81
|
tags: list[str]=None,
|
|
81
|
-
static: bool=
|
|
82
|
+
static: bool=None):
|
|
82
83
|
|
|
83
84
|
if material: self.material_handler.add(material)
|
|
84
85
|
else: material = self.material_handler.base
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#version 330 core
|
|
2
|
+
|
|
3
|
+
layout (location = 0) in vec3 in_position;
|
|
4
|
+
|
|
5
|
+
layout (location = 5) in vec3 obj_position;
|
|
6
|
+
layout (location = 6) in vec4 obj_rotation;
|
|
7
|
+
layout (location = 7) in vec3 obj_scale;
|
|
8
|
+
|
|
9
|
+
// Uniforms
|
|
10
|
+
uniform mat4 projectionMatrix;
|
|
11
|
+
uniform mat4 viewMatrix;
|
|
12
|
+
|
|
13
|
+
// Function to get the model matrix from node position, rotation, and scale
|
|
14
|
+
mat4 getModelMatrix(vec3 pos, vec4 rot, vec3 scl) {
|
|
15
|
+
mat4 translation = mat4(
|
|
16
|
+
1 , 0 , 0 , 0,
|
|
17
|
+
0 , 1 , 0 , 0,
|
|
18
|
+
0 , 0 , 1 , 0,
|
|
19
|
+
pos.x, pos.y, pos.z, 1
|
|
20
|
+
);
|
|
21
|
+
mat4 rotation = mat4(
|
|
22
|
+
1 - 2 * (rot.z * rot.z + rot.w * rot.w), 2 * (rot.y * rot.z - rot.w * rot.x), 2 * (rot.y * rot.w + rot.z * rot.x), 0,
|
|
23
|
+
2 * (rot.y * rot.z + rot.w * rot.x), 1 - 2 * (rot.y * rot.y + rot.w * rot.w), 2 * (rot.z * rot.w - rot.y * rot.x), 0,
|
|
24
|
+
2 * (rot.y * rot.w - rot.z * rot.x), 2 * (rot.z * rot.w + rot.y * rot.x), 1 - 2 * (rot.y * rot.y + rot.z * rot.z), 0,
|
|
25
|
+
0, 0, 0, 1
|
|
26
|
+
);
|
|
27
|
+
mat4 scale = mat4(
|
|
28
|
+
scl.x, 0 , 0 , 0,
|
|
29
|
+
0 , scl.y, 0 , 0,
|
|
30
|
+
0 , 0 , scl.z, 0,
|
|
31
|
+
0 , 0 , 0 , 1
|
|
32
|
+
);
|
|
33
|
+
return translation * rotation * scale;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
void main() {
|
|
38
|
+
// Set the model matrix
|
|
39
|
+
mat4 modelMatrix = getModelMatrix(obj_position, obj_rotation, obj_scale);
|
|
40
|
+
// Set the fragment position
|
|
41
|
+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
|
|
42
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#version 330 core
|
|
2
|
+
|
|
3
|
+
layout (location = 0) out vec4 fragColor;
|
|
4
|
+
|
|
5
|
+
// Structs needed for the shader
|
|
6
|
+
struct textArray {
|
|
7
|
+
sampler2DArray array;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
struct Material {
|
|
11
|
+
vec3 color;
|
|
12
|
+
float roughness;
|
|
13
|
+
float subsurface;
|
|
14
|
+
float sheen;
|
|
15
|
+
float sheenTint;
|
|
16
|
+
float anisotropic;
|
|
17
|
+
float specular;
|
|
18
|
+
float metallicness;
|
|
19
|
+
float specularTint;
|
|
20
|
+
float clearcoat;
|
|
21
|
+
float clearcoatGloss;
|
|
22
|
+
|
|
23
|
+
int hasAlbedoMap;
|
|
24
|
+
vec2 albedoMap;
|
|
25
|
+
int hasNormalMap;
|
|
26
|
+
vec2 normalMap;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
in vec2 uv;
|
|
30
|
+
in mat3 TBN;
|
|
31
|
+
|
|
32
|
+
// Material attributes
|
|
33
|
+
flat in Material mtl;
|
|
34
|
+
|
|
35
|
+
// Uniforms
|
|
36
|
+
uniform textArray textureArrays[5];
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
vec3 getNormal(Material mtl, mat3 TBN){
|
|
40
|
+
// Isolate the normal vector from the TBN basis
|
|
41
|
+
vec3 normal = TBN[2];
|
|
42
|
+
// Apply normal map if the material has one
|
|
43
|
+
if (bool(mtl.hasNormalMap)) {
|
|
44
|
+
normal = texture(textureArrays[int(round(mtl.normalMap.x))].array, vec3(uv, round(mtl.normalMap.y))).rgb * 2.0 - 1.0;
|
|
45
|
+
normal = normalize(TBN * normal);
|
|
46
|
+
}
|
|
47
|
+
// Return vector
|
|
48
|
+
return normal;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void main() {
|
|
52
|
+
// Get lighting vectors
|
|
53
|
+
vec3 normal = getNormal(mtl, TBN);
|
|
54
|
+
|
|
55
|
+
// Lighting variables
|
|
56
|
+
vec3 N = normalize(normal);
|
|
57
|
+
|
|
58
|
+
// Output fragment color
|
|
59
|
+
fragColor = vec4(normal, 1.0);
|
|
60
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
layout (location = 5) in vec3 obj_position;
|
|
10
|
+
layout (location = 6) in vec4 obj_rotation;
|
|
11
|
+
layout (location = 7) in vec3 obj_scale;
|
|
12
|
+
layout (location = 8) in float obj_material;
|
|
13
|
+
|
|
14
|
+
// Variables passed on to the fragment shader
|
|
15
|
+
out vec2 uv;
|
|
16
|
+
out mat3 TBN;
|
|
17
|
+
|
|
18
|
+
// Material struct sent to fragment shader
|
|
19
|
+
struct Material {
|
|
20
|
+
vec3 color;
|
|
21
|
+
float roughness;
|
|
22
|
+
float subsurface;
|
|
23
|
+
float sheen;
|
|
24
|
+
float sheenTint;
|
|
25
|
+
float anisotropic;
|
|
26
|
+
float specular;
|
|
27
|
+
float metallicness;
|
|
28
|
+
float specularTint;
|
|
29
|
+
float clearcoat;
|
|
30
|
+
float clearcoatGloss;
|
|
31
|
+
|
|
32
|
+
int hasAlbedoMap;
|
|
33
|
+
vec2 albedoMap;
|
|
34
|
+
int hasNormalMap;
|
|
35
|
+
vec2 normalMap;
|
|
36
|
+
};
|
|
37
|
+
flat out Material mtl;
|
|
38
|
+
|
|
39
|
+
// Uniforms
|
|
40
|
+
uniform mat4 projectionMatrix;
|
|
41
|
+
uniform mat4 viewMatrix;
|
|
42
|
+
uniform sampler2D materialsTexture;
|
|
43
|
+
|
|
44
|
+
// Function to get the model matrix from node position, rotation, and scale
|
|
45
|
+
mat4 getModelMatrix(vec3 pos, vec4 rot, vec3 scl) {
|
|
46
|
+
mat4 translation = mat4(
|
|
47
|
+
1 , 0 , 0 , 0,
|
|
48
|
+
0 , 1 , 0 , 0,
|
|
49
|
+
0 , 0 , 1 , 0,
|
|
50
|
+
pos.x, pos.y, pos.z, 1
|
|
51
|
+
);
|
|
52
|
+
mat4 rotation = mat4(
|
|
53
|
+
1 - 2 * (rot.z * rot.z + rot.w * rot.w), 2 * (rot.y * rot.z - rot.w * rot.x), 2 * (rot.y * rot.w + rot.z * rot.x), 0,
|
|
54
|
+
2 * (rot.y * rot.z + rot.w * rot.x), 1 - 2 * (rot.y * rot.y + rot.w * rot.w), 2 * (rot.z * rot.w - rot.y * rot.x), 0,
|
|
55
|
+
2 * (rot.y * rot.w - rot.z * rot.x), 2 * (rot.z * rot.w + rot.y * rot.x), 1 - 2 * (rot.y * rot.y + rot.z * rot.z), 0,
|
|
56
|
+
0, 0, 0, 1
|
|
57
|
+
);
|
|
58
|
+
mat4 scale = mat4(
|
|
59
|
+
scl.x, 0 , 0 , 0,
|
|
60
|
+
0 , scl.y, 0 , 0,
|
|
61
|
+
0 , 0 , scl.z, 0,
|
|
62
|
+
0 , 0 , 0 , 1
|
|
63
|
+
);
|
|
64
|
+
return translation * rotation * scale;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Function to get the TBN matrix for normal mapping
|
|
68
|
+
mat3 getTBN(mat4 modelMatrix, vec3 normal, vec3 tangent, vec3 bitangent){
|
|
69
|
+
vec3 T = normalize(vec3(modelMatrix * vec4(tangent, 0.0)));
|
|
70
|
+
vec3 B = normalize(vec3(modelMatrix * vec4(bitangent, 0.0)));
|
|
71
|
+
vec3 N = normalize(vec3(modelMatrix * vec4(normal, 0.0)));
|
|
72
|
+
return mat3(T, B, N);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void main() {
|
|
76
|
+
// Set the model matrix
|
|
77
|
+
mat4 modelMatrix = getModelMatrix(obj_position, obj_rotation, obj_scale);
|
|
78
|
+
|
|
79
|
+
// Set out variables
|
|
80
|
+
TBN = getTBN(modelMatrix, in_normal, in_tangent, in_bitangent);
|
|
81
|
+
uv = in_uv;
|
|
82
|
+
|
|
83
|
+
// Get the material
|
|
84
|
+
int mtl_size = 19;
|
|
85
|
+
int materialID = int(obj_material);
|
|
86
|
+
|
|
87
|
+
mtl.hasNormalMap = int(texelFetch(materialsTexture, ivec2(0, 16 + materialID * mtl_size), 0).r);
|
|
88
|
+
mtl.normalMap = vec2(texelFetch(materialsTexture, ivec2(0, 17 + materialID * mtl_size), 0).r, texelFetch(materialsTexture, ivec2(0, 18 + materialID * mtl_size), 0).r);
|
|
89
|
+
|
|
90
|
+
// Set the fragment position
|
|
91
|
+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
|
|
92
|
+
}
|