matus-chochlik / oglplus

OGLplus is a collection of open-source, cross-platform libraries which implement an object-oriented facade over the OpenGL® (version 3 and higher) and also OpenAL® (version 1.1) and EGL (version 1.4) C-language APIs. It provides wrappers which automate resource and object management and make the use of these libraries in C++ safer and more convenient.
http://oglplus.org/
Boost Software License 1.0
491 stars 72 forks source link

Write from one transform feedback to another transform feedback #78

Closed ghost closed 10 years ago

ghost commented 10 years ago

I am trying to achieve something similar to what the following tutorial is doing: http://ogldev.atspace.co.uk/www/tutorial28/tutorial28.html

Basically what I want to do is draw my vertices to a transform feedback buffer, then draw that onto another transform feedback buffer and circle through this process as many times as I want.

The code that I currently have crashes on the DrawTransformFeedback function. I am pretty sure that the problem is the second parameter I am passing. In opengl the second parameter of this function is simply the index of the transform feedback buffer, in oglplus it requires the TransformFeedbackName which I am not sure how I can extract from my Buffer.

I cut out some parts of my code to give you a better image of what I am trying to do: (primitives are patches because I have all stages of the pipeline active) This is how I setup all the buffers:

// Buffer setup
m_verts0.Bind(Buffer::Target::Array);
Buffer::Data(Buffer::Target::Array, data, BufferUsage::DynamicDraw);

m_trFeed.Bind(Buffer::Target::TransformFeedback);
m_verts.Bind(Buffer::Target::Array);
Buffer::Data(Buffer::Target::Array, data, BufferUsage::DynamicDraw);
m_verts.BindBase(Buffer::IndexedTarget::TransformFeedback, 0);

m_trFeed2.Bind(Buffer::Target::TransformFeedback);
m_verts2.Bind(Buffer::Target::Array);
Buffer::Data(Buffer::Target::Array, data, BufferUsage::DynamicDraw);
m_verts2.BindBase(Buffer::IndexedTarget::TransformFeedback, 0);

And this is how I try to use them to render:

// first pass
{
m_trprog.Use();
m_verts0.Bind(Buffer::Target::Array);
m_trFeed2.Bind(Buffer::Target::TransformFeedback);
////m_verts2.BindBase(Buffer::IndexedTarget::TransformFeedback, 0);

TransformFeedback::Activator activates_tfb(TransformFeedbackPrimitiveType::Triangles);
m_meshInstr.Draw(m_meshInds);
activates_tfb.Finish();
}

// second pass
{
m_mprog.Use();
m_verts2.Bind(Buffer::Target::Array);
m_trFeed.Bind(Buffer::Target::TransformFeedback);
////m_verts.BindBase(Buffer::IndexedTarget::TransformFeedback, 0);

TransformFeedback::Activator activates_tfb(TransformFeedbackPrimitiveType::Triangles);
gl->DrawTransformFeedback(PrimitiveType::Patches, TransformFeedback::Binding(TransformFeedbackTarget::TransformFeedback));
activates_tfb.Finish();
}

// third pass
{
m_prog.Use();
m_verts.Bind(Buffer::Target::Array);
m_trFeed2.Bind(Buffer::Target::TransformFeedback);
////m_verts2.BindBase(Buffer::IndexedTarget::TransformFeedback, 0);

TransformFeedback::Activator activates_tfb(TransformFeedbackPrimitiveType::Triangles);
gl->DrawTransformFeedback(PrimitiveType::Patches, TransformFeedback::Binding(TransformFeedbackTarget::TransformFeedback));
activates_tfb.Finish();
}

It crashes on the first call of the DrawTransformFeedback function at runtime.

What I want to do there is pass the index of m_trFeed2 as the second parameter for the second pass and m_trFeed as the second parameter for the third pass.

If I enable the BindBase functions that I have commented out when rendering it stops the crashing and I do get some output that looks like the proper one, but according to the tutorial calling BindBase again should not be required. Maybe this is actually correct though and I am being paranoid.

Sorry for the length of this post.

matus-chochlik commented 10 years ago

Hi,

IMHO You should not pass the same TFB object that is currently bound and activated to DrawTransformFeedback, instead pass the other one:

// second pass
m_trFeed.Bind(Buffer::Target::TransformFeedback);
...
gl->DrawTransformFeedback(PrimitiveType::Patches, m_trFeed2);
...
// third pass
m_trFeed2.Bind(Buffer::Target::TransformFeedback);
...
gl->DrawTransformFeedback(PrimitiveType::Patches, m_trFeed);
...
ghost commented 10 years ago

That's what I am actually trying to do, but I get the following compile error on DrawTransformFeedback if I do it that way:

Cannot convert parameter 2 from oglplus::Buffer to oglplus::TransformFeedbackName
matus-chochlik commented 10 years ago

Ah, I assumed that m_trFeed is a TransformFeedback object not a Buffer. A TransformFeedback object keeps track of transform feedback buffer bindings in a similar manner as a VertexArray does for vertex attribute array buffers. So if you want to switch transform feedback output to different buffers, you either must call the Buffer::BindBase function before every switch or use transform feedback objects.

ghost commented 10 years ago

Aha, changing from Buffer to TransformFeedback did the trick. Thanks for your time!