Codea 1.5 Beta

Interesting - just tried it out. Your shader draws a spline?

This is the GLSL ES spec: http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf

lowp, mediump and highp are precision specifiers. The actual ranges for them are specified at the bottom of page 33 of the spec. The spec calls them “minimum” ranges, but iOS devices tend to stick to those minimums.

For example, a lowp float goes from -2, 2

A lowp integer goes from -256, 256.

It’s much faster to use lowp in calculations than highp.

And - the language is “GLSL Shader language”. No, really. (it’s modeled to be familiar to people used to C/C++) It is optimized to do things the GPU does well (matrix math, vector stuff, and so on) and not have things the GPU doesn’t need (strings, for example).

You may also see HLSL floating around out there - that’s the Microsoft DirectX version. Not identical, but similar enough to mechanically translate between them.

I linked to a quick reference card above - the last 2 pages have a list of functions and so on.

Thanks for the reference, Bortels, and the spec, Simeon. I also found http://www.raywenderlich.com/10862/how-to-create-cool-effects-with-custom-shaders-in-opengl-es-2-0-and-cocos2d-2-x which felt like quite a gentle introduction.

What is meant to happen if you use a shader that refers to a texture but no texture is set? When I had two meshes using the same shader then the one without a texture seemed to get something from the one with the texture. And when I had no texture then it behaved differently to when I had no shader (the shader was the “default” one which I guess ought to do “nothing”).

Do you have any examples using two textures in a shader? It seems like there is a bug that all sampler variables get the mesh.texture texture instead. Unless I’ve missed something? Tried assigning an image element. Maybe would be nice if you could use the texture name directly?

In the editor it would be nice with an imageRef() that shows the image picker dialog, when you need image-element for the texture.

And in reading around I learnt about frame buffers. This looks like a way to store information between runs. Is this possible at the moment? If not, will it be so? This would be fantastic for dynamic shaders.

I know everyone is excited about shaders, but there are a couple of other new features that are also pretty exciting! :slight_smile: One such feature is the ability to read, list, and save tabs in a project. To celebrate, I’ve created a function that, given a URL that points to a file, will create a new tab in the current project with the contents of the downloaded file.

-- ImportURL

-- Usage: importURL([tabname,] url)
function importURL(tabname, url)
    tabname, url = url and tabname, url or tabname
    
    if not tabname then
        tabname = url:sub(#url - url:reverse():find("/", 1) + 2, #url)
        tabname = tabname:sub(1, tabname:find("%.", 1) - 1)
    end
    
    http.request(url, function(data, status, headers)
        if status == 200 then
            saveProjectTab(tabname, data)
            print("Tab '"..tabname.."' created")
        else
            print("Failed to download '"..url.."' to '"..tabname.."'")
        end
    end)
end

I recommend making a project with this as the only file in it (other than main), so that you can include it as a dependency for other projects. Then just call importURL() in your project with the URL of the file you want to download and import as a tab. Here’s an example of downloading the awesome middleclass.lua from kikito’s public github repo:

importURL("https://raw.github.com/kikito/middleclass/master/middleclass.lua")

When complete, a new tab named “middleclass” will be created in your project with the contents of middleclass.lua. You can also specify the desired tab name as an optional first argument if you’d like:

importURL("MiddleClass", "https://raw.github.com/kikito/middleclass/master/middleclass.lua")

One thing to be aware of is that the new tab will not appear until after you exit your project and re-enter it.

.@Simeon: I’m not sure how easy this would be to do, but it might be worth considering to make Codea aware of when saveProjectTab() is called while a program is executing, and when execution ends and flow is returned to the editor, reload all of the tabs.

As a bit of added fun I’ve created another bit of code that will download ImportURL.lua from my github repo, use loadstring() to inject the importURL function into the global namespace, and then call importURL to actually download the ImportURL.lua file and create a tab for it in your project. Put this in your setup() function:


local url = "https://raw.github.com/apendley/CodeaMisc/master/ImportURL.lua"

http.request(url, function(data, status, headers)
    if status == 200 then
        assert(loadstring(data))()
        importURL(url)
    end
end)

After you run the program, exit, and re-enter the project, you will now have an ImportURL tab with the importURL function! :slight_smile:

About editing shaders again :). I think it would be nice if when editing a shader used in a program, to get the option to start the lua program from the shader view. When modifying a shader you move back and forth a lot between shader editor and lua editor just to press the play button for the lua code.

Yes, I was thinking that too. Especially when the shader has parameters then the shader preview is pretty useless. In those circumstances I’d quite like to be able to turn off the automatic version and be able to go quickly to a particular project.

Did we enable file io and os.pwd? I’m about to leave, so can’t test. Thinking of making a time-lapse camera thing, was trying to figure out how to save the images. (I figure I’ll have to export them and make them into a movie on the pc…)

The tab stuff looks exciting, in a very utility kind of way, but I’m into that… What happens if I save binary data into a tab?

io and os.getenv are there. I’ve been able to create, write to, and read from files in Codea’s Documents, Library/Caches, and tmp folders by getting Codea’s root location using os.getenv(‘HOME’). I have not yet figured out how (or it’s not possible) to create directories, or list the files in a directory.

I’m willing to bet saving binary data into a tab will achieve nothing good, since Codea treats all tabs as .lua files.

How do I pass an array to a shader? I can declare:

uniform vec2 pts[4];

and write

m.shader.pts = {vec2(...)}

but although nothing complains, it doesn’t seem to work.

Ok - I had a big post, just deleted it all, because I didn’t understand image(data). I had thought it was image.data, readable and writable. No such luck.

How do I get the raw data from an image? That is, without doing it pixel by pixel with get.

I want to do “img = image(CAMERA)” then save that off, or post it.

