I’ve got a very simple app built in oF that I’m being driven crazy by.
I’m drawing two very simple scenes to two displays, one with a GUI to control the output of a shader which I need to be displayed on both hence the FBO. I thought that this would be easy but apparently I was mistaken. I have added a small circle to the center of each display to test how the variables for colour and radius are passed between the displays.
main.cpp
<code>#include "ofMain.h"
#include "ofAppGLFWWindow.h"
//========================================================================
#ifdef OF_TARGET_OPENGLES
ofGLESWindowSettings settings;
settings.glesVersion = 2;
ofGLFWWindowSettings settings;
settings.setGLVersion(3, 2);
settings.setSize(1920, 1080); // native gui display
settings.windowMode = OF_FULLSCREEN;
settings.setPosition({1920, 0});
settings.resizable = false;
auto mainWindow = ofCreateWindow(settings);
settings.setSize(1280, 800); // native gui display
settings.windowMode = OF_WINDOW;
settings.setPosition({0, 0});
settings.resizable = false;
auto guiWindow = ofCreateWindow(settings);
guiWindow->setVerticalSync(false);
auto mainApp = std::make_shared<ofApp>();
// Add separate draw listeners for each window
ofAddListener(mainWindow->events().draw, mainApp.get(), &ofApp::drawMainWindow);
ofAddListener(guiWindow->events().draw, mainApp.get(), &ofApp::drawGuiWindow);
<code>#include "ofMain.h"
#include "ofApp.h"
#include "ofAppGLFWWindow.h"
//========================================================================
int main()
{
#ifdef OF_TARGET_OPENGLES
ofGLESWindowSettings settings;
settings.glesVersion = 2;
#else
ofGLFWWindowSettings settings;
settings.setGLVersion(3, 2);
#endif
settings.setSize(1920, 1080); // native gui display
settings.windowMode = OF_FULLSCREEN;
settings.setPosition({1920, 0});
settings.resizable = false;
auto mainWindow = ofCreateWindow(settings);
settings.setSize(1280, 800); // native gui display
settings.windowMode = OF_WINDOW;
settings.setPosition({0, 0});
settings.resizable = false;
auto guiWindow = ofCreateWindow(settings);
guiWindow->setVerticalSync(false);
auto mainApp = std::make_shared<ofApp>();
mainApp->setupGui();
// Add separate draw listeners for each window
ofAddListener(mainWindow->events().draw, mainApp.get(), &ofApp::drawMainWindow);
ofAddListener(guiWindow->events().draw, mainApp.get(), &ofApp::drawGuiWindow);
ofRunApp(mainApp);
ofRunMainLoop();
}
</code>
#include "ofMain.h"
#include "ofApp.h"
#include "ofAppGLFWWindow.h"
//========================================================================
int main()
{
#ifdef OF_TARGET_OPENGLES
ofGLESWindowSettings settings;
settings.glesVersion = 2;
#else
ofGLFWWindowSettings settings;
settings.setGLVersion(3, 2);
#endif
settings.setSize(1920, 1080); // native gui display
settings.windowMode = OF_FULLSCREEN;
settings.setPosition({1920, 0});
settings.resizable = false;
auto mainWindow = ofCreateWindow(settings);
settings.setSize(1280, 800); // native gui display
settings.windowMode = OF_WINDOW;
settings.setPosition({0, 0});
settings.resizable = false;
auto guiWindow = ofCreateWindow(settings);
guiWindow->setVerticalSync(false);
auto mainApp = std::make_shared<ofApp>();
mainApp->setupGui();
// Add separate draw listeners for each window
ofAddListener(mainWindow->events().draw, mainApp.get(), &ofApp::drawMainWindow);
ofAddListener(guiWindow->events().draw, mainApp.get(), &ofApp::drawGuiWindow);
ofRunApp(mainApp);
ofRunMainLoop();
}
ofApp.h
class ofApp : public ofBaseApp
void drawMainWindow(ofEventArgs &args); // Add this function
void drawGuiWindow(ofEventArgs &args); // Add this function
void keyPressed(int key) override;
void keyReleased(int key) override;
void mouseMoved(int x, int y) override;
void mouseDragged(int x, int y, int button) override;
void mousePressed(int x, int y, int button) override;
void mouseReleased(int x, int y, int button) override;
void mouseScrolled(int x, int y, float scrollX, float scrollY) override;
void mouseEntered(int x, int y) override;
void mouseExited(int x, int y) override;
void windowResized(int w, int h) override;
void dragEvent(ofDragInfo dragInfo) override;
void gotMessage(ofMessage msg) override;
ofParameterGroup parameters;
ofParameter<float> radius;
ofParameter<ofColor> color;
ofParameter<float> xValue;
ofParameter<float> yValue;
void saveFboToImage(const std::string &filename);
<code>#pragma once
#include "ofMain.h"
#include "ofxGui.h"
#include "ofImage.h"
class ofApp : public ofBaseApp
{
public:
void setup() override;
void setupGui();
void update() override;
void draw() override;
void drawMainWindow(ofEventArgs &args); // Add this function
void drawGuiWindow(ofEventArgs &args); // Add this function
void exit() override;
void keyPressed(int key) override;
void keyReleased(int key) override;
void mouseMoved(int x, int y) override;
void mouseDragged(int x, int y, int button) override;
void mousePressed(int x, int y, int button) override;
void mouseReleased(int x, int y, int button) override;
void mouseScrolled(int x, int y, float scrollX, float scrollY) override;
void mouseEntered(int x, int y) override;
void mouseExited(int x, int y) override;
void windowResized(int w, int h) override;
void dragEvent(ofDragInfo dragInfo) override;
void gotMessage(ofMessage msg) override;
void drawFbo();
ofShader shader;
ofFbo fbo;
ofParameterGroup parameters;
ofParameter<float> radius;
ofParameter<ofColor> color;
ofParameter<float> xValue;
ofParameter<float> yValue;
ofxPanel gui;
void saveFboToImage(const std::string &filename);
};
</code>
#pragma once
#include "ofMain.h"
#include "ofxGui.h"
#include "ofImage.h"
class ofApp : public ofBaseApp
{
public:
void setup() override;
void setupGui();
void update() override;
void draw() override;
void drawMainWindow(ofEventArgs &args); // Add this function
void drawGuiWindow(ofEventArgs &args); // Add this function
void exit() override;
void keyPressed(int key) override;
void keyReleased(int key) override;
void mouseMoved(int x, int y) override;
void mouseDragged(int x, int y, int button) override;
void mousePressed(int x, int y, int button) override;
void mouseReleased(int x, int y, int button) override;
void mouseScrolled(int x, int y, float scrollX, float scrollY) override;
void mouseEntered(int x, int y) override;
void mouseExited(int x, int y) override;
void windowResized(int w, int h) override;
void dragEvent(ofDragInfo dragInfo) override;
void gotMessage(ofMessage msg) override;
void drawFbo();
ofShader shader;
ofFbo fbo;
ofParameterGroup parameters;
ofParameter<float> radius;
ofParameter<ofColor> color;
ofParameter<float> xValue;
ofParameter<float> yValue;
ofxPanel gui;
void saveFboToImage(const std::string &filename);
};
ofApp.cpp
//--------------------------------------------------------------
ofSetCircleResolution(200);
shader.load("shader.vert", "shader.frag");
fbo.allocate(1920, 1080, GL_RGB);
//--------------------------------------------------------------
parameters.setName("parameters");
parameters.add(radius.set("radius", 50, 1, 100));
parameters.add(color.set("color", 100, ofColor(0, 0), 255));
parameters.add(xValue.set("xValue", 0.5, 0.0, 1.0));
parameters.add(yValue.set("yValue", 0.5, 0.0, 1.0));
//--------------------------------------------------------------
//--------------------------------------------------------------
ofClear(255, 255, 255, 0);
shader.setUniform1f("xValue", xValue);
shader.setUniform1f("yValue", yValue);
ofDrawRectangle(0, 0, 1920, 1080);
// saveFboToImage("updated_fbo.png"); // tested and working
//--------------------------------------------------------------
//--------------------------------------------------------------
void ofApp::drawGuiWindow(ofEventArgs &args)
ofBackground(ofColor::red);
fbo.draw(10, 0, ofGetWidth(), ofGetHeight()); // Draw the FBO on the GUI window
ofSetCircleResolution(200); // Apply circle resolution
ofDrawCircle(ofGetWidth() / 2, ofGetHeight() / 2, radius);
ofDrawBitmapString(std::to_string(ofGetWidth()) + " x " + std::to_string(ofGetHeight()), ofGetWidth() - 100, 20);
//--------------------------------------------------------------
void ofApp::drawMainWindow(ofEventArgs &args)
ofBackground(ofColor::red);
fbo.draw(10, 0, ofGetWidth(), ofGetHeight()); // Draw the FBO on the main window
// Draw additional graphics (the circle and frame rate text)
ofSetCircleResolution(200); // Apply circle resolution
ofDrawCircle(ofGetWidth() / 2, ofGetHeight() / 2, radius);
ofDrawBitmapString(std::to_string(ofGetWidth()) + " x " + std::to_string(ofGetHeight()), ofGetWidth() - 100, 20);
ofDrawBitmapString(ofGetFrameRate(), 10, 20);
//--------------------------------------------------------------
//--------------------------------------------------------------
void ofApp::keyPressed(int key)
//--------------------------------------------------------------
void ofApp::keyReleased(int key)
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y)
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button)
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button)
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button)
//--------------------------------------------------------------
void ofApp::mouseScrolled(int x, int y, float scrollX, float scrollY)
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y)
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y)
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h)
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg)
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo)
//--------------------------------------------------------------
void ofApp::saveFboToImage(const std::string &filename)
fbo.readToPixels(pixels);
image.setFromPixels(pixels);
<code>#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup()
{
ofSetFrameRate(60);
ofSetCircleResolution(200);
shader.load("shader.vert", "shader.frag");
fbo.allocate(1920, 1080, GL_RGB);
}
//--------------------------------------------------------------
void ofApp::setupGui()
{
parameters.setName("parameters");
parameters.add(radius.set("radius", 50, 1, 100));
parameters.add(color.set("color", 100, ofColor(0, 0), 255));
parameters.add(xValue.set("xValue", 0.5, 0.0, 1.0));
parameters.add(yValue.set("yValue", 0.5, 0.0, 1.0));
gui.setup(parameters);
}
//--------------------------------------------------------------
void ofApp::update()
{
//
}
//--------------------------------------------------------------
void ofApp::drawFbo()
{
fbo.begin();
ofClear(255, 255, 255, 0);
shader.begin();
shader.setUniform1f("xValue", xValue);
shader.setUniform1f("yValue", yValue);
ofDrawRectangle(0, 0, 1920, 1080);
shader.end();
fbo.end();
// saveFboToImage("updated_fbo.png"); // tested and working
}
//--------------------------------------------------------------
void ofApp::draw()
{
drawFbo();
}
//--------------------------------------------------------------
void ofApp::drawGuiWindow(ofEventArgs &args)
{
ofBackground(ofColor::red);
ofSetColor(255);
fbo.draw(10, 0, ofGetWidth(), ofGetHeight()); // Draw the FBO on the GUI window
ofSetColor(color);
ofSetCircleResolution(200); // Apply circle resolution
ofDrawCircle(ofGetWidth() / 2, ofGetHeight() / 2, radius);
ofSetColor(0);
gui.draw();
ofSetColor(255);
ofDrawBitmapString(std::to_string(ofGetWidth()) + " x " + std::to_string(ofGetHeight()), ofGetWidth() - 100, 20);
}
//--------------------------------------------------------------
void ofApp::drawMainWindow(ofEventArgs &args)
{
ofBackground(ofColor::red);
ofSetColor(255);
fbo.draw(10, 0, ofGetWidth(), ofGetHeight()); // Draw the FBO on the main window
// Draw additional graphics (the circle and frame rate text)
ofSetColor(color);
ofSetCircleResolution(200); // Apply circle resolution
ofDrawCircle(ofGetWidth() / 2, ofGetHeight() / 2, radius);
ofSetColor(255);
ofDrawBitmapString(std::to_string(ofGetWidth()) + " x " + std::to_string(ofGetHeight()), ofGetWidth() - 100, 20);
ofDrawBitmapString(ofGetFrameRate(), 10, 20);
}
//--------------------------------------------------------------
void ofApp::exit()
{
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key)
{
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key)
{
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y)
{
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button)
{
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button)
{
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button)
{
}
//--------------------------------------------------------------
void ofApp::mouseScrolled(int x, int y, float scrollX, float scrollY)
{
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y)
{
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y)
{
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h)
{
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg)
{
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo)
{
}
//--------------------------------------------------------------
void ofApp::saveFboToImage(const std::string &filename)
{
ofPixels pixels;
fbo.readToPixels(pixels);
ofImage image;
image.setFromPixels(pixels);
image.save(filename);
}
</code>
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup()
{
ofSetFrameRate(60);
ofSetCircleResolution(200);
shader.load("shader.vert", "shader.frag");
fbo.allocate(1920, 1080, GL_RGB);
}
//--------------------------------------------------------------
void ofApp::setupGui()
{
parameters.setName("parameters");
parameters.add(radius.set("radius", 50, 1, 100));
parameters.add(color.set("color", 100, ofColor(0, 0), 255));
parameters.add(xValue.set("xValue", 0.5, 0.0, 1.0));
parameters.add(yValue.set("yValue", 0.5, 0.0, 1.0));
gui.setup(parameters);
}
//--------------------------------------------------------------
void ofApp::update()
{
//
}
//--------------------------------------------------------------
void ofApp::drawFbo()
{
fbo.begin();
ofClear(255, 255, 255, 0);
shader.begin();
shader.setUniform1f("xValue", xValue);
shader.setUniform1f("yValue", yValue);
ofDrawRectangle(0, 0, 1920, 1080);
shader.end();
fbo.end();
// saveFboToImage("updated_fbo.png"); // tested and working
}
//--------------------------------------------------------------
void ofApp::draw()
{
drawFbo();
}
//--------------------------------------------------------------
void ofApp::drawGuiWindow(ofEventArgs &args)
{
ofBackground(ofColor::red);
ofSetColor(255);
fbo.draw(10, 0, ofGetWidth(), ofGetHeight()); // Draw the FBO on the GUI window
ofSetColor(color);
ofSetCircleResolution(200); // Apply circle resolution
ofDrawCircle(ofGetWidth() / 2, ofGetHeight() / 2, radius);
ofSetColor(0);
gui.draw();
ofSetColor(255);
ofDrawBitmapString(std::to_string(ofGetWidth()) + " x " + std::to_string(ofGetHeight()), ofGetWidth() - 100, 20);
}
//--------------------------------------------------------------
void ofApp::drawMainWindow(ofEventArgs &args)
{
ofBackground(ofColor::red);
ofSetColor(255);
fbo.draw(10, 0, ofGetWidth(), ofGetHeight()); // Draw the FBO on the main window
// Draw additional graphics (the circle and frame rate text)
ofSetColor(color);
ofSetCircleResolution(200); // Apply circle resolution
ofDrawCircle(ofGetWidth() / 2, ofGetHeight() / 2, radius);
ofSetColor(255);
ofDrawBitmapString(std::to_string(ofGetWidth()) + " x " + std::to_string(ofGetHeight()), ofGetWidth() - 100, 20);
ofDrawBitmapString(ofGetFrameRate(), 10, 20);
}
//--------------------------------------------------------------
void ofApp::exit()
{
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key)
{
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key)
{
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y)
{
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button)
{
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button)
{
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button)
{
}
//--------------------------------------------------------------
void ofApp::mouseScrolled(int x, int y, float scrollX, float scrollY)
{
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y)
{
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y)
{
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h)
{
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg)
{
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo)
{
}
//--------------------------------------------------------------
void ofApp::saveFboToImage(const std::string &filename)
{
ofPixels pixels;
fbo.readToPixels(pixels);
ofImage image;
image.setFromPixels(pixels);
image.save(filename);
}
shader.frag
<code>OF_GLSL_SHADER_HEADER
// Use the texture coordinates to compute the gradient
float r = vTexCoord.x * xValue;
float g = vTexCoord.y * yValue;
outputColor = vec4(r += xValue, g += yValue, b, a);
<code>OF_GLSL_SHADER_HEADER
uniform float xValue;
uniform float yValue;
in vec2 vTexCoord;
out vec4 outputColor;
void main()
{
// Use the texture coordinates to compute the gradient
float r = vTexCoord.x * xValue;
float g = vTexCoord.y * yValue;
float b = 1.0;
float a = 1.0;
outputColor = vec4(r += xValue, g += yValue, b, a);
}
</code>
OF_GLSL_SHADER_HEADER
uniform float xValue;
uniform float yValue;
in vec2 vTexCoord;
out vec4 outputColor;
void main()
{
// Use the texture coordinates to compute the gradient
float r = vTexCoord.x * xValue;
float g = vTexCoord.y * yValue;
float b = 1.0;
float a = 1.0;
outputColor = vec4(r += xValue, g += yValue, b, a);
}
shader.vert
<code>OF_GLSL_SHADER_HEADER
uniform mat4 modelViewProjectionMatrix;
gl_Position = modelViewProjectionMatrix * position;
<code>OF_GLSL_SHADER_HEADER
uniform mat4 modelViewProjectionMatrix;
in vec4 position;
in vec2 texcoord;
out vec2 vTexCoord;
void main()
{
vTexCoord = texcoord;
gl_Position = modelViewProjectionMatrix * position;
}
</code>
OF_GLSL_SHADER_HEADER
uniform mat4 modelViewProjectionMatrix;
in vec4 position;
in vec2 texcoord;
out vec2 vTexCoord;
void main()
{
vTexCoord = texcoord;
gl_Position = modelViewProjectionMatrix * position;
}
I’ve checked the output of the FBO after initialisation and during the loop and it’s as I would expect. However only the GUI window displays the FBO, the main display shows a black rectangle. The red background and offset fbo draw position is to show that there is something being drawn. I’ve hardcoded the larger display resolution values into the the FBO function so that it will scale down for the GUI display. There are no error messages and everything compiles fine. I’m at my wits end.