lavavu-osmesa 1.9.9__cp313-cp313-manylinux_2_28_x86_64.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.
Files changed (65) hide show
  1. lavavu/LavaVuPython.py +561 -0
  2. lavavu/_LavaVuPython.cpython-313-x86_64-linux-gnu.so +0 -0
  3. lavavu/__init__.py +15 -0
  4. lavavu/__main__.py +12 -0
  5. lavavu/amalgamate.py +15 -0
  6. lavavu/aserver.py +359 -0
  7. lavavu/control.py +1731 -0
  8. lavavu/convert.py +888 -0
  9. lavavu/dict.json +2528 -0
  10. lavavu/font.bin +0 -0
  11. lavavu/html/LavaVu-amalgamated.css +282 -0
  12. lavavu/html/OK-min.js +99 -0
  13. lavavu/html/baseviewer.js +307 -0
  14. lavavu/html/control.css +104 -0
  15. lavavu/html/control.js +340 -0
  16. lavavu/html/dat-gui-light-theme.css +68 -0
  17. lavavu/html/dat.gui.min.js +2 -0
  18. lavavu/html/draw.js +2259 -0
  19. lavavu/html/drawbox.js +1039 -0
  20. lavavu/html/emscripten-template.js +184 -0
  21. lavavu/html/emscripten.css +92 -0
  22. lavavu/html/favicon.ico +0 -0
  23. lavavu/html/gl-matrix-min.js +47 -0
  24. lavavu/html/gui.css +25 -0
  25. lavavu/html/menu.js +615 -0
  26. lavavu/html/server.js +226 -0
  27. lavavu/html/stats.min.js +5 -0
  28. lavavu/html/styles.css +58 -0
  29. lavavu/html/webview-template.html +43 -0
  30. lavavu/html/webview.html +43 -0
  31. lavavu/lavavu.py +6200 -0
  32. lavavu/osmesa/LavaVuPython.py +561 -0
  33. lavavu/osmesa/_LavaVuPython.cpython-313-x86_64-linux-gnu.so +0 -0
  34. lavavu/osmesa/__init__.py +0 -0
  35. lavavu/points.py +191 -0
  36. lavavu/server.py +343 -0
  37. lavavu/shaders/default.frag +14 -0
  38. lavavu/shaders/default.vert +17 -0
  39. lavavu/shaders/fontShader.frag +20 -0
  40. lavavu/shaders/fontShader.vert +18 -0
  41. lavavu/shaders/lineShader.frag +39 -0
  42. lavavu/shaders/lineShader.vert +26 -0
  43. lavavu/shaders/pointShader.frag +127 -0
  44. lavavu/shaders/pointShader.vert +53 -0
  45. lavavu/shaders/triShader.frag +153 -0
  46. lavavu/shaders/triShader.vert +49 -0
  47. lavavu/shaders/volumeShader.frag +400 -0
  48. lavavu/shaders/volumeShader.vert +5 -0
  49. lavavu/tracers.py +207 -0
  50. lavavu/vutils.py +211 -0
  51. lavavu_osmesa-1.9.9.dist-info/METADATA +323 -0
  52. lavavu_osmesa-1.9.9.dist-info/RECORD +65 -0
  53. lavavu_osmesa-1.9.9.dist-info/WHEEL +5 -0
  54. lavavu_osmesa-1.9.9.dist-info/entry_points.txt +2 -0
  55. lavavu_osmesa-1.9.9.dist-info/licenses/LICENSE.md +179 -0
  56. lavavu_osmesa-1.9.9.dist-info/top_level.txt +1 -0
  57. lavavu_osmesa.libs/libLLVM-17-51492e70.so +0 -0
  58. lavavu_osmesa.libs/libOSMesa-f6a8f160.so.8.0.0 +0 -0
  59. lavavu_osmesa.libs/libdrm-b0291a67.so.2.4.0 +0 -0
  60. lavavu_osmesa.libs/libffi-3a37023a.so.6.0.2 +0 -0
  61. lavavu_osmesa.libs/libglapi-520b284c.so.0.0.0 +0 -0
  62. lavavu_osmesa.libs/libpcre2-8-516f4c9d.so.0.7.1 +0 -0
  63. lavavu_osmesa.libs/libselinux-d0805dcb.so.1 +0 -0
  64. lavavu_osmesa.libs/libtinfo-3a2cb85b.so.6.1 +0 -0
  65. lavavu_osmesa.libs/libzstd-76b78bac.so.1.4.4 +0 -0
