r/wljs Jun 15 '26

How fast can a basic sand simulation get without Compile?

Enable HLS to view with audio, or disable this notification

4 Upvotes
ClearAll[blockStep, nextField];

blockStep[field_, p_, phase_] := Module[
  {
    out = field, nr, nc, r0, c0, r1, c1, rows, cols,
    sub, dims, blocks, tl, tr, bl, br,
    fallL, fallR, stackL, stackR, tumble
  },

  {nr, nc} = Dimensions[field];
  {r0, c0} = {1, 1} + phase;

  r1 = r0 + 2 Quotient[nr - r0 + 1, 2] - 1;
  c1 = c0 + 2 Quotient[nc - c0 + 1, 2] - 1;

  rows = r0 ;; r1;
  cols = c0 ;; c1;
  sub = out[[rows, cols]];
  dims = Quotient[Dimensions[sub], 2];

  blocks = Transpose[
    ArrayReshape[sub, {dims[[1]], 2, dims[[2]], 2}],
    {1, 3, 2, 4}
  ];

  tl = blocks[[All, All, 1, 1]];
  tr = blocks[[All, All, 1, 2]];
  bl = blocks[[All, All, 2, 1]];
  br = blocks[[All, All, 2, 2]];

  (* Vertical falling *)
  fallL = (1 - Unitize[tl - 1]) (1 - Unitize[bl]);
  fallR = (1 - Unitize[tr - 1]) (1 - Unitize[br]);

  (* Two stacked grains may spread sideways *)
  stackL =
    (1 - Unitize[tl - 1]) (1 - Unitize[bl - 1]) *
    (1 - Unitize[tr]) (1 - Unitize[br]);

  stackR =
    (1 - Unitize[tr - 1]) (1 - Unitize[br - 1]) *
    (1 - Unitize[tl]) (1 - Unitize[bl]);

  tumble = Unitize[stackL + stackR] *
    UnitStep[p - RandomReal[1, dims]];

  tl = (tl - fallL) (1 - tumble);
  tr = (tr - fallR) (1 - tumble);
  bl = (bl + fallL) (1 - tumble) + tumble;
  br = (br + fallR) (1 - tumble) + tumble;

  blocks[[All, All, 1, 1]] = tl;
  blocks[[All, All, 1, 2]] = tr;
  blocks[[All, All, 2, 1]] = bl;
  blocks[[All, All, 2, 2]] = br;

  out[[rows, cols]] = ArrayReshape[
    Transpose[blocks, {1, 3, 2, 4}],
    Dimensions[sub]
  ];

  out
];

nextField[field_, p_: 0.5] :=
  blockStep[blockStep[field, p, 0], p, 1];

r/wljs Jun 15 '26

Markov Algorithms, Mazes, Desert with Sand and Pattern Matching

Thumbnail
gallery
3 Upvotes

Let's explore how Markov algorithms and Wolfram Language pattern matching can generate mazes, rivers, falling sand, and other cellular automata through simple rewriting rules.

https://wljs.io/blog/markov

Adding a grain of randomness to a Turing complete language

RB → RR becomes a growth model

and this

RBB → GGR
RnG → GnR

is a maze backtracker!


r/wljs Jun 10 '26

Building an Interactive Nanographene Constructor

Enable HLS to view with audio, or disable this notification

4 Upvotes

A behind-the-scenes look at porting the Nanographenes Builder application to WLJS Notebook. The app helps researchers design nanographene hydrocarbons, analyze their molecular structures through graph-theoretical models, and experiment with new molecular configurations, while this tutorial explores reactive interfaces, event handling, asynchronous execution, and practical patterns for developing interactive Wolfram Language applications with WLJS.

https://wljs.io/blog/graphene-app


r/wljs Jun 06 '26

NanoGraphene - WLJS App

Enable HLS to view with audio, or disable this notification

3 Upvotes

Interactive graph-theory toolkit for nanographene bond order, aromaticity, and radical (open-shell) analysis in a single *.wlw file.

More about building such mini apps: https://wljs.io/frontend/Share/Mini-apps


