Hello, this is my first post here, nice to find such a helpful site.
Recently I am digging into the examples to find the most proper ways to use Cinder’s VboMesh Class. It is so flexible to use and thus sometimes a bit confusing to decide which way to choose on what requirements.
Here I mostly ask the most ‘idiomatic’ ways to create a VboMesh from custom vbos.
//! Creates a VboMesh which represents the user's vertex buffer objects. Allows optional \a indexVbo to enable indexed vertices; creates a static index VBO if none provided.
static VboMeshRef create( uint32_t numVertices, GLenum glPrimitive, const std::vector<std::pair<geom::BufferLayout,VboRef>> &vertexArrayBuffers, uint32_t numIndices = 0, GLenum indexType = GL_UNSIGNED_SHORT, const VboRef &indexVbo = VboRef() );
//! Creates a VboMesh which represents the user's vertex buffer objects. Allows optional \a indexVbo to enable indexed vertices; creates a static index VBO if none provided.
static VboMeshRef create( uint32_t numVertices, GLenum glPrimitive, const std::vector<Layout> &vertexArrayLayouts, uint32_t numIndices = 0, GLenum indexType = GL_UNSIGNED_SHORT, const VboRef &indexVbo = VboRef() );
The two ‘create’ calls above only differs in ‘layout’ part. Please help me clarify if my understanding is right.
const std::vector<std::pairgeom::BufferLayout,VboRef> &vertexArrayBuffers
which associate the layouts info with correspondent vbo. One VboMesh can have many vbos, each vbo can have many interleaved attributes. But I know the gl::Batch is kind of wrapper of Vao, so, are there any max attribute number requirements for the VboMesh? Like the sum of all vbo’s attribute numbers should be below 16?
The second one is even more confusing, I can’t see how the VboMesh::Layout associate with the vbo or the data. I still can’t make a minimum working example using this api. When is this one useful against custom vbo or vertex data?
Below are my minimum examples to learn how to use the first api to draw triangles.
#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/VboMesh.h"
#include "cinder/gl/gl.h"
using namespace ci;
using namespace ci::app;
//class VboMesh;
using fms = std::chrono::duration<float, std::milli>;
using Clock = std::chrono::steady_clock;
class BasicApp : public App {
public:
void draw() override;
void setup() override;
private:
struct vertex {
vec2 pos;
vec3 color;
};
gl::GlslProgRef m_shader;
gl::BatchRef m_batchAOS;
gl::BatchRef m_batchSOA;
};
void BasicApp::draw()
{
gl::clear();
m_batchSOA->draw();
m_batchAOS->draw();
}
void BasicApp::setup() {
m_shader = gl::GlslProg::create(loadAsset("vertex.vert"), loadAsset("fragment.frag"));
gl::enableDepthRead();
gl::enableDepthWrite();
std::vector<vertex> vertices = {
{vec2(-0.5, 0.5), vec3(1, 0, 0)},
{vec2(-1, -0.5), vec3(0, 1, 0)},
{vec2(0, -0.5), vec3(0, 0, 1)}
};
std::vector<vec2> position {vec2(0.5, 0.5), vec2(0,-0.5), vec2(1, -0.5)};
std::vector<vec3> colors {vec3(1, 0, 1), vec3(1, 1, 0), vec3(0, 1, 1)};
/**
* @brief try array of structures layout!
*/
auto vbo = gl::Vbo::create(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
geom::BufferLayout layout;
layout.append(geom::CUSTOM_0, 2, sizeof(vertex), offsetof(vertex, pos));
layout.append(geom::CUSTOM_1, 3, sizeof(vertex), offsetof(vertex, color));
auto meshAOS = gl::VboMesh::create(
vertices.size(),
GL_TRIANGLES,
{{layout, vbo}}
);
auto glsl = gl::GlslProg::create(loadAsset("vertex.vert"), loadAsset("fragment.frag"));
gl::Batch::AttributeMapping map = {{geom::CUSTOM_0, "pos"},{geom::CUSTOM_1, "color"}};
m_batchAOS = gl::Batch::create(meshAOS, m_shader, map);
/**
* @brief try structure of arrays layout!
*/
auto vboPos = gl::Vbo::create(GL_ARRAY_BUFFER, position);
auto vboColor = gl::Vbo::create(GL_ARRAY_BUFFER, colors);
auto meshSOA = gl::VboMesh::create(
(uint32_t)3, GL_TRIANGLES,
{
{geom::BufferLayout({geom::AttribInfo(geom::CUSTOM_0, 2, 0, 0)}), vboPos},
{geom::BufferLayout({geom::AttribInfo(geom::CUSTOM_1, 3, 0, 0)}), vboColor}
}
);
m_batchSOA = gl::Batch::create(meshSOA, m_shader, map);
}
CINDER_APP( BasicApp, RendererGl )