Does Codea 4 support mesh:buffer("position")?

In Codea 3.x we can access the a mesh’s attributes using buffer, just like below:

-- Accessing a built-in buffer
------------------------------
-- Create a mesh
myMesh = mesh()

-- Access its position buffer
posBuffer = myMesh:buffer("position")

-- Resize the buffer
posBuffer:resize(30)

-- Add some random vertices
for i = 1,30 do
    posBuffer[i] = vec2( math.random(-50,50),
                         math.random(-50,50) )
end
                   
-- Set all vertex colors to white
myMesh:setColors(255,255,255,255)

-- Draw the mesh
myMesh:draw()

Another example:

-- Accessing a shader buffer
------------------------
-- Create a mesh
myMesh = mesh()

-- Assign a shader to myMesh
--  This shader has an attribute named 'myAttribute'
myMesh.shader = shader(asset.documents.MyShader)

-- Fetch the attribute array
myAttrBuffer = myMesh:buffer("myAttribute")

-- Resize our buffer 
myAttrBuffer:resize(30)

-- Add some random numbers
for i = 1,30 do
    myAttrBuffer[i] = math.random(-50,50)
end

-- The shader will now use this data
--  when myMesh is drawn

In Codea 4, we get the powerful compute shader, It relies heavily on the use of buffer, but I found in Codea 4, the mesh’s method buffer() is nil.

Is there another way to do the same thing? thanks.

i think that’s what this code is doing here -

-- Create a reusable shader chunk for the instances buffer that looks like this in GLSL:
    -- struct Instances 
    -- {
    --    vec4 position; // (x, y, vx, vy) position and velocity
    -- };
    instancesChunk = shader.chunk()
        :buffer{"Instance", "instances", access = "readwrite"}
            :vec4("position")
        :done()
    

@skar Thanks. That code looks like the glsl code in shader, it equals below:

struct Instance
{
    vec4 position;
};

layout(std430, binding = BUFFER0 ) buffer  Pos
{
    Instance instances[ ]; 
}; 

//BUFFER_RW(instances, Instance, BUFFER0);

What I am looking for is the lua code in Codea, in Codea 3.x we have them, I do not if it is supported in 4.x.

I haven’t added support for custom vertex attributes (Codea calls them mesh buffers). I could probably add it though

@John Please add this if possible, so that we can define the compute shader buffer in Codea directly to mesh’s vertex buffer and normals buffer, let the compute shader modify the vertices and normals in the vertex shader directly with these buffers. I wonder if this assumption is correct. Thank you.

The code like below:

