diff options
| author | s-ol <s+removethis@s-ol.nu> | 2025-08-04 23:00:18 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-08-04 23:00:18 +0000 |
| commit | 12153d43224fa2a58cedad4497a5c4020b233cf1 (patch) | |
| tree | 6edc0c85bd770ecfc9ceecac9fddd0c3b076f021 | |
| parent | docs: small fixes in guide and reference (diff) | |
| download | alive-12153d43224fa2a58cedad4497a5c4020b233cf1.tar.gz alive-12153d43224fa2a58cedad4497a5c4020b233cf1.zip | |
lib/glsl-view: align source names, add stream source
| -rw-r--r-- | alv-lib/glsl-view.moon | 110 | ||||
| -rw-r--r-- | examples/glsl-view/simple.alv | 12 | ||||
| -rw-r--r-- | examples/glsl-view/stream.alv | 20 | ||||
| -rw-r--r-- | examples/love-glsl-view-tsv.alv | 26 |
4 files changed, 148 insertions, 20 deletions
diff --git a/alv-lib/glsl-view.moon b/alv-lib/glsl-view.moon index e0b8678..8b3ec3f 100644 --- a/alv-lib/glsl-view.moon +++ b/alv-lib/glsl-view.moon @@ -2,6 +2,10 @@ import Constant, PureOp, Op, template_subst, Input, T, Array, Struct, sig, const import Message, Bundle, Timetag, add_item from require 'alv-lib._osc' import dns, udp from require 'socket' +tryprefix = (prefix, filename) -> + return filename unless prefix and filename\match '^%./' + prefix .. filename + GLSL_TYPES = num: 'float' bool: 'bool' @@ -29,9 +33,9 @@ uniform = Constant.meta name: 'uniform' summary: "override uniform binding type." examples: { '(uniform glsl-type value)' } - description: "Generates a struct as received by [shader][]: + description: "Generates a uniform struct as received by [glsl-view/shader][]: -`(uniform 'sampler2D' 'image.png')` is equivalent to `{'type' 'sampler2d' 'val' 'image.png'}`." +`(uniform 'sampler2D' 'sampler-name')` is equivalent to `{'type' 'sampler2D' 'val' 'sampler-name'}`." value: class extends Op pattern = sig.str + sig! @@ -47,46 +51,108 @@ uniform = Constant.meta tick: => @out\set @unwrap_all! -video = Constant.meta +video_source = Constant.meta meta: name: 'video' summary: "load a video texture source." - examples: { '(video [socket] name filename [type])' } + examples: { '(video-source [socket] name type filename [format] [args])' } + description: "Creates a texture source from a video or image file. + +- `name` is a unique name for this texture source. +- `type` can be one of: + - `2D`: `sampler2D` (loads first frame only) + - `3D` or `2D_ARRAY`: `sampler3D`/`sampler2DArray` (loads whole video) +- `filename` is the video file 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." value: class extends Op - pattern = -sig['osc/out'] + const.str + const.str + -const.str + pattern = -sig['osc/out'] + const.str + const.str + const.str + -const.str + -const! setup: (inputs, scope) => - { socket, name, filename, type } = pattern\match inputs + { socket, name, type, filename, format, args } = pattern\match inputs @prefix = COPILOT.active_module.file\match'(.*/)[^/]*$' super socket: Input.hot socket or scope\get '*oscout*' name: Input.cold name + type: Input.cold type filename: Input.cold filename - type: Input.cold type or Constant.str "2D" + format: format and Input.cold format + args: args and Input.cold args samplertype = assert GLSL_SAMPLER_TYPES[@inputs.type!] @setup_out '=', (Struct type: T.str, val: T.str), type: samplertype, val: @inputs.name! tick: => - { :socket, :name, :type, :filename } = @unwrap_all! + { :socket, :name, :type, :filename, :format, :args } = @unwrap_all! with @inputs.socket! - if @prefix and not (filename\match '^/') or (filename\match '^%w:\\') - filename = @prefix .. filename - \send Message.pack { address: "/texture/#{name}/video", types: "ss", "TEXTURE_#{type}", filename } + filename = tryprefix @prefix, filename + msg = Message.new{ address: "/texture/#{name}/video", types: "ss", "TEXTURE_#{type}", filename } + msg\add 's', format if format + add_item msg, @inputs.args\type!, args if args + \send Message.pack msg.content -- destroy: => -- name = @inputs.name! -- with @inputs.socket! -- \send Message.pack { address: "/texture/#{name}/destroy", types: "" } -tsv_input = Constant.meta +stream_source = Constant.meta + meta: + name: 'stream' + summary: "load a stream texture source." + examples: { '(stream-source [socket] name type uri [format] [args])' } + description: "Creates a realtime stream from a capture source. + +- `name` is a unique name for this texture source. +- `type` must be `2D`. +- `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' '2D' '/dev/video0') + (stream-source 'testpt' '2D' 'testsrc=size=1280x720:rate=30' 'lavfi')" + + value: class extends Op + pattern = -sig['osc/out'] + const.str + const.str + const.str + -const.str + -const! + setup: (inputs, scope) => + { socket, name, type, filename, format, args } = pattern\match inputs + + @prefix = COPILOT.active_module.file\match'(.*/)[^/]*$' + + super + socket: Input.hot socket or scope\get '*oscout*' + name: Input.cold name + type: Input.cold type + 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 '=', (Struct type: T.str, val: T.str), type: samplertype, val: @inputs.name! + + tick: => + { :socket, :name, :type, :filename, :format, :args } = @unwrap_all! + + with @inputs.socket! + filename = tryprefix @prefix, filename + msg = Message.new{ address: "/texture/#{name}/stream", types: "ss", "TEXTURE_#{type}", 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-input' + name: 'tsv-source' summary: "load a texture-share-vk texture source." - examples: { '(texture [socket] name [type])' } + examples: { '(tsv-source [socket] name [type])' } + description: "Creates a texture source from a texture-share-vk texture. + +- `name` is a unique name for this texture source. +- `type` defaults to `2D`." value: class extends Op pattern = -sig['osc/out'] + const.str + -const.str @@ -111,12 +177,13 @@ shader_ = Constant.meta meta: name: 'shader' summary: "compile a GLSL shader with uniforms." - examples: { '#shader"code…"' } - description: "Syncs code and parameters with glsl-view via OSC. + examples: { '$shader"code…"' } + description: "A template string formatter for [glsl-view/draw][] that returns a shader struct~. - `code…` is a template string that can contain `~-stream` template substitutions that are used as follows: - `str`: substituted directly as GLSL - - `{type: str val: …}`: reference to uniform of type `type` (instead of infered as follows) + - another shader struct~: substituted as GLSL, with uniforms lifted + - `{type: str val: …}`: reference to uniform of GLSL-type `type` (instead of inferred as follows) - `num`, `bool`: reference to `uniform float/bool` - `num[I]`, `bool[I]`: reference to `uniform vecI/bvecI` - `num[I][J]`: reference to `uniform matIxJ`" @@ -211,8 +278,11 @@ Constant.meta summary: "glsl-view integration via OSC." value: - :video - 'tsv-input': tsv_input - :texture + :uniform + + 'video-source': video_source + 'stream-source': stream_source + 'tsv-source': tsv_source + shader: shader_ :draw diff --git a/examples/glsl-view/simple.alv b/examples/glsl-view/simple.alv new file mode 100644 index 0000000..64e3335 --- /dev/null +++ b/examples/glsl-view/simple.alv @@ -0,0 +1,12 @@ +([1]import* glsl-view time math) +([2]import osc) + +([3]def *oscout* ([4]osc/connect 'localhost' 9000)) + +([5]draw $[6]shader" +in vec2 uv; +out vec4 color; + +void main() { + color = vec4(uv, sin(uv.x + $([7]ramp 1 tau)), 1); +}") diff --git a/examples/glsl-view/stream.alv b/examples/glsl-view/stream.alv new file mode 100644 index 0000000..1ca2c63 --- /dev/null +++ b/examples/glsl-view/stream.alv @@ -0,0 +1,20 @@ +([1]import* glsl-view time) +([2]import osc) + +([3]def *oscout* ([5]osc/connect 'localhost' 9000)) + +([6]def cam ([7]stream-source 'webcam' '2D' '/dev/video0') + tst ([8]stream-source 'testpt' '2D' 'testsrc=size=1280x720:rate=30' 'lavfi')) + +([9]draw $[10]shader" +in vec2 uv; +out vec4 color; + +void main() { + vec3 cam = texture($cam , uv).rgb; + vec3 tst = texture($tst , uv).rgb; + + color.rgb = mix(cam, tst, $([11]lfo 1)); + + color.a = 1.0; +}") diff --git a/examples/love-glsl-view-tsv.alv b/examples/love-glsl-view-tsv.alv new file mode 100644 index 0000000..344f979 --- /dev/null +++ b/examples/love-glsl-view-tsv.alv @@ -0,0 +1,26 @@ +([1]import* love math link-time) +([2]import osc glsl-view ) + +([3]def *oscout* ([4]osc/connect 'localhost' 9000) + *clock* ([5]clock false 120)) + +## send from love2d module +([6]tsv-output 'love2d') +([7]draw ([8]->> + ([16]rectangle 'fill' 100 100) + ([14]color [1 0.3 0.6]) + ([11]rotate ([12]* tau ([13]ramp 2))) ## rotate tau (2*PI) every 2 seconds + ([9]translate ([10]mouse-pos)) ## move to mouse cursor +)) + +## receive in glsl-view +([17]def my-tex ([18]glsl-view/tsv-source 'love2d')) +([19]glsl-view/draw $[20]glsl-view/shader" +in vec2 uv; +out vec4 col; + +void main() { + vec2 p = uv * $([21]switch ([22]every 1) 1 2 3); + col = texture($my-tex , p); + col.a = 1; +}") |
