ShaderFrog / editor

MIT License
25 stars 6 forks source link

Improved boilerplate on new shaders #10

Open Bug-Reaper opened 3 weeks ago

Bug-Reaper commented 3 weeks ago

Finally learned enough GLSL and THREE-flavored GLSL to be dangerous!

Went to port over some of my shader-toys and from what I remember the process went something like this.

  1. Created a new shader.
  2. Struggled a bit to hook up some of the usual varyings like vNormal/vPosition/vUv etc....
  3. Couln't figure out how to add iTime.
  4. Bailed lol.

I think some upgraded default boilerplate is gonna go a long way for easier adoption:

  1. Add in all of the default available varyings through threejs vNormal, vPosition, vUv, the vertexColor one. Doesn't have to use all of them per say but just have them declared in the default vertex/frag shaders.
  2. Add a default iTime or iTime equivelant.

As always look up to your stuff Andrew, loved the parrallax demo of recent and can't wait to make some dank frogs.

AndrewRayCode commented 3 weeks ago

Thank you for this feedback! The boilerplate code for Shaderfrog 1.0 has a lot of what you're asking for. I haven't added it yet to the second version of the editor.

I also was inspired by your issue to hack together a shadertoy import proof of concept: https://x.com/andrewray/status/1825771064657686588 . This won't get you that far, but might help with some of the boilerplate importing.

Here's some longform background information while I mull over the right way to add boilerplate code.

Brain Dump of Shaderfrog "Standard" Variables

I think it makes sense to at least have a documentation modal or help page that shows the variables/uniforms available in a glsl node. Right now, Shaderfrog Core injects a few uniforms: https://github.com/ShaderFrog/core/blob/bb247b76ad285e2cfcf547da14408331f2a5a704/src/plugins/three/threngine.ts#L716-L718

    time: { value: 0 },
    cameraPosition: { value: new Vector3(1.0) },
    renderResolution: { value: new Vector2(1.0) },

And the Shaderfrog Editor updates those values in the scene at runtime: https://github.com/ShaderFrog/editor/blob/c2a713b6ea6afe5ec4f552e9fe271441f04c4bbb/src/editor-engine-plugins/three/ThreeComponent.tsx#L491-L515

(I just added renderResolution to support the Shadertoy import).

For attributes, and varyings like vPosition, there are two aspects here. First off, if you have a Three.js material in your graph, like the MeshPhysicalMaterial in this graph, then the Three.js shader automatically creates variables like vUv and vPosition which are then available in your fragment shader.

These varyings become available to your individual fragment GLSL nodes because, in the end, all of the GLSL nodes are compiled into one big single GLSL program (which you can view, and live edit, on the Shader -> Fragment/Vertex sub-tabs of the editor). Additionally, if you have a GLSL node, when it's compiled to the final shader all of your variables are "mangled" - aka renamed - to make sure they don't conflict with other GLSL source code in the graph, except I hard code that engine variables names like vUv should not be renamed.

So if you have a Three.js shader in your graph, you get these variables for free. If you don't have a shader in your graph, you need to manually assign those varyings in the vertex shader. You can see an example of that by double clicking on the red vertex node in this graph to see its source code: https://shaderfrog.com/2/editor/clp6gohkq0006parh3jr90ym2

Also, Shaderfrog tries to trick Three.js into passing uniforms to the final RawShaderMaterial, so there are also the matrix uniforms available like modelMatrix, and the attributes also come along with the geometry, like position, regardless of if you have a Three.js material in your graph.

This also applies to Babylon, Playcanvas, and any other engine plugin to Shaderfrog.

Boilerplate in the "hybrid graph" editor

I've been thinking for a while about the right mental model for what type of editor Shaderfrog is. Currently, the intention of Shaderfrog is a kind of social shader remixer and GLSL module composition system, where each node in your graph is a standalone effect/shader, and you can trivially replace and remix nodes together with any other from the online ecosystem. For example, it was trivial to take this shadertoy port by another user and multiply in other shaders from the site to make a new effect. You can also see in these graphs there are several fragment (green) and vertex (red) source code nodes.

In that sense, the main focus of my development has been on these social features, and the ability to promote shaders into composable modules. What you're looking for right now is closer to something a standard code editor offers - where you're editing all of the shader code in one file/editor.

I'm saying this because I'm not sure it makes sense to add full boilerplate code to every new fragment/vertex node in the graph. The fragment/vertex nodes right now are intentionally empty because the social composition nature of the graph means there might be many GLSL nodes.

TL;DR with the above context, I see at least three options:

  1. The initial nodes could have boilerplate, and new users could delete those nodes if they want a fresh graph
  2. There could be an option in the right click menu to add a "boilerplate" code node, vs an empty fragment/vertex node
  3. This could be done with documentation, listing the types of each built in attribute/uniform
  4. Maybe have a more standard "root" node - or repurpose the output node - to include that boilerplate
Bug-Reaper commented 3 weeks ago

Appreciate it man!

I think putting it under a right-click option may be difficult for people to discover organically.

More fond of maybe having some Boilerplate that's commented out or a dedicated button in the UX like ("create new" & "create new with boilerplate") or "insert boilerplate to this shader", etc....


Saw your shadertoy importer thing on X and that looks pretty sweet. Definitely feels like a genius move to help some of the giga-chads from shadertoy take a spin on the frog 🐸.

Bug-Reaper commented 2 weeks ago

Hey @AndrewRayCode I tried to bring over some of my equirectangular shaders and even with new import got pretty bricked out within 30mins of my attempt.

https://shaderfrog.com/2/editor/cm0bq5pla000apa8vjyxmfsiu

I'm still pretty convinced with a boilerplate with more of the normally used varyings etc I could figure it out? I'm so lost on what abstractions are fucking me lol?

I ported most of the stuff I'd pass to a shader-material.

AndrewRayCode commented 2 weeks ago

@Bug-Reaper Ah crap sorry about that - in this case you need to switch the preview object to a plane. I'll improve the auto import feature to do that automatically

Bug-Reaper commented 2 weeks ago

@Bug-Reaper Ah crap sorry about that - in this case you need to switch the preview object to a plane. I'll improve the auto import feature to do that automatically

Hahahahha thanks for the quick reply @AndrewRayCode -- I think you misunderstand my intent.

I want the shader to preview on a sphere. I don't understand why it won't preview on the sphere. If I shove the same frag/vert shader into a Vanilla shader-material I can put it on w/e object I want sphere or otherwise.

That particular shader is by design supposed to be the texture for a sphere (spherical-mapped plane / equirectangular).

This is not a common use-case I'm one of like a few people that have made equirectangular shaders like this (at least on shader-toy lol)

AndrewRayCode commented 2 weeks ago

I think this might be what you're looking for: https://shaderfrog.com/2/editor/cm0cv3rkz000epa8vvjzysigd

The issue may be that a three.js ShaderMaterial automatically includes the proper vertex transformations to set the position on the screen. When importing from Shadertoy, I set the shader to be screen space, which basically locks the plane to the screen, and it doesn't include the camera model/view transformations.

I believe this is working properly - using the same vertex position math that a three.js shader material uses. To your point about boilerplate, if there was better boilerplate variables / easier to find, this would be obvious. Unfortunately right now there are many non-obvious things in the shaderfrog 2.0 UI. Thank you for helping point out the most glaring ones! This vertex code in this shader is also the default vertex code in a new/empty three.js material, which I personally often reference to copy/paste to get the uvs/position varyings easily. I also agree with you that if this were the default, it would be way easier to discover.

The other feature on the roadmap is to toggle the shadertoy import between a screen space style shader (what it is now, locking the plane to the camera by ignoring the camera matricies) and a uv or vertex position based shader, which is what I believe you're looking for with this import.

Also right now you'll need to jump through this same hoop for any future shadertoy imports. It looks like you were already able to navigate switching from uv-based seed to position-based, which is another hoop to jump through.

Bug-Reaper commented 2 weeks ago

Ohhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh @AndrewRayCode okay yea this is on me for not doing the modelviewmatrix magic on the position in the vertex shader lol 😂!

Also maybe different use-cases just commented out.

EX: one shader-toy import and the uv/vertex position code is commented out with notes. Applies to the default boilerplate too.


Strongly think some boilerplate with more stuff (and maybe having to remove some stuff) is better than barebones boilerplate. Even the THREE docs don't cover the THREE flavored GLSL stuff very well so if you're not coming in with that it's very difficult to find your footing.