← Back

ofxUbo

github.com/Ahbee/ofxUbo · @Ahbee
OF 0.9 Graphics

an openframeworks addon for interfacing with uniform buffers and blocks

29 2 Last commit 9y ago Created 12y ago

README

Overview

Uniform buffers are an alternative way to upload data to GLSL. They are available in openGl 3.2+. Normally Uniform buffers can be tedious to set up because you have to worry about layout differences between client side and GLSL. ofxUbo takes care of all that and makes it easy to use uniform buffers. ofxUbo works with shared and std140 layouts. Tested for openframeworks 0.8.0

Advantages over ofShader::setUniform

1. Uniform Buffers are a more organized way to send a "struct" of data 2. If you are sending the same data to multiple shaders, Ubo's can significantly reduce code. 3. With Ubo's, you can send arbitary data to GLSL much more easily. For example sending an array of 4x4 matrices is trivial with ubos, but would be quite difficult with ofShader::setUniform.

How to use



step 1: Use programable renderer



First make sure you are using the programable renderer in openframeworks. Set that in your main function before anything.

ofSetCurrentRenderer(ofGLProgrammableRenderer::TYPE);

step 2: Define client side struct



Next define a struct in openframewroks that matches your uniform block in GLSL. For example if your uniform block looks like this in GLSL.

uniform RandomData
{
	int x;
	vec2 position;
	float numbers[20];
	mat3 transform;
	mat4 bones[100];
	bool drawMask;
	mat4x3 matrix; // 4 col, 3 row
} ;


in openframeworks you define something that looks like this. Names do not have to match but the types do.

struct RandomData
{
	int x;
	ofVec2f position;
	float numbers[20];
	ofMatrix3x3 transform;
	ofMatrix4x4 bones[100];
	int drawmask // bool in GlSL in actually an int 
	float matrix4 // 4 row, 3 col
}
Note that in openframeworks matrices are Row Major, but in GLSL they are Column major. But this ok since ofxUbo uploads a row major matrix as Column major matrix in GLSL. Genral rule is, on client side work in Row Major, and in GLSL work in Column Major.

here is a table to match GLSL types to openframework side types;

GLSLOpenframeworks
intint
floatfloat
boolint
vec2ofVec2f or float[2]
vec3ofVec3f or float [3]
vec4ofVec4f or float [4]
mat3ofMatrix3x3 or float3
mat4ofMatrix4x4 or float4
mat2float2
mat2x3float2
mat2x4float2
mat3x2float3
mat3x4float3
mat4x2float4
mat4x3float4
Of coarse any of these types can be turned into an array.

step 3 ofxUboShader



Instead of ofShader use ofxUboShader, which is just a subclass with 2 extra functions.

ofxUboShader shader
create an Instance of your struct and set its members

RandomData myRandomData
// set members of myRandomData


use ofxUboShader::setUniformBuffer to upload your data to GLSL. Should be done inside draw function. The first parameter is the uniform block name, the second is your data.

void ofApp::draw(){
	shader.begin();
	shader.setUniformBuffer("RandomData",myRandomData);
	// draw stuff
	shader.end();    
}


Manual padding

By default ofxUbo queries the layout in GLSL and uploads your data accordingly. However if you want to manual pad and upload data yourself you can do that as well.

To get the layout, call ofxUboShader::printLayout. This prints uniform block info to the console

// prints the layout of 'Material' to console
shader.printLayout("Material");
then use ofxUboShader::setUniformBuffer with an extra boolean argument

shader.setUniformBuffer("Material", blueShine, true);
for example suppose your srtuct in GLSL looks like this

uniform Settings{
	vec2 center;
	vec4 color;
};
then shader.printLayout("Settings") will print out this

Block Name: Settings
Layout Size: 32
	Settings.center
		GL_FLOAT_VEC2
		offset: 0
		size: 8
		array Stride: 0
		matrix Stride: 0
	Settings.color
		GL_FLOAT_VEC4
		offset: 16
		size: 16
		array Stride: 0
		matrix Stride: 0


By looking at the Offset info, you know your struct on the cpu side should look like this

struct Settings {
    ofVec2f center;
    float pad[2];
    ofVec4f color;
};


Notes

You can use double types only with manual padding The auto upload does not yet support double types. To do this I need to query alignment of types. C++11 has alignof, but openframeworks currently does not support C++11. I will support doubles as soon as openframeworks upgrades. If someone knows a way to query alignments please let me know. If a struct is not uploading correctly please let me know. Post an issue with both your cpu side struct and the corresponding uniform block. I will look at it. Also try uploading manually. Pull requests are encouraged





Get this addon

HTTPS
SSH