openFrameworks icon indicating copy to clipboard operation
openFrameworks copied to clipboard

A dream about fbos summing using += operator

Open dimitre opened this issue 3 years ago • 12 comments

Last night I dreamt about OF, ofFbo had a += operator so you could sum layers like this. In fact this still makes sense to me, so I decided to make this quick PR

fbo += fbo2;

example

#include "ofApp.h"

ofFbo fbo;
ofFbo fbo2;
ofFbo fbo3;

//--------------------------------------------------------------
void ofApp::setup(){
	fbo.allocate(600, 600, GL_RGBA);
	fbo.begin();
	ofClear(0,0);
	ofSetColor(255, 0, 0);
	ofDrawCircle(300, 300, 200);
	fbo.end();
	
	fbo2.allocate(600, 600, GL_RGBA);
	fbo2.begin();
	ofClear(0,0);
	ofSetColor(0, 0, 255);
	ofDrawRectangle(100, 100, 300, 50);
	fbo2.end();

	fbo3.allocate(600, 600, GL_RGBA);
	fbo3.begin();
	ofClear(0,0);
	ofSetColor(0, 255, 0);
	ofDrawRectangle(200, 200, 300, 50);
	fbo3.end();

	fbo += fbo2;
	fbo += fbo3;
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
	fbo.draw(0,0);
}

void ofApp::keyPressed(int key) {

}

Screen Shot 2022-10-06 at 16 23 03

dimitre avatar Oct 06 '22 19:10 dimitre

love this idea. curious what others think? @ofZach @NickHardeman @2bbb

I would definitely consider removing the ofSetColor in the += incase you would want to do that explicitly.

ofTheo avatar Oct 06 '22 22:10 ofTheo

yeah I was in doubt about setcolor, I'll remove it now

dimitre avatar Oct 06 '22 22:10 dimitre

I like the idea of operators. It makes sense using GL_RGBA, but a GL_RGB fbo would just draw right over the other. Not sure if this would be confusing or not. I would also be interested in an equal operator to a color like fbo = ofColor::black that simply begins, clears to color and then ends.

NickHardeman avatar Oct 07 '22 02:10 NickHardeman

It seems like good!

Can we support more general rhs targets like ofImage, ofVideoPlayer, ofVideoGrabber? (or more and more general, structs have draw method...?😊)

Yes, I know, making thing general makes complex. However, I think it would be good if it could be generalized with a good balance.

2bbb avatar Oct 31 '22 03:10 2bbb

one question -- what happens when FBOs are not the same size?

am a fan of the = ofColor approach that @NickHardeman suggested.

ofZach avatar Oct 31 '22 11:10 ofZach

@ofZach it can be drawin in 0,0 coordinate. top left

dimitre avatar Oct 31 '22 12:10 dimitre

I like the ofColor operator too!

dimitre avatar Oct 31 '22 12:10 dimitre

@NickHardeman I think it is OK to just overwrite if there is no transparency or blend mode enabled for the two images. Not an unexpected result.

dimitre avatar Oct 31 '22 12:10 dimitre

This is just an idea.

+= is simple and understandable. But fbo += fbo1 and fbo = fbo + fbo1 are not same. (I don't know there is good implementation for fbo + fbo1) Maybe this is not so important. However, there is a point of concern.

And I think design of iostream is not so cool. (mainly about string formatting and iomanip...) However I think those style is possibility those are better and extendable way to fbo processing.

like below:

fbo << fbo1;
fbo << fbo2 << fbo3;
fbo << ofFboOpStyle::Fill << fbo4;
fbo << ofFboOpStyle::AspectFit << fbo5;
fbo << ofFboOpStyle::Offset(10, 10) << fbo6;

I know those may be over-featured or non-intuitive... As a mere suggestion.

2bbb avatar Nov 01 '22 08:11 2bbb

I really like this one I don't see any downside since += operator is not very obvious to use in objects but makes sense in this fbo case.

dimitre avatar Dec 07 '22 18:12 dimitre

what about fbo *= shader, where fbo is passed through shader, transparently swapping a lazily-allocated buffer?

[edit: of course I'm not specifically advocating the *= operator itself (although it feels not bad) but the principle]

artificiel avatar Feb 19 '23 23:02 artificiel

(posting like this as I'm not sure how to pull another user's branch then add to the PR?)

ofFbo.h

	ofFbo & operator *=(const ofShader & shader) { return pass(shader); }
	ofFbo & pass(const ofShader & shader);
	std::unique_ptr<ofFbo> buffer; // sole overhead if method is unused is unallocated pointer

ofFbo.cpp

ofFbo & ofFbo::pass(const ofShader & shader) {
	
	// lazy  --  perhaps augment settings to make within allocate() if so desired
	if (!buffer) buffer = std::make_unique<ofFbo>();
	
	// conformant  --  if compare is too costly at every frame, hook into allocate to maintain sync
	if (buffer->settings != settings) buffer->allocate(settings);
	
	buffer->begin();
	ofClear(0,0,0,0);
	shader.begin();
	draw(0,0);
	shader.end();
	buffer->end();
	
	// perhaps this could be "texture swapped" with some clever GL code?
	begin();
	buffer->draw(0,0);
	end();
	
	return *this; // to enable things like : flatten_fbo += (layer_fbo *= layer_shader);
}

ofApp.cpp:

    fbo *= shader;

artificiel avatar Mar 08 '23 01:03 artificiel