Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Love this lib #1

Open
rbenzazon opened this issue Jun 9, 2024 · 2 comments
Open

Love this lib #1

rbenzazon opened this issue Jun 9, 2024 · 2 comments

Comments

@rbenzazon
Copy link

rbenzazon commented Jun 9, 2024

I've been browsing this code for hours, I love the effort to make something similar than three but way better and more modern.

I'm contemplating the idea of writing a new kind of webgl engine, yours is doing many things that I want. All began when browsing threejs source code, I was a bit disappointed about the patterns used. I wanted to see if the tree shaking was really there. It wasn't. Mainly due to poor coding practices ( some were pre esm leftovers, other plain bad ideas ). I get the feeling that the lib was never designed to be truly optimized.

I want to create one similar to svelte, which compiles the app to a more static code, which has tailor made shaders (pre compiled not full of conditions) which has a perfect tree shaking using polymorphism and proper de-coupling.
When you take three, and you create a rotating cube example, you get 1KB of your app, +600KB of three, even if you bundle three within the app, not using the pre bundled version.
Now you do the same ex in pure JS webgl, without engine, using m4 imported in ESM function by function (important detail, never *), you get 7KB. OK there are some things missing here and there but clearly not 600KB.

I managed to get to 220KB re-creating the Three repo, copying class by class, deleting huge unused module chunks, not even bothering to make it work, it requires a bit of redesign in some cases to work, for instance shaderlib and shaderchunk load everything always, I just kept them but empty. Still huge in my opinion. I had to activate class property mangle, which forces apps that would use the lib to bundle together in the same bundle context I guess, not necessarily bad.

Then I started understanding the threejs lib job, and how it achieves it. It's a kind of reactive engine, but without being truly one. There is no declarative reactive statements. The GLSL is string. The clever bit relies on JS replace function, which I don't like. The invalidation mechanism is specific in each case, reinventing the wheel each time.

threlte is clever, but the reactive part that I want is the engine, but threlte only makes the app reactive and relies solely on three as engine.

I would prefer having glsl in dedicated files to empower the shader dev with the best IDE integration, but make them a template as well with language extension, like what svelte is doing with HTML in .svelte files, but keep the JS outside. Components would be a JS function/class that ties potentially to shader(s) templates which expose a prop API. In 3d engines and apps, including custom 3d components, you don't always need to associate the JS code with shaders.

Ideally a compiler would calculate what's static within the app and what is runtime reactive, so no complete lib is needed, components and models are the most static possible and only the actually used webgl API code is bundled, either shared or inlined if used once. Shader pre compiled with used materials and options only.

I don't know about the behavior of zephyr3d completely, it seems that it's doing most of what I'm looking for, except that some part is runtime instead of pre compiled, is that correct? I checked out one example (gltf helmet) and it seems that it's only 300KB including everything like gltf loader, which is impressive. I plan on trying it out and discover the details. From what I've see this lib is a huge contribution to the worlds of webgl/gpu rendering, thank you so much.

The only thing I found super impressive but I would prefer different, is the choice of JS for the shaders. I think we can achieve the same with glsl directly, but we need to add templating to the language. The JS version avoids the language extension but at the cost of not being glsl files with language tools. Also your approach makes the JS variables used in glsl easy to track, so there is no bundler/minifyer challenge. In the glsl extension path, this is a big difficulty, write bundler plugins to minimize the glsl and its template variables knowing where they originate from.

@gavinyork
Copy link
Owner

Hi rbenzazon,

Thanks a ton for diving into my project and giving such detailed feedback! I'm super excited to hear that you find it impressive and that it matches up with a lot of your ideas and goals.

One of my main goals has been to keep the compiled js as small as possible. I've put a lot of effort into effective tree shaking, though I know there's always room to get better.

Using js for shaders instead of GLSL/WGSL is definitely a bit of an experiment. I'm not a big fan of the traditional string assembly method for shaders. String templating can be a pain and isn't very flexible. Plus, supporting multiple shader languages with string templates would mean different implementations, which just adds complexity. By writing shaders directly in js, I was aiming for more flexibility and dynamic shader definitions.

For zephyr3d, all shaders are currently generated at runtime because of the Javascript-based shader generation. There's no system for using pre-compiled shaders right now. I chose this approach to maximize flexibility, but I get that pre-compilation could have its perks, and I'm open to exploring it in future updates.

I'd love to hear more about what you're working on and any other ideas you have. If you try out zephyr3d and have any questions or more feedback, feel free to reach out.

Best regards,

Gavinyork

@rbenzazon
Copy link
Author

Hi Gavinyork,
I've been delighted to get your answer, I'm planning on diving more into your lib and make examples to study the runtime behavior more. I didn't abandon my idea of a compiler but I need to take some steps to make it happen. For now I'm focusing on creating a reactive and aggressively tree shaken engine :
https://github.com/rbenzazon/svelte-gl
It uses svelte stores to wire the different parts of the engine reactively and I've started to design the decoupling approach to get between 20KB and 30KB minified based lib when it will have more features. As a user, the app you want to create is the main svelte file, the engine is the store model, the gl file have most of the core webgl api calls, lights and effects (here only tone mapping) is imported by the main file and injected into the engine. These "components" import their own shader elements and provide a function to expose it to the engine, for instance :
-declarations, stacks things before the main function
-irradiance, which is by definition additive so easy to stack between light types
-color, stacks fragColor assignment, technically I can add multiple tone mapping
The templating is string literals directly within the glsl. The syntax highlighter I use doesn't seem to bother too much. It's simplistic but works for now.
Only one material (will be PBR when complete)
The idea behind this is to design and test the reactive model before doing a compiler. This lib will be useful for simple 3d visualization and to create big data 3d charts by being ultra simple and efficient, often using a single program with batched and instanced geometry. The main app file being svelte we can leverage the component reactive statement which can defined the interactivity of the scene data. I don't plan on modelling the 3d component as svelte component, only the UI will be done using svelte HTML/component templating.

Greetings
Raphaël

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants