Buffers in craft shaders?

@John, in this thread you gave very helpful examples of the format for Craft shaders.

I’ve been able to use them to adapt many existing mesh shaders to the Craft format.

I’m coming up against something I can’t figure out from your examples, though.

I can’t suss out the Craft version of mesh shader buffer calls.

Is there a Craft shader equivalent to mesh:buffer([propertyName])?

Anybody? This is the reference on buffers for mesh shaders:

https://codea.io/reference/Shaders.html#shader

They’re so useful on mesh shaders. It would surprise me if there’s no version of it on Craft shaders.

@John since the topic of Craft shaders kind of obliquely came up again in reference to @ignatz’s shader-based touch-detection system, I thought I might as well ask…

…any chance of getting buffers to work with Craft shaders?

…the completist in me would love to move all the old awesome shader effects into Craft, but without buffers it just can’t be done….

I think this came up another time in a different thread but Craft doesn’t support buffers because we use a less flexible but more efficient vertex steam format (interleaved vs separate streams). The only places you can pack extra data in as it stands are the uv attribute and color attribute. The colors are limited to 1 byte per channel though so it’s not that great. The modern runtime (Carbide) fixes this by giving you access to compute buffers but obviously if you’re running on the legacy runtime you can’t access those. I think there is also a second uv attribute in Craft so you that would give you 4 floats and 4 unorm bytes to work with. What sort of stuff did you normally put inside buffers?

To be honest, when I tried to convert old shader projects to Craft projects, it seemed like most of the really amazing ones used buffers.

But just as an example, here’s a thing comparing a simple animation the old shaders could do that Craft can’t:

Undulate: mesh v Craft.zip (126.7 KB)

It has a toggle in the parameters view to switch between the mesh animation and my attempt to emulate it in Craft.

@UberGoober I have something similar.


viewer.mode=STANDARD

function setup()
    parameter.watch("fps")
    parameter.number("amplitude",1,6,2) 
    parameter.number("speed",1,3,1) 
    parameter.number("wave",1,6,6) 
    assert(OrbitViewer, "Please include Cameras as a dependency")        
    scene = craft.scene()
    scene.ambientColor=color(255)
    v=scene.camera:add(OrbitViewer, vec3(0,0,0),130,0,3000)
    v.rx,v.ry=-45,-20
    grid,s,f,sph=40,.1,90,{}
    for x=grid,-grid,-1 do
        sph[x]={}
        for y=grid,-grid,-1 do
            sph[x][y]=createPlane(vec3(x,y,0))
        end
    end
end

function draw()
    update(DeltaTime)
    scene:draw()
    fps=1//DeltaTime
end

function update(dt)
    scene:update(dt)
    f=f+(s*speed)
    if f>180 then
        f=f-180
    end
    for x=grid,-grid,-1 do
        for y=grid,-grid,-1  do
            sph[x][y].position=vec3(sph[x][y].x,sph[x][y].y,math.sin(math.sqrt((x/wave)^2+(y/wave)^2)-f*speed)*amplitude)
        end
    end
end

function createPlane(p)
    local pt=scene:entity()
    pt.position=p
    pt.model = craft.model.cube(vec3(1.2,.6,1.2))
    pt.material = craft.material(asset.builtin.Materials.Basic)
    pt.material.diffuse=color(math.random(255),math.random(255),math.random(255))
    return pt
end

@dave1707 it’s great, but this it’s not a shader that can then be applied to any different model I choose. For example with mesh you can have shaders that make meshes do an explosion effect and then you can easily apply it to any model you want to see explode.

If I recall correctly one of your projects did a similar thing in Craft, but since you can’t animate values in Craft shaders, you didn’t use a shader at all, you did it by ‘manually’ replacing every single triangle in the original entity’s model with a whole separate entity and model of its own, and then animating those entities individually. Like you have to do in the code you just posted, too.

I don’t know anything about the efficiencies @John was referring to, but it seems at least possible that if you’re making an explosion by animating a thousand different individual entities, as you have to do with Craft, versus making an explosion by applying just one shader to just one entity, as you can do with meshes—it seems possible that the more efficient way is the second way.

Granted this borders on the ridiculous, but could you in theory emulate the power of mesh buffers for use in Craft shaders by generating a different Craft shader for every ‘frame’ you wanted to animate, and then changing the model’s shader every draw() cycle? It’d be wild, but it’d theoretically make it possible to truly update any pre-Craft project to use Craft.

I don’t see how this would be any different than just having a single uniform value driving the animations you want. Multiple shaders don’t give you any extra features. Buffers are just additional per vertex data, which is useful for the kinds of animations you are talking about but not a requirement.

In the undulate example, you could encode the distanceFromCenter attribute into the uv vertex attribute and set that via the model’s uvs giving you exactly the same effect. The main limitation being you couldn’t then use it for texturing, or if you wanted a larger number of per-vertex attributes. In that way mesh buffers are more flexible for sure

I’m not sure what you mean, and I’m at the edge of my technical abilities so I might just be slow.

With the mesh shader you can change the vertex values individually and dynamically at runtime—you just send it the delta time and every vertex animates differently.

With the Craft shader you can’t do that, or at least I don’t think you can.

Are you talking about changing vertices within the shader or in the Lua code? Because mesh shaders and Craft shaders can both do those things and always have. Buffers give you more custom per-vertex data to work with but you can still just modify vertices in the vertex shader using uniforms/properties in both or based on other vertex attributes. Both shaders types are just GLSL shaders, there’s nothing special about them except in how data gets passed in. When I get some time I can show you how to modify your example so that the craft undulation shader works using a spare vertex attribute (like uv2 or something)

@John I realized I may be confusing some terms.

It’s not possible to make the shader store a value that gets updated every draw cycle and then recalculates each vertex’s position based on that? It has to be done with uv2 or something?

The values you are talking about are vertex attributes. Every vertex in your model no matter what it is has per vertex data. It’s up to the programmer to define what that data is. At a minimum you’ll want position data (which we have), but you’ll generally want other things like colours, uvs and stuff. In the original mesh type I added buffers so that you could define extra per-vertex data beyond what is normally available

The shader takes this per-vertex attribute data and transforms it before it gets drawn to the screen. It doesn’t recalculate anything it just passes the data on to the next stage of the shader pipeline. So you can’t use a vertex shader to write back to this data. What you can do with buffers in codea is just send new data to the gpu every frame. Usually when you want stuff to vary each frame you’ll use uniform values (values that are shared for all vertices within the shader). In Codea we call those properties and you can just set them directly, but they don’t vary for each vertex. If you repurpose an existing channel like color or uv/uv2 you can use it in the shader to drive other visible effects like position offsets, colors or textures in different ways

Honestly you might want to look into some books on shader programming to give yourself a better idea of how they work since it’s a little beyond the scope of a forum post. I recommend this free book: https://thebookofshaders.com/

@John I found it!

There’s a term I’ve been looking for: array uniforms.

I knew there was a forum post where we’d discussed this before, and there was a term I couldn’t remember from it:

In this you mention something called array uniforms and you seem to think it’s possible that they could be implemented in Craft shaders.

It seems like they could be used for cool things—are they also not possible for the reasons you mentioned?