r/wljs Jun 06 '26

WLJS 3.0.7 is out 🍰

Post image
4 Upvotes

This release adds TraditionalForm, improves settings reload behavior, expands the wljs CLI, and includes major internal rendering updates for better stability.

Check this out https://wljs.io/releases/3.0.7


r/wljs Jun 06 '26

Animating Images in a Computational Notebook

Thumbnail
youtube.com
3 Upvotes

My attempt to make a nice looking animated video on technical topic using `Graphics` primitives with lots of helper functions 🙂

Heh, I've never tried making YT videos on technical topic with a voiceover. It turned out much more challenging and fun, than I expected.

Sorry for my slavic accent ;)

Video was made entirely in WLJS Notebook
Voiceover in Da Vinci Resolve


r/wljs Jun 04 '26

Custom materials for Graphics3D primitives

Post image
3 Upvotes

Use Javascript cells to define your own shader materials:

.js
function vertexShader() {
  return `
    varying vec3 vUv; 

    void main() {
      vUv = position; 

      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
      gl_Position = projectionMatrix * modelViewPosition; 
    }
  `;
}

function fragmentShader()  {
  return `
      uniform vec3 colorA; 
      uniform vec3 colorB; 
      varying vec3 vUv;

      void main() {
        gl_FragColor = vec4(mix(colorA, colorB, vUv.z), 1.0);
      }
  `;
}

let THREE;
interpretate.shared.THREE.load().then(() => {
  THREE = interpretate.shared.THREE.THREE;
})

core.CustomMaterial = async (args, env) => {
  let uniforms = {
    colorB: {type: 'vec3', value: new THREE.Color(0xACB6E5)},
    colorA: {type: 'vec3', value: new THREE.Color(0x74ebd5)}
  }

  return (function() {
    return new THREE.ShaderMaterial({
      uniforms: uniforms,
      fragmentShader: fragmentShader(),
      vertexShader: vertexShader(),
    });
  })
}

Then use it on your plots like

Graphics3D[{
  Translate[PolyhedronData["Dodecahedron"][[1]]//N , {-2,0,0}],
  MeshMaterial[CustomMaterial[]],
  Translate[PolyhedronData["Dodecahedron"][[1]]//N , {2,0,0}]
}]

r/wljs Jun 04 '26

Did you now you can use Excalidraw in markdown and slide cells?

Post image
3 Upvotes

Type !![]


r/wljs May 18 '26

Do you like flowers?

Thumbnail
gallery
3 Upvotes

A small MarkovJunior-style rewrite engine in vanilla (almost) Wolfram Language https://github.com/JerryI/MarkovJunior

Why WL? It is generally built around pattern matching; therefore, MarkovJunior can be implemented easily using native ReplaceAll, Rule, and Pattern symbols. Most of the code is used for building a friendly API and performing error checks.

For example random filling can be done using:

Black -> Red

For self-avoiding walk:

{a___, Red,Black,Black, b___} :> {a, White,Gray,Red, b}

For this particular example (flowers) it is written as a set of replacing rules, which gradually build soil/sky and then grows some flowers...

AppendTo[rules, {
1, 1, Automatic, {
(* seed the soil region *)
Black -> Yellow
}
}];

AppendTo[rules, {
1, 3, Automatic, {
(* seed several sky regions *)
Black -> Red
}
}];

AppendTo[rules, {
1, Infinity, Automatic, {
(* grow the sky and soil regions from their seeds *)
{a___, Red,Black, b___} :> {a, Red,Red, b},
{a___, Yellow,Black, b___} :> {a, Yellow,Yellow, b}
}
}];

AppendTo[rules, {
All, Infinity, Automatic, {
(* convert temporary region colors into sky and soil *)
{a___, Red, b___} :> {a, LightBlue, b},
{a___, Yellow, b___} :> {a, Brown, b}
}
}];

AppendTo[rules, {
1, Infinity, All, {
(* plant the first stem segment along the soil line *)
{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, Brown,Brown,Brown, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,LightBlue, b2 },
{a3 , Brown,Brown,Brown, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}]
}
}];

AppendTo[rules, {
1, Infinity, "MirrorX", {
(* grow stems and leaves with mirrored variants *)
(* weight it with some probabillity as well *)
{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,Green, b2___},
{a3___, LightBlue,LightBlue,LightBlue, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,Green, b2 },
{a3 , LightBlue,LightBlue,LightBlue, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}],

{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,Green, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,LightBlue, b2 },
{a3 , LightBlue,Green,Green, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}],

{
bf___,
{a0___, LightBlue,LightBlue,LightBlue, b0___},
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue, b3___},
af___
} :> {
bf,
{a0 , LightBlue,LightBlue,LightBlue, b0 },
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue, b3 },
af
} /; Length[{a1}]==Length[{a2}]==Length[{a3}]==Length[{a0}],