I’m also getting back some funky numbers from CurrentTouch.tapCount. Like millions.

More, just to show the test rig:



-- timelapse

-- Use this function to perform your initial setup
function setup()
    print("Hello World!")
    home = os.getenv("HOME") .. "/Documents/timelapse.codea"
    print(home)
    cameraSource(CAMERA_FRONT)
    ts = CurrentTouch.state
    print("starting state is " .. ts)
    fresh = true
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    sprite(CAMERA, WIDTH/2, HEIGHT/2)
    -- sprite(CAMERA, WIDTH/2, HEIGHT/2, 768/4, 1024/4)
    if ((CurrentTouch.state ~= ts) and fresh)then
        fresh = false
        im = image(768/4, 1024/4)
        print("click")
        setContext(im)
        background(228, 224, 23, 255)
        sprite(CAMERA, WIDTH/2, HEIGHT/2, 768/4, 1024/4)
        saveImage("Documents:timelapse", im)
        setContext()
        --print(string.len(im.data))
    end

end

The idea here was to try to save the camera image to the spritepack - but what I get is a yellow blank image. Yellow is good - that’s the background I set - but no sprite image. I’m guessing maybe the context is always the screen for the camera? (I figured in the absence of being able to get image data, I could save to the spritepack, then grab from that with io.*, but no luck. I’m making a drive to Vegas end of the month - my idea is to put the ipad in the passenger seat, and take an image every 30 seconds or so, then stitch them together to make a movie.)

.@Bortels you should be able to do:

local myImage = image(CAMERA)
saveImage( "Documents:MyImage", myImage )

```

.@Andrew_Stacey I am unsure if we have support for uniform arrays and structs in shaders. Arrays might be possible, structs unlikely.

You can however pass in arbitrary data per-vertex from your mesh. Meshes now support attribute buffers (which can be modified in-place, unlike mesh.vertices for example).

Buffers require that an attribute array be declared in the mesh’s vertex shader — otherwise the buffer won’t exist at runtime and you’ll get nil.

(I may need @John to clarify the below — I haven’t used buffers much.)

-- Get a float buffer
myBuffer = myMesh:buffer("someBuffer")

-- Set all elements to 1
myBuffer:set(1)

-- Set index 5 to 0.5
myBuffer[5] = 0.5

```


Then in your vertex shader you get the contents of myBuffer passed in per-vertex:

~~~
//This is populated with the buffer value for each vertex
attribute float someBuffer;

//Optional, for sending interpolated output to fragment shader
varying lowp float vSomeBuffer;

void main()
....
~~~

Hi @toadkick, you are right - creating tabs is NEATO! I played with that code you wrote and managed to overwrite the Main tab instantly, although as you noted the other tabs don’t appear until you close reopen.

Hi again, couldn’t help but mash together @toadkick and @ruilov’s code to make a gitHub project getter, just save this as a tab and include it as a dependency. Means I don’t need to plug in my iPad to get updated code…

-- ImportURL

-- Usage: importURL([tabname,] url)
function importURL(tabname, url)
    tabname, url = url and tabname, url or tabname

    if not tabname then
        tabname = url:sub(#url - url:reverse():find("/", 1) + 2, #url)
        tabname = tabname:sub(1, tabname:find("%.", 1) - 1)
    end

    http.request(url, function(data, status, headers)
        if status == 200 then
            saveProjectTab(tabname, data)
            print("Tab '"..tabname.."' created")
        else
            print("Failed to download '"..url.."' to '"..tabname.."'")
        end
    end)
end

---
-- getGit
-- This program uses a URL to find all the bits of a GitHub repo and replicate it.
-- usage: getGit("https://github.com/fredbogg/ABCplayerCodea")
function getGit(URLstring)
    
    print("Close this project and reopen it to see the new tabs. It should run straight away.")
    print("The Main tab will have moved to be first, and be aware that tab orders could change due to download times.")
    print("Credit to Rui Viana (ruilov) and toadkick for code and inspiration.")
    
    -- we change the URL a bit and assume the master branch is correct
    URL = string.sub(URLstring,1,8) .. "raw." .. string.sub(URLstring,9) .. "/master/"
    
    -- get the info.plist file for its list of tabs
    http.request(URL .. "Info.plist", httpSuccess, httpFail)
    
    -- hopefully go to httpSuccess()
end

function httpSuccess(string)
    -- create the tabs one by one
    contents = string
    buffers = {}
    
    -- code from Rui Viana's GitHub client, https://github.com/ruilov/GitClient-Release 
---
    -- find the buffer order
    local bufferKey = "<key>Buffer Order</key>"
    local idx = contents:find(bufferKey)
    assert(idx~=nil,"Could not find buffer order.")
    contents = contents:sub(idx)
    
    -- find the end of the buffer order
    local idx2 = contents:find("</array>")
    assert(idx2~=nil,"Could not find the end of the buffer order.")
    contents = contents:sub(1,idx2)
    
    local buffers = {}
    for buff in contents:gmatch("<string>([%a%s%d]+)</string>") do
        table.insert(buffers,buff..".lua")
    end
---
-- end Rui's code

    -- make buffers
    for i = 1, #buffers do
        importURL(URL .. buffers[i])
    end
end

function httpFail(error)
    print("some kinda http problem")
    print(error)
end

Edit: fixed comment

.@Simeon, the keyboard goes almost blank if you drag while holding one of the cut copy or paste buttons following text selection.

.@Fred Great idea. I’m uploading a build that no longer requires you to close and re-open the project to see the new tabs created by saveProjectTab.

.@Everyone else — I’ve tried to fix the specific issues brought up in this thread. Please let me know if anything you’ve reported is still broken.