glslkit-webgl 0.1.0.pre

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.
@@ -0,0 +1,11 @@
1
+ #pragma once
2
+
3
+ mat2 rotate2d(float angle) {
4
+ float c = cos(angle), s = sin(angle);
5
+ return mat2(c, -s, s, c);
6
+ }
7
+
8
+ float sdTorus(vec3 p, vec2 t) {
9
+ vec2 q = vec2(length(p.xz) - t.x, p.y);
10
+ return length(q) - t.y;
11
+ }
@@ -0,0 +1,8 @@
1
+ #version 300 es
2
+ precision mediump float;
3
+ in vec2 v_uv;
4
+ uniform sampler2D u_texture;
5
+ out vec4 frag_color;
6
+ void main() {
7
+ frag_color = texture(u_texture, v_uv);
8
+ }
@@ -0,0 +1,9 @@
1
+ #version 300 es
2
+ layout(location = 0) in vec3 a_position;
3
+ layout(location = 1) in vec2 a_uv;
4
+ uniform mat4 u_mvp;
5
+ out vec2 v_uv;
6
+ void main() {
7
+ v_uv = a_uv;
8
+ gl_Position = u_mvp * vec4(a_position, 1.0);
9
+ }
@@ -0,0 +1,79 @@
1
+ #version 300 es
2
+ precision highp float;
3
+
4
+ uniform float u_time;
5
+ uniform vec2 u_resolution;
6
+ out vec4 frag_color;
7
+
8
+ #define PI 3.14159265359
9
+
10
+ #include "common/sdf.glsl"
11
+ #include "common/color.glsl"
12
+
13
+ float scene(vec3 p) {
14
+ p.xz *= rotate2d(u_time * 0.32);
15
+ p.xy *= rotate2d(sin(u_time * 0.27) * 0.55);
16
+
17
+ float angle = atan(p.z, p.x);
18
+ float pulse = 0.10 * sin(angle * 7.0 + u_time * 2.4);
19
+ float portal = sdTorus(p, vec2(1.25, 0.17 + pulse));
20
+
21
+ vec3 orb = p;
22
+ orb.xz *= rotate2d(-u_time * 0.7);
23
+ orb -= vec3(1.25, sin(u_time * 1.8) * 0.22, 0.0);
24
+ float satellite = length(orb) - 0.11;
25
+ return min(portal, satellite);
26
+ }
27
+
28
+ vec3 normalAt(vec3 p) {
29
+ vec2 e = vec2(0.0015, 0.0);
30
+ float d = scene(p);
31
+ return normalize(vec3(
32
+ scene(p + e.xyy) - d,
33
+ scene(p + e.yxy) - d,
34
+ scene(p + e.yyx) - d
35
+ ));
36
+ }
37
+
38
+ float raymarch(vec3 origin, vec3 direction, out vec3 point) {
39
+ float distanceTravelled = 0.0;
40
+ for (int i = 0; i < 96; i++) {
41
+ point = origin + direction * distanceTravelled;
42
+ float distanceToScene = scene(point);
43
+ if (distanceToScene < 0.001 || distanceTravelled > 12.0) break;
44
+ distanceTravelled += distanceToScene * 0.72;
45
+ }
46
+ return distanceTravelled;
47
+ }
48
+
49
+ void main() {
50
+ vec2 uv = (gl_FragCoord.xy * 2.0 - u_resolution) / u_resolution.y;
51
+ float vignette = max(0.0, 1.0 - dot(uv, uv) * 0.28);
52
+
53
+ vec3 origin = vec3(0.0, 0.0, 4.2);
54
+ vec3 direction = normalize(vec3(uv, -1.8));
55
+ vec3 point;
56
+ float travelled = raymarch(origin, direction, point);
57
+
58
+ vec3 color = vec3(0.006, 0.008, 0.025);
59
+ float rays = pow(max(0.0, 1.0 - length(uv)), 5.0);
60
+ color += vec3(0.12, 0.03, 0.30) * rays;
61
+
62
+ if (travelled < 12.0) {
63
+ vec3 normal = normalAt(point);
64
+ vec3 light = normalize(vec3(0.7, 1.2, 2.0));
65
+ float diffuse = max(dot(normal, light), 0.0);
66
+ float rim = pow(1.0 - max(dot(normal, -direction), 0.0), 2.4);
67
+ float bands = 0.5 + 0.5 * sin(atan(point.z, point.x) * 9.0 - u_time * 3.0);
68
+ vec3 neon = palette(bands + u_time * 0.06);
69
+ color += neon * (0.18 + diffuse * 0.65 + rim * 2.4);
70
+ color += pow(max(dot(reflect(-light, normal), -direction), 0.0), 32.0);
71
+ }
72
+
73
+ float glowDistance = abs(length(uv) - 0.47 - sin(atan(uv.y, uv.x) * 7.0 + u_time) * 0.018);
74
+ color += palette(u_time * 0.07 + length(uv)) * 0.012 / max(glowDistance, 0.008);
75
+
76
+ color *= vignette;
77
+ color = pow(color, vec3(0.82));
78
+ frag_color = vec4(color, 1.0);
79
+ }
@@ -0,0 +1,5 @@
1
+ #version 300 es
2
+ layout(location = 0) in vec2 a_position;
3
+ void main() {
4
+ gl_Position = vec4(a_position, 0.0, 1.0);
5
+ }
@@ -0,0 +1,5 @@
1
+ #pragma once
2
+
3
+ vec3 palette(float t) {
4
+ return 0.55 + 0.45 * cos(6.28318 * (vec3(0.02, 0.18, 0.38) * t + vec3(0.0, 0.18, 0.42)));
5
+ }
@@ -0,0 +1,11 @@
1
+ #pragma once
2
+
3
+ mat2 rotate2d(float angle) {
4
+ float c = cos(angle), s = sin(angle)
5
+ return mat2(c, -s, s, c);
6
+ }
7
+
8
+ float sdTorus(vec3 p, vec2 t) {
9
+ vec2 q = vec2(length(p.xz) - t.x, p.y);
10
+ return length(q) - t.y;
11
+ }
@@ -0,0 +1,79 @@
1
+ #version 300 es
2
+ precision highp float;
3
+
4
+ uniform float u_time;
5
+ uniform vec2 u_resolution;
6
+ out vec4 frag_color;
7
+
8
+ #define PI 3.14159265359
9
+
10
+ #include "common/sdf.glsl"
11
+ #include "common/color.glsl"
12
+
13
+ float scene(vec3 p) {
14
+ p.xz *= rotate2d(u_time * 0.32);
15
+ p.xy *= rotate2d(sin(u_time * 0.27) * 0.55);
16
+
17
+ float angle = atan(p.z, p.x);
18
+ float pulse = 0.10 * sin(angle * 7.0 + u_time * 2.4);
19
+ float portal = sdTorus(p, vec2(1.25, 0.17 + pulse));
20
+
21
+ vec3 orb = p;
22
+ orb.xz *= rotate2d(-u_time * 0.7);
23
+ orb -= vec3(1.25, sin(u_time * 1.8) * 0.22, 0.0);
24
+ float satellite = length(orb) - 0.11;
25
+ return min(portal, satellite);
26
+ }
27
+
28
+ vec3 normalAt(vec3 p) {
29
+ vec2 e = vec2(0.0015, 0.0);
30
+ float d = scene(p);
31
+ return normalize(vec3(
32
+ scene(p + e.xyy) - d,
33
+ scene(p + e.yxy) - d,
34
+ scene(p + e.yyx) - d
35
+ ));
36
+ }
37
+
38
+ float raymarch(vec3 origin, vec3 direction, out vec3 point) {
39
+ float distanceTravelled = 0.0;
40
+ for (int i = 0; i < 96; i++) {
41
+ point = origin + direction * distanceTravelled;
42
+ float distanceToScene = scene(point);
43
+ if (distanceToScene < 0.001 || distanceTravelled > 12.0) break;
44
+ distanceTravelled += distanceToScene * 0.72;
45
+ }
46
+ return distanceTravelled;
47
+ }
48
+
49
+ void main() {
50
+ vec2 uv = (gl_FragCoord.xy * 2.0 - u_resolution) / u_resolution.y;
51
+ float vignette = max(0.0, 1.0 - dot(uv, uv) * 0.28);
52
+
53
+ vec3 origin = vec3(0.0, 0.0, 4.2);
54
+ vec3 direction = normalize(vec3(uv, -1.8));
55
+ vec3 point;
56
+ float travelled = raymarch(origin, direction, point);
57
+
58
+ vec3 color = vec3(0.006, 0.008, 0.025);
59
+ float rays = pow(max(0.0, 1.0 - length(uv)), 5.0);
60
+ color += vec3(0.12, 0.03, 0.30) * rays;
61
+
62
+ if (travelled < 12.0) {
63
+ vec3 normal = normalAt(point);
64
+ vec3 light = normalize(vec3(0.7, 1.2, 2.0));
65
+ float diffuse = max(dot(normal, light), 0.0);
66
+ float rim = pow(1.0 - max(dot(normal, -direction), 0.0), 2.4);
67
+ float bands = 0.5 + 0.5 * sin(atan(point.z, point.x) * 9.0 - u_time * 3.0);
68
+ vec3 neon = palette(bands + u_time * 0.06);
69
+ color += neon * (0.18 + diffuse * 0.65 + rim * 2.4);
70
+ color += pow(max(dot(reflect(-light, normal), -direction), 0.0), 32.0);
71
+ }
72
+
73
+ float glowDistance = abs(length(uv) - 0.47 - sin(atan(uv.y, uv.x) * 7.0 + u_time) * 0.018);
74
+ color += palette(u_time * 0.07 + length(uv)) * 0.012 / max(glowDistance, 0.008);
75
+
76
+ color *= vignette;
77
+ color = pow(color, vec3(0.82));
78
+ frag_color = vec4(color, 1.0);
79
+ }
@@ -0,0 +1,5 @@
1
+ #version 300 es
2
+ layout(location = 0) in vec2 a_position;
3
+ void main() {
4
+ gl_Position = vec4(a_position, 0.0, 1.0);
5
+ }
@@ -0,0 +1,49 @@
1
+ (function () {
2
+ "use strict";
3
+
4
+ const script = document.currentScript;
5
+ const entry = script && script.dataset.entry;
6
+ const rubyVersion = (script && script.dataset.rubyVersion) || "4.0";
7
+ const wasmWasiVersion = (script && script.dataset.wasmWasiVersion) || "2.10.1";
8
+
9
+ if (!entry) {
10
+ throw new Error("glslkit-webgl: data-entry must name the Ruby entry file");
11
+ }
12
+
13
+ const packageName = `@ruby/${rubyVersion}-wasm-wasi`;
14
+ const packageRoot = `https://cdn.jsdelivr.net/npm/${packageName}@${wasmWasiVersion}/dist`;
15
+ const wasmUrl = `${packageRoot}/ruby+stdlib.wasm`;
16
+ const vmUrl = `https://cdn.jsdelivr.net/npm/@ruby/wasm-wasi@${wasmWasiVersion}/dist/browser/+esm`;
17
+
18
+ async function compile(response) {
19
+ if (!response.ok) {
20
+ throw new Error(`glslkit-webgl: failed to fetch ruby.wasm (${response.status})`);
21
+ }
22
+
23
+ try {
24
+ return await WebAssembly.compileStreaming(response.clone());
25
+ } catch (_error) {
26
+ return WebAssembly.compile(await response.arrayBuffer());
27
+ }
28
+ }
29
+
30
+ async function boot() {
31
+ const [{ DefaultRubyVM }, response] = await Promise.all([
32
+ import(vmUrl),
33
+ fetch(wasmUrl),
34
+ ]);
35
+ const module = await compile(response);
36
+ const { vm } = await DefaultRubyVM(module);
37
+ const baseUrl = new URL(".", new URL(entry, document.baseURI)).href;
38
+ const feature = new URL(entry, document.baseURI).pathname.split("/").pop().replace(/\.rb$/, "");
39
+ const ruby = [
40
+ 'require "js/require_remote/relative_shim"',
41
+ `JS::RequireRemote.instance.base_url = ${JSON.stringify(baseUrl)}`,
42
+ `JS::RequireRemote.instance.load(${JSON.stringify(feature)})`,
43
+ ].join("\n");
44
+
45
+ await vm.evalAsync(ruby);
46
+ }
47
+
48
+ window.glslkitWebGLReady = boot();
49
+ })();
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glslkit-webgl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - kyubey1228
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-08-24 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: glslkit
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 0.1.0.pre
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: 0.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: 0.1.0.pre
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: 0.2.0
32
+ description: Lets you write WebGL2 rendering code entirely in Ruby, running under
33
+ ruby.wasm in the browser. Resolves uniform/attribute locations from a glslkit reflection
34
+ manifest instead of calling getActiveUniform, and surfaces shader compile errors
35
+ as Ruby exceptions pointing at the original file and line. REQUIRES a ruby.wasm
36
+ runtime (the `js` gem) to run — it installs under a normal CRuby/JRuby/TruffleRuby,
37
+ but raises a clear LoadError instead of working there. This gem is meant to be bundled
38
+ into a ruby.wasm build (see README), not required from a regular Ruby process.
39
+ email:
40
+ - kyuuka1228@gmail.com
41
+ executables: []
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - CHANGELOG.md
46
+ - LICENSE.txt
47
+ - README.md
48
+ - glslkit-webgl.gemspec
49
+ - lib/glslkit/webgl.rb
50
+ - lib/glslkit/webgl/context.rb
51
+ - lib/glslkit/webgl/embed.rb
52
+ - lib/glslkit/webgl/errors.rb
53
+ - lib/glslkit/webgl/geometry.rb
54
+ - lib/glslkit/webgl/live_reload.rb
55
+ - lib/glslkit/webgl/matrix.rb
56
+ - lib/glslkit/webgl/program.rb
57
+ - lib/glslkit/webgl/reload_result.rb
58
+ - lib/glslkit/webgl/texture.rb
59
+ - lib/glslkit/webgl/version.rb
60
+ - sample/app.rb
61
+ - sample/error_panel.rb
62
+ - sample/generated-broken/neon-broken_shaders.rb
63
+ - sample/generated/cube_shaders.rb
64
+ - sample/generated/neon_shaders.rb
65
+ - sample/index.html
66
+ - sample/neon-error.html
67
+ - sample/neon-error.rb
68
+ - sample/neon.html
69
+ - sample/neon.rb
70
+ - sample/shaders-broken/common/color.glsl
71
+ - sample/shaders-broken/common/sdf.glsl
72
+ - sample/shaders-broken/neon-broken.frag
73
+ - sample/shaders-broken/neon-broken.vert
74
+ - sample/shaders/common/color.glsl
75
+ - sample/shaders/common/sdf.glsl
76
+ - sample/shaders/cube.frag
77
+ - sample/shaders/cube.vert
78
+ - sample/shaders/neon.frag
79
+ - sample/shaders/neon.vert
80
+ - shim/glslkit-webgl.js
81
+ homepage: https://github.com/kyubey1228/glslkit
82
+ licenses:
83
+ - MIT
84
+ metadata:
85
+ homepage_uri: https://github.com/kyubey1228/glslkit
86
+ source_code_uri: https://github.com/kyubey1228/glslkit/tree/main/webgl
87
+ changelog_uri: https://github.com/kyubey1228/glslkit/blob/main/webgl/CHANGELOG.md
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '3.1'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubygems_version: 3.6.2
103
+ specification_version: 4
104
+ summary: ruby.wasm WebGL2 binding that consumes glslkit reflection manifests
105
+ test_files: []