lavavu/points.py ADDED
@@ -0,0 +1,191 @@
1
+ """
2
+ Warning! EXPERIMENTAL:
3
+ these features and functions are under development, will have bugs,
4
+ and may be heavily modified in the future
5
+
6
+ Tools for importing and working with point clouds
7
+ - OBJ loader, requires pywavefront
8
+ - PLY loader, requires plyfile
9
+ - LAS loader, requires laspy
10
+
11
+ These functions ported from my viz script repo here:
12
+ https://github.com/mivp/vizscripts/tree/master/pointcloud
13
+ More tools can be found there, including a ptx reader which handles transformations of multiple point clouds into one coord space
14
+
15
+ """
16
+ import numpy
17
+ import os
18
+ import convert
19
+
20
+ def loadpointcloud(filename, subsample=1, dtype=numpy.float32, components=['x', 'y', 'z', 'red', 'green', 'blue', 'alpha']):
21
+ """
22
+ Attempt to load the passed point cloud file based
23
+ Pick loader based on extension
24
+
25
+ Parameters
26
+ ----------
27
+ filename, str
28
+ Full path to file to load
29
+ subsample, int
30
+ Subsample factor, sample every Nth point
31
+ dtype, numpy.dtype
32
+ Type of data
33
+ components, list
34
+ List of components per point
35
+
36
+ Returns
37
+ -------
38
+ vertices : array
39
+ numpy array x,y,z
40
+ colours : array
41
+ numpy array r,g,b or r,g,b,a
42
+ """
43
+ fn, ext = os.path.splitext(filename)
44
+ ext = ext.lower()
45
+ if ext == '.xyz':
46
+ #Loop over lines in input file
47
+ count = 0
48
+ V = []
49
+ C = []
50
+ with open(filename, 'r') as file:
51
+ for line in file:
52
+ #Subsample?
53
+ count += 1
54
+ if subsample > 1 and count % subsample != 1: continue
55
+
56
+ if count % 10000 == 0:
57
+ print(count)
58
+ sys.stdout.flush()
59
+
60
+ #Read particle position
61
+ data = re.split(r'[,;\s]+', line.rstrip())
62
+ if len(data) < 3: continue
63
+ x = float(data[0])
64
+ y = float(data[1])
65
+ z = float(data[2])
66
+
67
+ V.append((x, y, z))
68
+
69
+ #R,G,B[,A] colour if provided
70
+ if len(data) >= 7:
71
+ C.append((int(data[3]), int(data[4]), int(data[5]), int(data[6])))
72
+ elif len(data) == 6:
73
+ C.append((int(data[3]), int(data[4]), int(data[5]), 255))
74
+
75
+ V = numpy.array(V)
76
+ C = numpy.array(C)
77
+
78
+ elif ext == '.xyzb':
79
+ inbytes = os.path.getsize(filename)
80
+ #All floats
81
+ #num = inbytes / (4 * 6) # x y z r g b
82
+ #All floats, rgba
83
+ #num = inbytes / (4 * 7) # x y z r g b a
84
+ #All doubles, rgba
85
+ #num = inbytes / (8 * 7) # x y z r g b a
86
+ #Float vert, byte colour
87
+ #num = inbytes / (4 * 3 + 4) # x y z r g b a
88
+ sz = numpy.dtype(dtype).itemsize
89
+ num = inbytes // (sz * len(components))
90
+
91
+ with open(filename, 'rb') as infile:
92
+ print("Importing " + str(num//subsample) + " points")
93
+ arr = numpy.fromfile(infile, dtype='float64')
94
+ infile.close()
95
+
96
+ arr = arr.astype(dtype).reshape(len(arr)//len(components), len(components))
97
+ if subsample > 1:
98
+ arr = arr[::subsample]
99
+
100
+ #Convert float rgba to uint32 colour
101
+ colours = None
102
+ if len(components) > 6:
103
+ colours = arr[:,3:len(components)]
104
+ colours *= 255
105
+ colours = colours.astype('uint8').ravel()
106
+ colours = colours.view(dtype='uint32')
107
+
108
+ return (arr[:,0:3], colours)
109
+
110
+ elif ext == '.obj':
111
+ print("Loading OBJ")
112
+ import pywavefront
113
+ scene = pywavefront.Wavefront(filename)
114
+ V = numpy.array(scene.vertices)
115
+
116
+ #SubSample
117
+ if subsample > 1:
118
+ V = V[::subsample]
119
+ print("Subsampled:",V.shape)
120
+
121
+ verts = V[:,0:3]
122
+ colours = V[:,3:] * 255
123
+
124
+ #Load positions and RGB
125
+ print("Creating visualisation ")
126
+ return (verts, colours)
127
+
128
+ elif ext == '.ply':
129
+ print("Loading PLY")
130
+ from plyfile import PlyData, PlyElement
131
+ plydata = PlyData.read(filename)
132
+ if plydata:
133
+ x = plydata['vertex']['x']
134
+ y = plydata['vertex']['y']
135
+ z = plydata['vertex']['z']
136
+ V = numpy.vstack((x,y,z)).reshape([3, -1]).transpose()
137
+
138
+ C = convert._get_PLY_colours(plydata.elements[0])
139
+
140
+ #SubSample
141
+ if subsample > 1:
142
+ V = V[::subsample]
143
+ if C is not None:
144
+ C = C[::subsample]
145
+
146
+ return (V, C)
147
+
148
+ elif ext == '.las' or ext == '.laz':
149
+ print("Loading LAS")
150
+ import laspy
151
+ infile = laspy.file.File(filename, mode="r")
152
+ '''
153
+ print(infile)
154
+ print(infile.point_format)
155
+ for spec in infile.point_format:
156
+ print(spec.name)
157
+ print(infile.header)
158
+ print(infile.header.dataformat_id)
159
+
160
+ print(infile.header.offset)
161
+ print(infile.header.scale)
162
+ '''
163
+
164
+ #Grab all of the points from the file.
165
+ #point_records = infile.points
166
+ #print(point_records)
167
+ #print(point_records.shape)
168
+
169
+ #Convert colours from short to uchar
170
+ if infile.red.dtype == numpy.uint16:
171
+ R = (infile.red / 255).astype(numpy.uint8)
172
+ G = (infile.green / 255).astype(numpy.uint8)
173
+ B = (infile.blue / 255).astype(numpy.uint8)
174
+ else:
175
+ R = infile.red
176
+ G = infile.green
177
+ B = infile.blue
178
+
179
+ ss = subsample
180
+ if ss > 1:
181
+ V = numpy.array([infile.x[::ss], infile.y[::ss], infile.z[::ss]])
182
+ C = numpy.array([R[::ss],G[::ss],B[::ss]])
183
+ return (V, C)
184
+ else:
185
+ V = numpy.array([infile.x, infile.y, infile.z])
186
+ C = numpy.array([R,G,B])
187
+ return (V, C)
188
+
189
+ else:
190
+ print("Unknown point cloud format, extension: ", ext)
191
+
lavavu/server.py ADDED
@@ -0,0 +1,343 @@
1
+ import urllib
2
+ import os
3
+ import threading
4
+ import time
5
+ import errno
6
+ from functools import partial
7
+ import weakref
8
+ import base64
9
+ import json
10
+ import socket
11
+
12
+ from socketserver import ThreadingMixIn
13
+ from http.server import SimpleHTTPRequestHandler, HTTPServer
14
+ from urllib.parse import unquote
15
+ from urllib.parse import urlparse
16
+ from urllib.parse import parse_qs
17
+
18
+ """
19
+ HTTP Server interface
20
+ """
21
+ class LVRequestHandler(SimpleHTTPRequestHandler, object):
22
+
23
+ def __init__(self, viewer_weakref, *args, **kwargs):
24
+ #Used with partial() to provide the viewer object
25
+ try:
26
+ self._lv = viewer_weakref
27
+ super(LVRequestHandler, self).__init__(*args, **kwargs)
28
+ except (IOError) as e:
29
+ pass #Just ignore IO errors on server
30
+ if e.errno == errno.EPIPE:
31
+ # EPIPE error, ignore
32
+ pass
33
+ elif e.errno == errno.EPROTOTYPE:
34
+ # MacOS "Protocol wrong type for socket" error, ignore
35
+ pass
36
+ else:
37
+ raise e
38
+
39
+ def serveResponse(self, data, datatype):
40
+ try:
41
+ #Serve provided data, with error check for SIGPIPE (broken connection)
42
+ self.send_response(200)
43
+ self.send_header('Content-type', datatype)
44
+ self.send_header('Access-Control-Allow-Origin', '*')
45
+ self.send_header('x-colab-notebook-cache-control', 'no-cache') #Colab: disable offline access cache
46
+ self.end_headers()
47
+ if data:
48
+ self.wfile.write(data)
49
+ #This specific error sometimes occurs on windows, ConnectionError is the base class and covers a few more
50
+ #except (IOError,ConnectionAbortedError) as e:
51
+ # if isinstance(e,ConnectionAbortedError):
52
+ except (IOError,ConnectionError) as e:
53
+ if isinstance(e,ConnectionError):
54
+ pass
55
+ elif e.errno == errno.EPIPE:
56
+ # EPIPE error, ignore
57
+ pass
58
+ else:
59
+ raise e
60
+
61
+ def do_HEAD(self):
62
+ self.serveResponse(None, 'text/html')
63
+
64
+ def do_POST(self):
65
+ #Always interpret post data as commands
66
+ #(can perform other actions too based on self.path later if we want)
67
+ data_string = self.rfile.read(int(self.headers['Content-Length']))
68
+ self.serveResponse(b'', 'text/plain')
69
+ #cmds = str(data_string, 'utf-8') #python3 only
70
+ try: #Python3
71
+ from urllib.parse import unquote
72
+ data_string = unquote(data_string)
73
+ except: #Python2
74
+ from urllib import unquote
75
+ data_string = unquote(data_string).decode('utf8')
76
+ cmds = str(data_string.decode('utf-8'))
77
+ #Run viewer commands
78
+ self._execute(cmds)
79
+
80
+ def do_GET(self):
81
+ lv = self._get_viewer()
82
+ parsed = urlparse(self.path)
83
+ query = parse_qs(parsed.query)
84
+
85
+ def img_response():
86
+ resp = None
87
+ if 'width' in query and 'height' in query:
88
+ resp = lv.jpeg(resolution=(int(query['width'][0]), int(query['height'][0])))
89
+ elif 'width' in query:
90
+ resp = lv.jpeg(resolution=(int(query['width'][0]), 0))
91
+ else:
92
+ resp = lv.jpeg()
93
+
94
+ #Ensure the response is valid before serving
95
+ if resp is not None:
96
+ self.serveResponse(resp, 'image/jpeg')
97
+
98
+ if self.path.find('image') > 0:
99
+ img_response()
100
+
101
+ elif self.path.find('command=') > 0:
102
+ pos1 = self.path.find('=')
103
+ pos2 = self.path.find('?')
104
+ if pos2 < 0: pos2 = len(self.path)
105
+ cmds = unquote(self.path[pos1+1:pos2])
106
+
107
+ #Run viewer commands
108
+ self._execute(cmds)
109
+
110
+ #Serve image or just respond 200
111
+ if self.path.find('icommand=') > 0:
112
+ img_response()
113
+ else:
114
+ self.serveResponse(b'', 'text/plain')
115
+
116
+ elif self.path.find('getstate') > 0:
117
+ state = lv.app.getState()
118
+ self.serveResponse(bytearray(state, 'utf-8'), 'text/plain; charset=utf-8')
119
+ #self.serveResponse(bytearray(state, 'utf-8'), 'text/plain')
120
+ elif self.path.find('connect') > 0:
121
+ if 'url' in query:
122
+ #Save first valid connection URL on the viewer
123
+ url = query['url'][0]
124
+ if len(lv._url) == 0:
125
+ lv._url = url
126
+ uid = id(lv)
127
+ self.serveResponse(bytearray(str(uid), 'utf-8'), 'text/plain; charset=utf-8')
128
+ elif self.path.find('key=') > 0:
129
+ pos2 = self.path.find('&')
130
+ cmds = unquote(self.path[1:pos2])
131
+ lv.commands('key ' + cmds, True)
132
+ self.serveResponse(b'', 'text/plain')
133
+ elif self.path.find('mouse=') > 0:
134
+ pos2 = self.path.find('&')
135
+ cmds = unquote(self.path[1:pos2])
136
+ lv.commands('mouse ' + cmds, True)
137
+ self.serveResponse(b'', 'text/plain')
138
+ elif len(self.path) <= 1:
139
+ #Root requested, returns interactive view
140
+ w = lv.control.Window(align=None, wrapper=None)
141
+ code = lv.control.show(True, filename="")
142
+ self.serveResponse(bytearray(code, 'utf-8'), 'text/html; charset=utf-8')
143
+ else:
144
+ return SimpleHTTPRequestHandler.do_GET(self)
145
+
146
+ #Serve files from lavavu html dir
147
+ def translate_path(self, path):
148
+ lv = self._get_viewer()
149
+ if not os.path.exists(path):
150
+ #print(' - not found in cwd')
151
+ if path[0] == '/': path = path[1:]
152
+ path = os.path.join(lv.htmlpath, path)
153
+ if os.path.exists(path) and os.path.isfile(path):
154
+ #print(' - found in htmlpath')
155
+ return path
156
+ else:
157
+ #print(' - not found in htmlpath')
158
+ return SimpleHTTPRequestHandler.translate_path(self, self.path)
159
+ else:
160
+ return SimpleHTTPRequestHandler.translate_path(self, path)
161
+
162
+ #Stifle log output
163
+ def log_message(self, format, *args):
164
+ return
165
+
166
+ def _get_viewer(self):
167
+ #Get from weak reference, if deleted raise exception
168
+ lv = self._lv()
169
+ if not lv:
170
+ self._closing = True
171
+ raise(Exception("Viewer not found"))
172
+ return lv
173
+
174
+ def _execute(self, cmds):
175
+ lv = self._get_viewer()
176
+
177
+ if len(cmds) and cmds[0] == '_':
178
+ #base64 encoded commands or JSON state
179
+ cmds = str(base64.b64decode(cmds).decode('utf-8'))
180
+ #cmds = str(base64.b64decode(cmds), 'utf-8')
181
+
182
+ #Object to select can be provided in preceding angle brackets
183
+ selobj = None
184
+ if cmds[0] == '<':
185
+ pos = cmds.find('>')
186
+ selobj = lv.objects[cmds[1:pos]]
187
+ cmds = cmds[pos+1:]
188
+
189
+ #Execute commands via python API by preceding with '.'
190
+ done = False
191
+ if cmds[0] == '.':
192
+ attr = cmds.split()[0][1:]
193
+ pos = cmds.find(' ')
194
+ params = cmds[pos+1:]
195
+ if selobj:
196
+ #Call on Object
197
+ func = getattr(selobj, attr)
198
+ if func and callable(func):
199
+ func(params)
200
+ done = True
201
+ else:
202
+ #Call on Viewer
203
+ func = getattr(lv, attr)
204
+ if func and callable(func):
205
+ func(params)
206
+ done = True
207
+ elif cmds[0] == '$':
208
+ #Requests prefixed by '$' are sent
209
+ #from property collection controls
210
+ #format is $ID KEY VALUE
211
+ # - ID is the python id() of the properties object
212
+ # All properties collections are stored on their parent
213
+ # object using this id in the _collections dict
214
+ # - KEY is the property name key to set
215
+ # - VALUE is a json string containing the value to set
216
+ S = cmds.split()
217
+ target = S[0][1:]
218
+ if target in lv._collections:
219
+ #Get from _collections by id (weakref)
220
+ props = lv._collections[target]()
221
+ props[S[1]] = json.loads(S[2])
222
+ #Check for callback - if provided, call with updated props
223
+ func = getattr(props, 'callback')
224
+ if func and callable(func):
225
+ func(props)
226
+
227
+ #Default, call via lv.commands() scripting API
228
+ if not done:
229
+ if selobj:
230
+ selobj.select()
231
+ lv.commands(cmds)
232
+
233
+ #Optional thread per request version:
234
+ class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
235
+ pass
236
+
237
+ """
238
+ HTTP Server manager class
239
+ """
240
+ class Server(threading.Thread):
241
+ def __init__(self, viewer, port=None, ipv6=False, retries=100):
242
+ self.host = 0
243
+ if port is None:
244
+ port = 8080
245
+ self._closing = False
246
+ #Allow viewer to be garbage collected
247
+ self.viewer = weakref.ref(viewer)
248
+ self.port = port
249
+ self.retries = retries
250
+ self.maxretries = retries
251
+ self.ipv6 = ipv6
252
+ super(Server, self).__init__()
253
+ self.daemon = True #Place in background so will be closed on program exit
254
+ self._cv = threading.Condition()
255
+
256
+ def handle(self):
257
+ try:
258
+ httpd.handle_request()
259
+ except (socket.exception) as e:
260
+ #print(str(e))
261
+ pass
262
+
263
+ def run(self):
264
+ httpd = None
265
+ HTTPServer.allow_reuse_address = False
266
+ try:
267
+ # We "partially apply" our first argument to get the viewer object into LVRequestHandler
268
+ handler = partial(LVRequestHandler, self.viewer)
269
+ if self.ipv6:
270
+ HTTPServer.address_family = socket.AF_INET6
271
+ hosts = ['::', 'localhost', '::1']
272
+ host = hosts[self.host]
273
+ #httpd = HTTPServer((host, self.port), handler)
274
+ httpd = ThreadingHTTPServer((host, self.port), handler)
275
+ else:
276
+ HTTPServer.address_family = socket.AF_INET
277
+ hosts = ['0.0.0.0', 'localhost', '127.0.0.1']
278
+ host = hosts[self.host]
279
+ #httpd = HTTPServer((host, self.port), handler)
280
+ httpd = ThreadingHTTPServer(('0.0.0.0', self.port), handler)
281
+
282
+ #print("Server running on host %s port %s" % (host, self.port))
283
+
284
+ #Sync with starting thread here to ensure server thread has initialised before it continues
285
+ with self._cv:
286
+ self._cv.notifyAll()
287
+
288
+ # Handle requests
289
+ #print("Using port: ", self.port)
290
+ # A timeout is needed for server to check periodically if closing
291
+ httpd.timeout = 0.05 #50 millisecond timeout
292
+ while self.viewer() is not None and not self._closing:
293
+ httpd.handle_request()
294
+
295
+ except (Exception) as e:
296
+ self.retries -= 1
297
+ if self.retries < 1:
298
+ print("Failed to start server, max retries reached")
299
+
300
+ #Try another port
301
+ if e.errno == errno.EADDRINUSE: #98
302
+ self.port += 1
303
+ #Try again
304
+ self.run()
305
+ elif e.errno == errno.EAFNOSUPPORT: #97 : Address family not supported by protocol
306
+ #Try next host name/address
307
+ self.host += 1
308
+ if self.host > 2:
309
+ #Try again without ipv6?
310
+ if self.ipv6:
311
+ self.ipv6 = False
312
+ else:
313
+ self.ipv6 = True
314
+ self.host = 0
315
+ #Try again
316
+ self.run()
317
+ else:
318
+ print("Server start failed: ",e, e.errno, self.port)
319
+
320
+ def serve(viewer, port=None, ipv6=False, retries=100):
321
+ s = Server(viewer, port, ipv6, retries)
322
+ #Start the thread and wait for it to finish initialising
323
+ with s._cv:
324
+ s.start()
325
+ s._cv.wait()
326
+ return s
327
+
328
+ #Ignore SIGPIPE altogether (does not apply on windows)
329
+ import sys
330
+ if sys.platform != 'win32':
331
+ from signal import signal, SIGPIPE, SIG_IGN
332
+ signal(SIGPIPE, SIG_IGN)
333
+
334
+ """
335
+ Main entry point - run server and open browser interface
336
+ """
337
+ if __name__ == '__main__':
338
+ import lavavu
339
+ lv = lavavu.Viewer()
340
+ #lv.animate(1) #Required to show viewer window and handle mouse/keyboard events there too
341
+ lv.browser()
342
+ lv._thread.join() #Wait for server to quit
343
+
@@ -0,0 +1,14 @@
1
+ in vec4 vColour;
2
+
3
+ flat in vec4 vFlatColour;
4
+ uniform bool uFlat;
5
+ out vec4 outColour;
6
+
7
+ void main(void)
8
+ {
9
+ if (uFlat)
10
+ outColour = vFlatColour;
11
+ else
12
+ outColour = vColour;
13
+ }
14
+
@@ -0,0 +1,17 @@
1
+ in vec4 aVertexPosition;
2
+ in vec4 aVertexColour;
3
+ in vec2 aVertexTexCoord;
4
+ uniform mat4 uMVMatrix;
5
+ uniform mat4 uPMatrix;
6
+ out vec4 vColour;
7
+ out vec2 vTexCoord;
8
+ flat out vec4 vFlatColour;
9
+
10
+ void main(void)
11
+ {
12
+ gl_Position = uPMatrix * uMVMatrix * aVertexPosition;
13
+ vColour = aVertexColour;
14
+ vTexCoord = aVertexTexCoord;
15
+ vFlatColour = aVertexColour;
16
+ }
17
+
@@ -0,0 +1,20 @@
1
+ in vec4 vColour;
2
+ in vec2 vTexCoord;
3
+
4
+ uniform bool uTextured;
5
+ uniform sampler2D uTexture;
6
+
7
+ out vec4 outColour;
8
+
9
+ void main(void)
10
+ {
11
+ vec4 fColour = vColour;
12
+ if (uTextured)
13
+ {
14
+ vec4 tColour = texture(uTexture, vTexCoord);
15
+ //Just use the alpha component (red in single component texture)
16
+ fColour.a = tColour.r;
17
+ }
18
+ outColour = fColour;
19
+ }
20
+
@@ -0,0 +1,18 @@
1
+ in vec4 aVertexPosition;
2
+ in vec2 aVertexTexCoord;
3
+
4
+ uniform mat4 uMVMatrix;
5
+ uniform mat4 uPMatrix;
6
+
7
+ uniform vec4 uColour;
8
+
9
+ out vec4 vColour;
10
+ out vec2 vTexCoord;
11
+
12
+ void main(void)
13
+ {
14
+ gl_Position = uPMatrix * uMVMatrix * aVertexPosition;
15
+ vColour = uColour;
16
+ vTexCoord = aVertexTexCoord;
17
+ }
18
+
@@ -0,0 +1,39 @@
1
+ in vec4 vColour;
2
+ in vec3 vVertex;
3
+
4
+ uniform float uOpacity;
5
+ uniform float uBrightness;
6
+ uniform float uContrast;
7
+ uniform float uSaturation;
8
+ uniform vec3 uClipMin;
9
+ uniform vec3 uClipMax;
10
+ uniform bool uOpaque;
11
+
12
+ out vec4 outColour;
13
+
14
+ void main(void)
15
+ {
16
+ //Clip planes in X/Y/Z
17
+ if (any(lessThan(vVertex, uClipMin)) || any(greaterThan(vVertex, uClipMax))) discard;
18
+
19
+ vec4 colour = vColour;
20
+ float alpha = colour.a;
21
+ if (uOpacity > 0.0) alpha *= uOpacity;
22
+
23
+ //Brightness adjust
24
+ colour += uBrightness;
25
+ //Saturation & Contrast adjust
26
+ const vec4 LumCoeff = vec4(0.2125, 0.7154, 0.0721, 0.0);
27
+ vec4 AvgLumin = vec4(0.5, 0.5, 0.5, 0.0);
28
+ vec4 intensity = vec4(dot(colour, LumCoeff));
29
+ colour = mix(intensity, colour, uSaturation);
30
+ colour = mix(AvgLumin, colour, uContrast);
31
+ colour.a = alpha;
32
+
33
+ if (alpha < 0.01) discard;
34
+
35
+ if (uOpaque)
36
+ colour.a = 1.0;
37
+
38
+ outColour = colour;
39
+ }
@@ -0,0 +1,26 @@
1
+ in vec3 aVertexPosition;
2
+ in vec4 aVertexColour;
3
+ uniform mat4 uMVMatrix;
4
+ uniform mat4 uPMatrix;
5
+
6
+ uniform int uPointDist; // Scale by distance
7
+
8
+ uniform vec4 uColour;
9
+ uniform float uOpacity;
10
+
11
+ out vec4 vColour;
12
+ out vec3 vVertex;
13
+
14
+ void main(void)
15
+ {
16
+ vec4 mvPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
17
+ gl_Position = uPMatrix * mvPosition;
18
+
19
+ if (uColour.a > 0.0)
20
+ vColour = uColour;
21
+ else
22
+ vColour = vec4(aVertexColour.rgb, aVertexColour.a*uOpacity);
23
+
24
+ vVertex = aVertexPosition.xyz;
25
+ }
26
+