computeShader = shader.compute(
[[
-- computer shader code here
]]

function setup()
    m = mesh.box(vec3(1,1,1), vec3(6,6,6))
    meshPosBuffer = m:buffer("position")

    computeShader:setBuffer("meshPosBuffer", meshPosBuffer, shader.readwrite)
end

function draw()
    local wx = computeShader:workgroupSize()
    computeShader:dispatch(meshPosBuffer.size/wx, 1, 1)

    m:draw()
end

I’ve managed to get compute shaders working on meshes. This is a little bit tricky since there are all sorts of caveats related to struct alignment. Once I added the correct padding (vec3’s don’t align correctly) I managed to read and write mesh vertices directly in a compute shader

I’ll also look into the ability to copy these buffers and swap them out, allowing for double-buffered GPU simulations involving these things. Right now there is no way for me to read these buffers back onto the CPU, so printing out the values from the mesh object wont work

Just remember that I’m doing a lot of work to clean up and simplify the GPU stuff here but at the end of the day these are very close to the hardware and will probably be very easy to crash when used incorrectly

The attached code won’t work on the current version of the Codea beta, but it will in the next one, once the fixes are applied:

-- Modern

-- Use this function to perform your initial setup
function setup()
    scn = scene.default3d()
    scn.camera:add(camera.rigs.orbit)
    
    -- Just a regular ol' sphere
    scn:entity("sphere"):add(mesh.icoSphere(1, 5))

    -- Get the mesh vertex buffer
    vb = scn.sphere.mesh.vertexBuffer
    
    -- This is based on the internal mesh vertex format (which has correct padding)
    -- this will be cleaned up a bit so mesh buffers can be bound automatically here
    comp = shader.builder()
    :buffer{"MeshVertex", "vertices"}
        :vec3("position")
        :float("padding0")
        :vec3("normal")
        :float("padding1")
        :vec4("tangent")
        :vec2("uv0")    
        :vec2("uv1")
        :uint("color")
        :float("padding3")
        :float("padding4")
        :float("padding5")
    :done()
    :uint{"vertexCount"}
    :threads(64, 1, 1)
    :include("codea/noise/noise.glsl")
    :compute
    [[
        // Ensure vertex index is within bounds
        uint i = gl_GlobalInvocationID.x;        
        if (i < vertexCount)
        {
            // Play with some noise for the mesh
            vec3 p = normalize(vertices[i].position);
            float n = Cellular3D(p + u_time.x);
            vertices[i].position = vertices[i].normal * (1 + n);
        }
    ]]
    :build()
    
    comp:setBuffer("verticesBuffer", vb, shader.readwrite)
    comp.vertexCount = vb.size
    
    scene.main = scn
end

function update(dt)
    comp:dispatch(vb.size / 64, 1, 1)
end

@John Very valuable work! Looking forward to the next release!

I have recently been learning how to understand compute shader and am trying to visualize some of the related concepts in Codea, such as local work items(another name: thread), local workgroups, global workgroups, and their dimensions and so on. I ran into some problems that confused me, and while it was normal for me to draw local workgroups, the global workgroups would flicker. When more than one instance is drawn in 3-d, a perspective error occurs, such that a later instance obscures a previous one.

I’m not sure if it’s my code or the version, but I’m constantly debugging the code.

GPUComputeModel.zip (4.2 KB)

Btw. A surprise discovery: found that our new forum can support big size picture! very nice!

special perspective

Flash

Changing the dispatch to VisualWorkGroup:dispatch(1,1,1) fixes the flickering for me. Basically your local workgroup size is multiplied by the number of dispatches to get the total number of threads. The global invocation index will give you the logical thread location within the entire workgroup, so if you have a local size of 2,2,2 and dispatch with 2,2,2 you end up with 4,4,4 threads in total (64)

The rendering issue you are getting is caused by the shader being translucent. This is the default for a shader that hasn’t got any settings (i.e. shader(vertexSource, fragmentSource). I’ll be adding some extra control over editing shader passes after creating them, someting like this:

    -- set this pass up for opaque rendering
    local pass = instancing:pass(1)
    pass.renderQueue = OPAQUE
    pass.blendMode = DISABLED
    pass.depthWrite = DEPTH_WRITE_ENABLED
    pass.depthFunc = DEPTH_FUNC_LESS_EQUAL

If you want to combine scenes with custom drawing commands (like instanced meshes), try this:

function scn:entity("customDrawing"):draw()
    myMesh:draw(instanceCount)
end

This also applies entity tranformations, handles active state, etc

@John Thanks a lot for your suggestion. Following your tips, I modified the drawing shader, added options, and solved the problem of perspective errors. The flicker problem was then resolved by modifying the index value settings in compute shader, and the entire global workgroup is now displayed as normal. I’m going to set each local workgroup to a different color next, and I’m continuing to work on index calculations.

The global workgroups

The latter command shows an error in the Codea editor, I do not know how modify it:

function scn:entity("customDrawing"):draw()
    myMesh:draw(instanceCount)
end

GPUComputeModelV2.zip (8.1 KB)

Found a simple way to set the color of the same local workgroup.

In this case, the size of local workgroup is (2,2,2), the below code;

    NUM_THREADS(2, 2, 2)

The num of local workgroups in one global workgroup is (5,6,7), the below line:

    VisualColorWorkGroup:dispatch(5,6,7)

GPUComputeModelV3.zip (9.0 KB)

Compute shader show

1 Like

Hmm, must have got the syntax wrong. Basically you just add a draw function to an entity, which will get called automatically when the scene is drawing, which will be handled properly vs a raw draw call outside of it