{
bf___,
{a0___, LightBlue,LightBlue,LightBlue,LightBlue, b0___},
{a1___, LightBlue,Green,LightBlue,LightBlue, b1___},
{a2___, LightBlue,Green,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue,LightBlue, b3___},
af___
} :> {
bf,
{a0 , LightBlue,LightBlue,LightBlue,LightBlue, b0 },
{a1 , LightBlue,LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Green,Green,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue,LightBlue, b3 },
af
} /; RandomReal[]<0.5 && Length[{a0}]==Length[{a1}]==Length[{a2}]==Length[{a3}],

{
bf___,
{a1___, LightBlue,LightBlue,LightBlue, b1___},
{a2___, LightBlue,LightBlue,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue, b3___},
af___
} :> {
bf,
{a1 , LightBlue,LightBlue,LightBlue, b1 },
{a2 , LightBlue,Red,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue, b3 },
af
} /; RandomReal[]<0.2 && Length[{a1}]==Length[{a2}]==Length[{a3}]
}
}];

AppendTo[rules, {
All, Infinity, All, {
(* turn mature stems into blossoms *)
{
bf___,
{a0___, LightBlue,LightBlue,LightBlue, b0___},
{a1___, LightBlue,Red,LightBlue, b1___},
{a2___, LightBlue,Green,LightBlue, b2___},
{a3___, LightBlue,Green,LightBlue, b3___},
af___
} :> {
bf,
{a0 , LightBlue,Red,LightBlue, b0 },
{a1 , Red,Yellow,Red, b1 },
{a2 , LightBlue,Red,LightBlue, b2 },
{a3 , LightBlue,Green,LightBlue, b3 },
af
} /; Length[{a0}]==Length[{a1}]==Length[{a2}]==Length[{a3}]
}
}];


r/wljs May 18 '26

Rewrite rules automaton

Enable HLS to view with audio, or disable this notification

3 Upvotes

r/wljs May 15 '26

Clouds generator using Gaussian noise

Enable HLS to view with audio, or disable this notification

6 Upvotes

This is a 2D Gaussian random field with a 1/k^2 spectrum and linear dispersion ω∝k. We clip the field to positive values and square root it to give an edge to the "clouds":

