aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2025-11-08 21:15:40 +0000
committers-ol <s+removethis@s-ol.nu>2025-11-08 21:15:40 +0000
commitf32f5b6fa1dc1f0fffce96a38984e1bdf747073f (patch)
tree3f87ee28665b394f393ae12e1c88bf86ef45e330
parentlib/glsl-view: fix documentation (diff)
downloadalive-f32f5b6fa1dc1f0fffce96a38984e1bdf747073f.tar.gz
alive-f32f5b6fa1dc1f0fffce96a38984e1bdf747073f.zip
lib/glsl-view: add buffered-stream-source
-rw-r--r--alv-lib/glsl-view.moon62
-rw-r--r--examples/glsl-view/buffered-stream.alv37
-rw-r--r--examples/glsl-view/video.alv29
3 files changed, 128 insertions, 0 deletions
diff --git a/alv-lib/glsl-view.moon b/alv-lib/glsl-view.moon
index 51f854c..0cb0a93 100644
--- a/alv-lib/glsl-view.moon
+++ b/alv-lib/glsl-view.moon
@@ -57,6 +57,22 @@ When absent, `glsl-type` is inferred based on the type of `value`:
type or= get_typestr @inputs[2]\type!
@out\set :type, :val
+offset= Constant.meta
+ meta:
+ name: 'offset'
+ summary: "get the playback offset of a buffered-stream-source."
+ examples: { '(offset [glsl-type] source)' }
+ description: "GLSL type: float/double/int/uint"
+
+ value: class extends PureOp
+ pattern: -sig.str + sig!
+ type: => Uniform
+ tick: =>
+ { type, source } = @unwrap_all!
+ type or= "float"
+ name = source.val
+ @out\set :type, val: "/source/#{name}/offset"
+
video_source = Constant.meta
meta:
name: 'video-source'
@@ -146,6 +162,49 @@ stream_source = Constant.meta
add_item msg, @inputs.args\type!, args if args
\send Message.pack msg.content
+buffered_stream_source = Constant.meta
+ meta:
+ name: 'buffered-stream-source'
+ summary: "load a stream as a 3d texture source."
+ examples: { '(stream-source [socket] type depth uri [format] [args])' }
+ description: "Creates a circular buffer 3d texture from a capture source.
+
+- `type` must be `3D` or `2D_ARRAY`.
+- `depth` is the number of frames to keep in the buffer.
+- `uri` is the ffmpeg URI to load. If it starts with `./` it will be resolved relative to the current alv module.
+- `format` optionally specifies the ffmpeg/avformat input format to use.
+- `args` is a struct of optional arguments for the ffmpeg/avformat input format.
+
+ (stream-source 'webcam' '3D' 64 '/dev/video0')"
+
+ value: class extends Op
+ pattern = -sig['osc/out'] + const.str + const.num + const.str + -const.str + -const!
+ setup: (inputs, scope) =>
+ { socket, type, depth, filename, format, args } = pattern\match inputs
+
+ @prefix = COPILOT.active_module.file\match'(.*/)[^/]*$'
+
+ super
+ socket: Input.hot socket or scope\get '*oscout*'
+ type: Input.cold type
+ depth: Input.cold depth
+ filename: Input.cold filename
+ format: format and Input.cold format
+ args: args and Input.cold args
+
+ samplertype = assert GLSL_SAMPLER_TYPES[@inputs.type!]
+ @setup_out '=', Uniform, type: samplertype, val: "alv-#{fmttag @tag}"
+
+ tick: =>
+ { :socket, :name, :type, :depth, :filename, :format, :args } = @unwrap_all!
+
+ with @inputs.socket!
+ filename = tryprefix @prefix, filename
+ msg = Message.new{ address: "/source/alv-#{fmttag @tag}/buffered-stream", types: "sis", "TEXTURE_#{type}", depth, filename }
+ msg\add 's', format if format
+ add_item msg, @inputs.args\type!, args if args
+ \send Message.pack msg.content
+
tsv_source = Constant.meta
meta:
name: 'tsv-source'
@@ -333,8 +392,11 @@ Constant.meta
'video-source': video_source
'stream-source': stream_source
+ 'buffered-stream-source': buffered_stream_source
'tsv-source': tsv_source
+ :offset
+
:freeze, 'step!': step_
shader: shader_
diff --git a/examples/glsl-view/buffered-stream.alv b/examples/glsl-view/buffered-stream.alv
new file mode 100644
index 0000000..94cb81b
--- /dev/null
+++ b/examples/glsl-view/buffered-stream.alv
@@ -0,0 +1,37 @@
+([1]import* glsl-view math link-time)
+([2]import osc random)
+
+([4]def *oscout* ([3]osc/connect 'localhost' 9000)
+ *clock* ([8]clock true 110 60))
+
+([7]def cam ([99]buffered-stream-source '3D' 64 '/home/s-ol/misc/WeChat_20241111172619.mp4'))
+
+([10]draw $[5]shader"
+in vec2 uv;
+out vec4 outcol;
+
+void main() {
+ vec3 nuv = vec3(uv, $([6]offset cam));
+ nuv.xy -= 0.5;
+
+ nuv.y /= 16.0 / 9.0;
+
+ vec2 bu = nuv.xy;
+
+ nuv.z -= abs(length(nuv.xy) / 2);
+
+ nuv.y *= 16.0 / 9.0;
+ nuv.xy += 0.5;
+
+ nuv.xy *= 480;
+ nuv.xy = floor(nuv.xy);
+ nuv.xy /= 480;
+
+ vec3 color = texture($cam, nuv).rgb;
+ // color.r = step(uv.x, nuv.z);
+ // color.g *= 0.5 + 0.5 * step(uv.x, $([11]ramp 3));
+ // color.b *= 0.5 + 0.5 * step(uv.x, $([13]ramp 2));
+ // color.r *= 0.5 + 0.5 * step(1 - uv.x, $([14]ramp 2));
+
+ outcol = vec4(color, 1);
+}")
diff --git a/examples/glsl-view/video.alv b/examples/glsl-view/video.alv
new file mode 100644
index 0000000..8b0fe70
--- /dev/null
+++ b/examples/glsl-view/video.alv
@@ -0,0 +1,29 @@
+([1]import* glsl-view math link-time)
+([2]import osc random)
+
+([4]def *oscout* ([3]osc/connect 'localhost' 9000)
+ *clock* ([8]clock true 110))
+
+([7]def v3d ([6]video-source '3D' '/home/s-ol/drone.mkv')
+ v2d ([9]stream-source '2D' '/home/s-ol/drone.mkv'))
+
+([10]draw $[5]shader"
+in vec2 uv;
+out vec4 outcol;
+
+uniform float tmpval;
+
+void main() {
+ vec3 nuv = vec3(uv, $([11]ramp 60));
+ nuv.xy *= 2;
+ nuv.z += dot(floor(nuv.xy), vec2(2, 1)) / 32;
+ vec3 v3d = texture($v3d, nuv).rgb;
+
+ vec3 v2d = texture($v2d, uv).rgb;
+
+ vec3 color = mix(v3d, v2d, $([12]lfo 8));
+
+ color *= $([16]fade 4 1);
+
+ outcol = vec4(color, 1);
+}")