I’m working on some extensions for OF bindings for Lua scripts in the Pure Data graphical patching programming environment. (That project is Ofelia.)
I’m quite new to all this – good with audio programming but I’m not at all expert with graphics. (Also not especially interested in C, FWIW.)
Ofelia doesn’t ship with any image filters. So after some digging around, it looked like it should be feasible to do ofImage --> draw to ofFbo --> pass fbo to shader --> get back to ofImage (and this could be passed to another fbo/shader).
Why fbo? Why not just bind the image and run the shader? The end goal is to modularize, so that the Pd user can create objects like [of.image] --> [of.brightness] --> [of.plane] and it would do texture mapping internally. (Another user has created a framework, but without shaders.) The brightness shader should be independent of any rotation/translation – so it seems necessary to me to run the shader to a non-displayed frame buffer, and then texture map the resulting frame buffer with rotation/translation.
I’ve been able to write a script that loads an image and draws it through a shader.
Now I’m trying to extend that with the fbo first (not even using the shader yet), but:
-- during setup:
fbo:allocate(image:getWidth(), image:getHeight(), GL_RGBA);
-- during drawing:
fbo:beginFbo();
image:draw(0, 0);
fbo:endFbo();
… and after this, the fbo is blank.
There’s no point in adding the shader until I’m sure the fbo has the data.
Any ideas? I’ll paste the Lua script below (and the entire Pd patch is shown in the screenshot).
hjh
if type(window) ~= "userdata" then;
window = ofWindow();
end;
;
local canvas = ofCanvas(this);
local dir = canvas:getDir() .. "/";
local image = ofImage();
local fbo = ofFbo();
local useFbo = 0;
;
function M.new();
ofWindow.addListener("setup", this);
ofWindow.addListener("draw", this);
ofWindow.addListener("exit", this);
window:setPosition(0, 0);
window:setSize(500, 500);
if ofWindow.exists then;
clock:delay(0);
else;
window:create();
end;
end;
;
function M.free();
window:destroy();
ofWindow.removeListener("setup", this);
ofWindow.removeListener("draw", this);
ofWindow.removeListener("exit", this);
end;
;
function M.setup();
ofSetWindowTitle("fbo1");
ofBackground(255, 255, 255, 255);
image:load(dir .. "../oil.jpg");
fbo:allocate(image:getWidth(), image:getHeight(), GL_RGBA);
M.pln = ofPlanePrimitive();
M.pln:setRows(4);
M.pln:setColumns(4);
M.pln:setWidth(500);
M.pln:setHeight(500);
M.pln:setPosition(ofVec3f(250.0, 250.0, 0.0):vec3());
end;
;
function M.useFbo(f) useFbo = f end;
;
function M.draw();
ofSetColor(255);
fbo:beginFbo();
image:draw(0, 0);
fbo:endFbo();
if(useFbo == 0) then image:bind() else fbo:bind() end;
M.pln:draw();
if(useFbo == 0) then image:unbind() else fbo:unbind() end;
end;
;
function M.exit();
image:clear();
end