Thanks! I’m going to throw a few more at you.
Corona’s full shader program applies any mask on your behalf.
Okay, cool. I assume it’s doing the same beforehand to the vertices coming through the vertex shader? If so, is it possible to recover the pre-transformed position and the matrix, on the GLSL side?
Actually, some of those might be handy as read-only properties on the Lua side, as well, which could later be fed back in as uniforms. I’m thinking, say, of certain motion blur effects that use both the previous and current transform.
What sort of vertex effects are you trying to achieve?
Uff, let’s see if I can even recall everything.
First off, the original use case:
This was a Tron-style effect, but with curvature, thickness, height, etc. These were Hermite curves, as far as I can recall. Since interpolating the curve (and attributes) requires neighbor information in the vertex shader, most of this state got put (crammed!) into a matrix4 array. Then, some stock mesh (in Corona, I think this would be some reasonably tessellated square polygon) gets instanced, the previous, current, and next states are looked up via a per-instance index, and each of the instance’s vertices are transformed.
That said, in 2D I imagine the bandwidth concerns will be far more sane. In which case, all the state could be loaded into three matrix4 uniforms and the instance index becomes a non-issue.
A couple more…
Would it be possible to provide setter functions for kernel parameters? Along the lines of, say:
kernel.vertexData = { { name = "\_brightness", -- Name of data in shader default = 0, min = 0, max = 1, index = 0 }, setters = { -- The display object is provided to store / lookup state, etc. brightness = function(effect, value, object) effect.\_brightness = value \* 1.01 end } } -- ... fill.effect.brightness = .3 -- set brightness to .3 \* 1.01 fill.effect.\_brightness = .3 -- set directly
I can think of a few motivations.
The first is just as convenience. For instance, the shader itself might want a pre-computed cosine or sine, but it would be more intuitive to provide an “angle” parameter in the documented interface.
Building on that same example, it would allow setting a couple fields at once, say:
kernel.vertexData = { { name = "\_cosa", default = 1, min = -1, max = 1, index = 0 }, { name = "\_sina", default = 0, min = -1, max = 1, index = 1 }, setters = { angle = function(effect, value, object) value = math.rad(value) effect.\_cosa = math.cos(value) effect.\_sina = math.cos(value) end } -- ... effect.angle = 30 -- set both \_cosa and \_sina
Finally, it can hide away tricks used to cram more data together when parameters are a premium:
kernel.vertexData = { { name = "\_xy", default = 0, min = 0, max = 1024, index = 0 }, -- mediump guarantees integers at least in range [-2^10, +2^10], floats -- slightly wider; two values in [0, 1) can be packed together, then -- later extracted in the shader setters = { x = function(effect, value, object) local y = object.\_y or 0 object.\_x = x -- keep local copy effect.\_xy = floor(x \* 1024) + y end, y = function(effect, value, object) local x = object.\_x or 0 object.\_y = y -- keep local copy effect.\_xy = floor(x \* 1024) + y end } -- ... effect.x = .4 -- updates x part, then repacks as \_xy
Sorry for the novel!