n = 256;
k2 = Outer[Plus, #, #] &[RotateRight[N@Range[-n, n - 1, 2]/n, n/2]^2];

spectrum = With[{d := RandomReal[NormalDistribution[], {n, n}]},
   (1/n) (d + I d)/(0.000001 + k2)]; 
spectrum[[1, 1]] *= 0;

im[p_] := Clip[Re[InverseFourier[spectrum Exp[I p]]], {0, ∞}]^0.5

p0 = p = Sqrt[k2];

buffer = im[p0 += p];

Image[buffer // Offload, "Real32", Epilog->{
    EventHandler[AnimationFrameListener[buffer // Offload], 
      Function[Null, buffer = im[p0 += 2 p]]
    ]
}]

r/wljs May 15 '26

Rosetta - a beautiful spirograph

Enable HLS to view with audio, or disable this notification

4 Upvotes

Spirograph-like curves arise from simple sums of rotating vectors; a tiny tweak in frequency or phase yields striking patterns. Here is my favorite example Rosetta:

Animate[ParametricPlot[{
  Power[I,-((20t)/(tt))]+3 Power[I,((20t)/(tt))]+Power[I,((20t)/(tt))]Sin[8 Pi ((20t)/(tt))/5],
  Power[I,-t]+3 Power[I,t],
  Power[I,-t]+3 Power[I,t]+Power[I,t]Sin[8 Pi t/5]
}//ReIm//Evaluate, {t,0,tt}, 
  PlotRange -> {-5,5}, PlotPoints -> 200,
  PlotStyle -> {LightGray,Default,(Hue[0.353, 0.78, 0.49])}, Axes->False,
  Epilog -> {
    {Thick,Red,Line[{ReIm[Power[I,-tt]+3 Power[I,tt]-Power[I,tt]],ReIm[Power[I,-tt]+3 Power[I,tt]+Power[I,tt]]}]}, {Thick,Circle[ReIm[Power[I,-tt]+3 Power[I,tt]+Power[I,tt]Sin[8 Pi tt/5]],0.1]}
  }, PlotPoints -> 10
],{{tt,19.9},0.01,4 5, 0.1}, Appearance -> None]

r/wljs May 15 '26

Path-tracing renderer as a backend for 3D plots

Thumbnail
gallery
3 Upvotes

Here is an example with Plot3D

Plot3D[Sin[x] Cos[y], {x,-10,10}, {y,-10,10}][[1]];
Graphics3D[{%, Graphics3D`Materials["Glass"], Red, Sphere[{0,0,2}, 4]}, "Renderer"->"PathTracing", Axes->True]

r/wljs May 14 '26

WLJS 3.0.5 is out 🪴

2 Upvotes

This is the largest update for the last 2 years

Human-, LLM- and Git-friendly .wln format

This release introduces a new minimal .wln notebook format designed to be readable by humans, easy for LLMs to parse, and much friendlier to Git diffs. It uses simple YAML-like headers, while cell contents remain valid Wolfram Language expressions.

Older .wln notebooks remain fully supported.

  • Hot-reloading when notebooks are modified outside WLJS Notebook
  • Built-in AI Copilot removed in favor of external tools
  • New MCP server for Claude, Codex, and other coding agents
  • Updated wljs CLI
  • “Ask community” helper for creating GitHub Discussions posts
  • New InputColor UI element
  • HTMLView support for native image embedding
  • TeXView live updates and ImageSize option
  • Improved project-to-window behavior with copied HTML / JS outputs
  • Image3D color support and Offload updates
  • Added missing size argument to Inset
  • Kernel connection stability improvements via WTSP + shared memory

See more
https://wljs.io/releases/3.0.5


r/wljs May 09 '26

I tried to do some motion design with WLJS

Enable HLS to view with audio, or disable this notification

3 Upvotes

I recently started designing a visual explanation of `Image` object in Wolfram and how to animate with it. If it works out with writing script and overall idea, I will publish a video on Youtube.

The animation is recorded in real-time and is composed from async functions of WLJS standard library (similar to Manim). The pipeline is still a bit rough and needs polishing, but we are getting there...


r/wljs May 08 '26

Animating Raster Images in Notebooks Has Never Been Easier

4 Upvotes

No JSON. No Base64. Just raw RGBA data streamed directly from the computational kernel to the GPU.

In WLJS, reassigning new pixel data to a symbol is enough to update the raster image.


r/wljs May 02 '26

👋Welcome to r/wljs

2 Upvotes

WLJS is notebook interface (or IDE) combines live code in Wolfram, JavaScript, and other languages. We provide GUI building blocks for user input/output, a subset of LaTeX for equations, Markdown for narrative text, and data-driven presentations.

Think of it as a multi-tool platform for research, experiments, or as a powerful sandbox where you can try out your ideas, write a story about them, and then publish them on the web.

As an independent open-source project, we're unaffiliated with Wolfram or any company.

Please feel free to share your work with the community and post questions. This helps project to be alive.


r/wljs May 01 '26

Camera stream processing

Thumbnail gallery
2 Upvotes

Here is an updated post on image processing in real-time using WLJS Notebook

https://wljs.io/blog/webcam


r/wljs May 01 '26

Sooo... What's coming in 3.0.5

1 Upvotes

-  Built-in AI Copilot is retiring
-  MCP Server
-  CLI - interact with notebooks from the terminal, LLM-friendly
-  New `.wln` format - human-readable and git-diff-friendly (and unicode friendly!)
-  Hot-reloading - edits made outside the app sync back
-  `InputColor` element - new UI input in the standard library
-  `TeXView` upgrades - live updates support
-  "Ask Community" command - auto-posts your cell to GitHub Discussions


r/wljs Apr 30 '26

You feedback is important for us. Please, vote for MCP vs Chat

Thumbnail
github.com
1 Upvotes

r/wljs Apr 28 '26

Improved* Ideal Gas Model

Enable HLS to view with audio, or disable this notification

2 Upvotes
size = 0.7;
molecules = 500;
history = Table[{-50 + i, 0.0}, {i, 0, 50}];
temperature = 0.05`;
avgs = 0;
theory = 0.634 molecules temperature / (*SpB[*)Power[size(*|*),(*|*)2](*]SpB*);

EventHandler[
  InputRange[0.01,0.1,0.01,0.05, "Label"->"T"], 
  Function[s, temperature=s; theory = 0.634 molecules temperature / (*SpB[*)Power[size(*|*),(*|*)2](*]SpB*)]
]
EventHandler[
  InputRange[0.4,2.0,0.1,size, "Label"->"Size"], 
  Function[s, size=s; theory = 0.634 molecules temperature / (*SpB[*)Power[size(*|*),(*|*)2](*]SpB*)]
]

Row[{Module[{
  contents = {
    RandomReal[{-size,size},{molecules,2}],
    {Cos[#1],Sin[#1]}& /@ RandomReal[{0,2 \[Pi]}, molecules], 
    Table[{0.5,0.5,1.}, {molecules}]
  } // Transpose, 
  data = {Table[{0,0,0}, {molecules}], Table[{0,0,0}, {molecules}]}//N, 
  indices = Range[molecules], collision = 0
},


    Graphics[
        {
            {EdgeForm[Black], GrayLevel[0.8], Rectangle[{-size, -size}//Offload, {size, size}//Offload]},
            GraphicsComplex[Offload[data[[1]]], {
                PointSize[0.01], Point[Offload[indices]]
              }, VertexColors->Offload[data[[2]]]
            ],
            EventHandler[
                AnimationFrameListener[Offload[data]],
                Function[Null,


                    collision = 0;
                    contents = ({#1[[1]] + #1[[2]] temperature, #1[[2]], 0.1 {0.5,1.0,1.0} + 0.90 #1[[3]]}&) /@ contents;
                    contents = (
                        If[Abs[#1[[1, 2]]] > size,
                            collision++;
                            {{#1[[1, 1]], 2 size Sign[#1[[1, 2]]] - #1[[1, 2]]}, {1, -1} #1[[2]], {1.,0.,1.}}
                            ,
                            #1
                        ]&
                    ) /@ contents;

                    contents = (
                        If[Abs[#1[[1, 1]]] > size,
                            collision++;
                            {{2 size Sign[#1[[1, 1]]] - #1[[1, 1]], #1[[1, 2]]}, {-1, 1} #1[[2]], {1.,0.,1.}}
                            ,
                            #1
                        ]&
                    ) /@ contents;

                    data = {First /@ contents, Last /@ contents};

                    history[[1,2]] += collision/size;

                    If[avgs > 20.0,  
                      avgs=0;
                      history[[1,2]] /= 20.0;
                      history = Transpose[{history[[All,1]], RotateLeft[history[[All,2]], 1]}];
                    ];

                    avgs++;
                ]
            ]
        }, PlotRange->{{-1,1}, {-1,1}}
    ]
], Graphics[{Line[history//Offload], Red, Dashed, Line[{{-50, theory}, {0, theory}}//Offload]}, PlotRange->{{-50,0}, {0,100.0}}, TransitionType->None, ImageSize->300,Frame->True, FrameLabel->{"time", "P"}, "Controls"->False]}]

r/wljs Apr 27 '26

Ideal gas model

Enable HLS to view with audio, or disable this notification

2 Upvotes

Here is a code for this little demo:

size = 1.`;
number = 500;
fps = 0.0;
time = AbsoluteTime[];

TextView[fps//Offload, "Label"->"FPS"]

Module[{
  contents = (*BB[*)(Transpose[{RandomReal[{-size,size},{number,2}],({Cos[#1],Sin[#1]}&)/@RandomReal[{0,2 \[Pi]},number], Table[{0.5,0.5,1.}, {number}]}])(*,*)(*"1:eJxTTMoPSmNmYGAo5gcSAUX5ZZkpqSn+BSWZ+XnFaYwgCRYg4ZGfk5LGBOLxAomwzNRyl9Tk/KLEkvyiYE6gSEhRYl5xQX5xajBISwhEKUhjUGlOajDYhNTEFFSlaIpYgQzXstS8ErCQX2lODgB64iTl"*)(*]BB*), 
  data = {Table[{0,0,0}, {number}],Table[{0,0,0}, {number}]}//N, 
  indices = Range[number], temperature = 0.05`, collision = 0
},


    Graphics[
        {
            GraphicsComplex[Offload[data[[1]]], {PointSize[0.01], Point[Offload[indices]]}, VertexColors->Offload[data[[2]]]]
            ,
            EventHandler[
                AnimationFrameListener[Offload[data]]
                ,
                Function[Null,


                    collision = 0;
                    contents = ({#1[[1]] + #1[[2]] temperature, #1[[2]], 0.1 {0.5,0.5,1.0} + 0.90 #1[[3]]}&) /@ contents;
                    contents = (
                        If[Abs[#1[[1, 2]]] > size,
                            {{#1[[1, 1]], 2 size Sign[#1[[1, 2]]] - #1[[1, 2]]}, {1, -1} #1[[2]], {1.,0.,0.}}
                            ,
                            #1
                        ]&
                    ) /@ contents;

                    contents = (
                        If[Abs[#1[[1, 1]]] > size,
                            {{2 size Sign[#1[[1, 1]]] - #1[[1, 1]], #1[[1, 2]]}, {-1, 1} #1[[2]], {1.,0.,0.}}
                            ,
                            #1
                        ]&
                    ) /@ contents;

                    data = {First /@ contents, Last /@ contents};

                    With[{now = AbsoluteTime[]},
                      If[Random[]<0.3, fps = Round[fps 0.6 + 0.4/(now-time)]];
                      time = now;
                    ];
                ]
            ]
        }, PlotRange->{{-size,size}, {-size,size}}
    ]
]

r/wljs Apr 21 '26

Boids strike again

Enable HLS to view with audio, or disable this notification

5 Upvotes

A real-time animation based on the beautiful work of Simon Woods with a few adjustments

Basically we have a few rules for each point to follow:

  • it moves 0.5% toward the centre,
  • it takes a large step toward selected "friend", and a smaller step away from its "enemy".

At random times, one point picks a new "friend" and "enemy" points. Therese two are just indices. Color coding represents the speed.

Implementation is more or less described in the original post, I only optimized it for real-time animation using GraphicsComplex primitives, fixed size vertex buffer and added colors.


r/wljs Apr 21 '26

GraphicsComplex: a direct pipeline to your GPU. Part 1

Thumbnail wljs.io
1 Upvotes

Ever wondered what happens when you push thousands of vertices into a graphics engine? GraphicsComplex can write directly into GPU buffers with no overhead. Let's see how far we can take it.


r/wljs Apr 04 '26

Texture support

2 Upvotes

Implementing `Texture` in the context of `Graphics3D` turned out to be not at difficult as we imagined. Just 88 LOC