Yea, but I have a handle on that part. Can ve done via read callback in the
registry, or saved as well, I saw there is serialization support.
I wrote a simple visitor that should convert a loaded model into meshlets.
I had it working nicely until I started to experiment with threaded access.
Attached is the source. Not elegant at all but I would be happy if you can
have a look and maybe spot the problem
Thanks a bunch!
On Wed, Jun 1, 2022, 09:25 Werner Modenbach <
[email protected]> wrote:
> Hi Nick,
> good to hear you are getting closer.
> Due to the fact that standard classes of paged data handle vertex arrays
> etc. autonomously and mesh shaders work different I think you have to look
> up where this handling is done and write your own derived class.
> Werner
>
>
> On 31. Mai 2022 21:28:08 MESZ, Trajce Nikolov NICK <
> [email protected]> wrote:
>>
>> Hi again Werner,
>>
>> I think I got it after reading few articles, actually the main one from
>> NVIDIA. Do you have experience in using this with paged data?
>>
>> On Sat, May 28, 2022 at 8:35 PM Trajce Nikolov NICK <
>> [email protected]> wrote:
>>
>>> Hi Werner!
>>>
>>> Thanks soo much for the shared code and the hints!!! I have a better
>>> understanding now how all works together wrt. buffers. Just this snippet,
>>> if you are willing to provide more hints.
>>>
>>> int startVertex = 1;
>>>
>>> int anzahl = _anzahlVertices;
>>>
>>> for (auto i=0; i<workgroupsInGeometry; ++i) {
>>>
>>> (*MeshletInfosArray)[i][0] = startVertex;
>>>
>>> (*MeshletInfosArray)[i][1] = min(TS_WORKGROUP_SIZE, anzahl);
>>>
>>> startVertex += TS_WORKGROUP_STEP;
>>>
>>> anzahl -=TS_WORKGROUP_STEP;
>>>
>>> }
>>>
>>>
>>> The ideal is to have a working code, a bit more robust then the one I found
>>> in the repo in the meshshaders branches. But I am getting there slowly :-)
>>>
>>>
>>> This is indeed a big thing!
>>>
>>>
>>> Big thanks!
>>>
>>> Nick
>>>
>>>
>>>
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>> Virus-free.
>>> www.avast.com
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>> <#m_-7378692753233440497_m_-4127028168198206277_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>>>
>>> On Sat, May 28, 2022 at 3:09 PM Trajce Nikolov NICK <
>>> [email protected]> wrote:
>>>
>>>> Okay. Thanks a buch for these hints! I am starting next week with
>>>> this. Will post findings
>>>>
>>>> On Sat, May 28, 2022, 14:44 Werner Modenbach <
>>>> [email protected]> wrote:
>>>>
>>>>> Yes, that is the only (?) way.
>>>>>
>>>>>
>>>>> On 28. Mai 2022 12:23:48 MESZ, Trajce Nikolov NICK <
>>>>> [email protected]> wrote:
>>>>>>
>>>>>> Hi!
>>>>>>
>>>>>> I haven't looked at the code yet, just want to clarify one thing: you
>>>>>> are providing the meshlets verts uvs normals through 1d texture?
>>>>>>
>>>>>> On Wed, May 25, 2022, 12:17 Trajce Nikolov NICK <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> Hi!
>>>>>>>
>>>>>>> Thanks a bunch! Is your code in the repo so I can have a look?
>>>>>>>
>>>>>>> On Wed, May 25, 2022, 09:17 Werner Modenbach <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> Hi Nick,
>>>>>>>> There is nothing special in the contents of the buffers. They are
>>>>>>>> just arrays like vertex array. Special is the definition as buffer
>>>>>>>> objects
>>>>>>>> and "overlaying" them with a texture like shown in my code. In the
>>>>>>>> shader
>>>>>>>> you have the instance ID and from that you access the meshlet info via
>>>>>>>> the
>>>>>>>> 1D texture. Get your operation parameters from there and fetch
>>>>>>>> vertices,
>>>>>>>> normals, colors etc. also via the textures.
>>>>>>>> The only difficulty is the size limit of the textures. So you
>>>>>>>> eventually have to split the arrays.
>>>>>>>> That's it.
>>>>>>>> Werner
>>>>>>>>
>>>>>>>>
>>>>>>>> On 24. Mai 2022 22:59:52 MESZ, Trajce Nikolov NICK <
>>>>>>>> [email protected]> wrote:
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I am also researching this subject. Have you succeeded? Any hints
>>>>>>>>> about the meshelts buffer objects? Any other hints?
>>>>>>>>>
>>>>>>>>> Thank you a bunch for any shared info!
>>>>>>>>>
>>>>>>>>> Nick
>>>>>>>>>
>>>>>>>>> On Wed, May 11, 2022 at 5:35 PM DC <[email protected]>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> Thanks Werner!
>>>>>>>>>> This will certainly help me get started.
>>>>>>>>>>
>>>>>>>>>> Much appreciated,
>>>>>>>>>> DC
>>>>>>>>>>
>>>>>>>>>> On Wednesday, May 11, 2022 at 4:13:08 AM UTC-5 Werner Modenbach
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi DC,
>>>>>>>>>>>
>>>>>>>>>>> here is the link:
>>>>>>>>>>> https://github.com/nvpro-samples/gl_vk_meshlet_cadscene
>>>>>>>>>>> This should help you with items 1) and 2)
>>>>>>>>>>>
>>>>>>>>>>> For item 3) see my code below.
>>>>>>>>>>> The way I assign the data structures in OSG is like that:
>>>>>>>>>>>
>>>>>>>>>>> // ----------------------
>>>>>>>>>>> // Create Meshlet primitive // ----------------------
>>>>>>>>>>>
>>>>>>>>>>> _geode->getOrCreateStateSet()->getOrCreateUniform(TASK_INVOCATIONS_PER_MESHLET,
>>>>>>>>>>> osg::Uniform::INT)->set(taskInvocationsPerMeshlet);
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::ProxyPrimitive> proxyPrimitive = new
>>>>>>>>>>> osg::ProxyPrimitive;
>>>>>>>>>>>
>>>>>>>>>>> proxyPrimitive->drawMeshTasks = new osg::DrawMeshTasks(0,
>>>>>>>>>>> workgroupsInGeometry * taskInvocationsPerMeshlet);
>>>>>>>>>>>
>>>>>>>>>>> geometry->setUseDisplayList(false);
>>>>>>>>>>>
>>>>>>>>>>> geometry->addPrimitiveSet(proxyPrimitive.get());
>>>>>>>>>>>
>>>>>>>>>>> _geode->addChild(geometry);
>>>>>>>>>>>
>>>>>>>>>>> // ----------------------
>>>>>>>>>>> // Vertices
>>>>>>>>>>>
>>>>>>>>>>> // ----------------------
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::Vec4Array> osgVertices = new
>>>>>>>>>>> osg::Vec4Array(toCopy);
>>>>>>>>>>>
>>>>>>>>>>> for (auto i=0; i<toCopy; ++i) { // fill array // Fill
>>>>>>>>>>> buffer
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> // Create Buffer and Texture
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::VertexBufferObject> verticesBufferObject =
>>>>>>>>>>> new osg::VertexBufferObject();
>>>>>>>>>>>
>>>>>>>>>>> verticesBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
>>>>>>>>>>>
>>>>>>>>>>> osgVertices->setBufferObject(verticesBufferObject.get());
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::TextureBuffer> vertexTexture = new
>>>>>>>>>>> osg::TextureBuffer(osgVertices.get());
>>>>>>>>>>>
>>>>>>>>>>> vertexTexture->setInternalFormat(GL_RGBA32F_ARB);
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> vertexTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> stateSet->setTextureAttributeAndModes(MESH_VERTEX_ARRAY_TEXTURE_UNIT,
>>>>>>>>>>> vertexTexture.get());
>>>>>>>>>>>
>>>>>>>>>>> // ----------------------
>>>>>>>>>>> // MeshletInfos
>>>>>>>>>>>
>>>>>>>>>>> // ----------------------
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<Vec4uiArray> MeshletInfosArray = new
>>>>>>>>>>> Vec4uiArray(workgroupsInGeometry);
>>>>>>>>>>>
>>>>>>>>>>> int startVertex = 1;
>>>>>>>>>>>
>>>>>>>>>>> int anzahl = _anzahlVertices;
>>>>>>>>>>>
>>>>>>>>>>> for (auto i=0; i<workgroupsInGeometry; ++i) {
>>>>>>>>>>>
>>>>>>>>>>> (*MeshletInfosArray)[i][0] = startVertex;
>>>>>>>>>>>
>>>>>>>>>>> (*MeshletInfosArray)[i][1] = min(TS_WORKGROUP_SIZE, anzahl);
>>>>>>>>>>>
>>>>>>>>>>> startVertex += TS_WORKGROUP_STEP;
>>>>>>>>>>>
>>>>>>>>>>> anzahl -= TS_WORKGROUP_STEP;
>>>>>>>>>>>
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> // Create Buffer and Texture
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::VertexBufferObject> meshInfosBufferObject =
>>>>>>>>>>> new osg::VertexBufferObject();
>>>>>>>>>>>
>>>>>>>>>>> meshInfosBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
>>>>>>>>>>>
>>>>>>>>>>> MeshletInfosArray->setBufferObject(meshInfosBufferObject.get());
>>>>>>>>>>>
>>>>>>>>>>> osg::ref_ptr<osg::TextureBuffer> meshInfosTexture = new
>>>>>>>>>>> osg::TextureBuffer(MeshletInfosArray.get());
>>>>>>>>>>>
>>>>>>>>>>> meshInfosTexture->setInternalFormat(GL_RGBA32UI_EXT);
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> meshInfosTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> stateSet->setTextureAttributeAndModes(MESH_INFOS_ARRAY_TEXTURE_UNIT,
>>>>>>>>>>> meshInfosTexture.get());
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> // ----------------------
>>>>>>>>>>> // Create and assign the Task- and Mesh shader as usual by
>>>>>>>>>>> using the corresponding shader type // ----------------------
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Am 10.05.2022 um 21:20 schrieb DC:
>>>>>>>>>>>
>>>>>>>>>>> OK. Thank you.
>>>>>>>>>>>
>>>>>>>>>>> On Tuesday, May 10, 2022 at 12:59:37 PM UTC-5 Werner Modenbach
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Hi DC,
>>>>>>>>>>>> I think we should clarify some aspects before going into the
>>>>>>>>>>>> details. If I understand well, your problem can be split into 3
>>>>>>>>>>>> parts
>>>>>>>>>>>> 1) You want to convert an existing model into meshlets. This is
>>>>>>>>>>>> not related to OSG. But I found a git repository from NVIDIA doing
>>>>>>>>>>>> this
>>>>>>>>>>>> job. I will lookup the link and send it to you tomorrow.
>>>>>>>>>>>> 2) For this to work you need task/mesh shaders doing their job
>>>>>>>>>>>> on the GPU. This is also not related to OSG. Maybe you find some
>>>>>>>>>>>> starting
>>>>>>>>>>>> point in the repository as well.
>>>>>>>>>>>> 3) You need to know how to load your shader and how to setup
>>>>>>>>>>>> the data structures in OSG. I hope I can help you with that by
>>>>>>>>>>>> providing
>>>>>>>>>>>> some code snippets.
>>>>>>>>>>>> Just let me know when you are ready for that step. But the code
>>>>>>>>>>>> I provided already should help you.
>>>>>>>>>>>> Werner
>>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>> Google Groups "OpenSceneGraph Users" group.
>>>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>>>> send an email to [email protected].
>>>>>>>>>> To view this discussion on the web visit
>>>>>>>>>> https://groups.google.com/d/msgid/osg-users/7680959c-297e-41ff-9159-464b38c8df73n%40googlegroups.com
>>>>>>>>>> <https://groups.google.com/d/msgid/osg-users/7680959c-297e-41ff-9159-464b38c8df73n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>>> .
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> trajce nikolov nick
>>>>>>>>>
>>>>>>>>> --
>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>> Groups "OpenSceneGraph Users" group.
>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>> send an email to [email protected].
>>>>>>>> To view this discussion on the web visit
>>>>>>>> https://groups.google.com/d/msgid/osg-users/eb4531f5-3420-4c75-be46-539490c5c659%40email.android.com
>>>>>>>> <https://groups.google.com/d/msgid/osg-users/eb4531f5-3420-4c75-be46-539490c5c659%40email.android.com?utm_medium=email&utm_source=footer>
>>>>>>>> .
>>>>>>>>
>>>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "OpenSceneGraph Users" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to [email protected].
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/osg-users/3fd7dcac-1cec-43d9-ac91-04e22f331bd9%40email.android.com
>>>>> <https://groups.google.com/d/msgid/osg-users/3fd7dcac-1cec-43d9-ac91-04e22f331bd9%40email.android.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>
>>>
>>> --
>>> trajce nikolov nick
>>>
>>>
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>> Virus-free.
>>> www.avast.com
>>> <https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
>>> <#m_-7378692753233440497_m_-4127028168198206277_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>>>
>>
>>
>> --
>> trajce nikolov nick
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "OpenSceneGraph Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/osg-users/0ab4c82f-1f17-47e9-aa1d-9c02b5a3f7fb%40email.android.com
> <https://groups.google.com/d/msgid/osg-users/0ab4c82f-1f17-47e9-aa1d-9c02b5a3f7fb%40email.android.com?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups
"OpenSceneGraph Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/osg-users/CAO-%2Bzi%3DoBzkPA8dKafgKp-ua2yeqijsvyyg-G14e%3DvTU%2BzF1yQ%40mail.gmail.com.
// This is public domain software and comes with
// absolutely no warranty. Use of public domain software
// may vary between counties, but in general you are free
// to use and distribute this software for any purpose.
// Example: OSG using an OpenGL 3.1 context.
// The comment block at the end of the source describes building OSG
// for use with OpenGL 3.x.
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osg/GraphicsContext>
#include <osg/Camera>
#include <osg/Viewport>
#include <osg/StateSet>
#include <osg/Program>
#include <osg/Shader>
#include <osg/DrawMeshTasks>
#include <osg/DrawMeshTasksIndirect>
#include <osg/MultiDrawMeshTasksIndirect>
#include <osg/MultiDrawMeshTasksIndirectCount>
#include <osgUtil/Optimizer>
#include <osg/TextureBuffer>
#include <osg/TriangleFUnctor>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osg/MatrixTransform>
#include <osgSim/LightPointNode>
#define MESH_VERTEX_ARRAY_TEXTURE_UNIT 0
#define MESH_INFOS_ARRAY_TEXTURE_UNIT 1
#define MESH_INDEX_ARRAY_TEXTURE_UNIT 2
using namespace osg;
namespace osg
{
class ProxyPrimitive : public PrimitiveSet
{
public:
ProxyPrimitive() {}
ProxyPrimitive(const ProxyPrimitive& pp, const CopyOp& copyop=CopyOp::SHALLOW_COPY) :
PrimitiveSet(pp, copyop),
drawMeshTasks(pp.drawMeshTasks) {}
META_Object(osg, ProxyPrimitive)
ref_ptr<DrawMeshTasks> drawMeshTasks;
void draw(State& state, bool) const
{
state.apply();
drawMeshTasks->draw(state);
}
void accept(PrimitiveFunctor&) const {}
void accept(PrimitiveIndexFunctor&) const {}
unsigned int index(unsigned int) const { return 0; }
unsigned int getNumIndices() const { return 0; }
void offsetIndices(int) {}
};
}
struct ToMeshletsVisitor : public osg::NodeVisitor
{
ToMeshletsVisitor()
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
{
}
//virtual void apply(osg::Transform& node)
//{
// if (node.asMatrixTransform())
// {
// node.asMatrixTransform()->setMatrix(osg::Matrixd::identity());
// }
// traverse(node);
//}
//virtual void apply(osg::LOD& node)
//{
// node.setCenter(osg::Vec3(0, 0, 0));
// traverse(node);
//}
struct Triangulate
{
struct Meshlet
{
size_t start = 0;
size_t index_start = 0;
std::vector<uint32_t> vertices;
std::vector<uint32_t> indices;
size_t count = 0;
std::vector<osg::Vec3> v_vec;
bool v_exists(const osg::Vec3& v)
{
for (size_t i = 0; i < v_vec.size(); ++i)
{
if (v_vec.at(i) == v) return true;
}
return false;
}
};
std::vector<Meshlet> meshlets_from_geometry;
size_t vxs_start = 0;
size_t idx_start = 0;
inline void operator () (const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3)
{
if (!meshlets_from_geometry.size())
{
meshlets_from_geometry.push_back(Meshlet());
}
bool unique_v1 = false;
bool unique_v2 = false;
bool unique_v3 = false;
size_t num_unique_verts = 0;
Meshlet& meshlet = meshlets_from_geometry.back();
if (!meshlet.v_exists(v1))
{
unique_v1 = true;
++num_unique_verts;
//meshlet.v_vec.push_back(v1);
}
if (!meshlet.v_exists(v2))
{
unique_v2 = true;
++num_unique_verts;
//meshlet.v_vec.push_back(v2);
}
if (!meshlet.v_exists(v3))
{
unique_v3 = true;
++num_unique_verts;
//meshlet.v_vec.push_back(v3);
}
if (num_unique_verts + meshlet.vertices.size() > 32)
{
vxs_start += meshlet.vertices.size();
idx_start += meshlet.indices.size();
meshlets_from_geometry.push_back(Meshlet());
Meshlet& meshlet = meshlets_from_geometry.back();
meshlet.start = vxs_start;
meshlet.index_start = idx_start;
unique_v1 = true;
//meshlet.v_vec.push_back(v1);
unique_v2 = true;
//meshlet.v_vec.push_back(v2);
unique_v3 = true;
//meshlet.v_vec.push_back(v3);
}
std::map<osg::Vec3, size_t>::iterator itr = vxs_map.find(v1);
if (itr == vxs_map.end())
{
indices->push_back(vxs->size());
vxs_map[v1] = vxs->size();
vxs->push_back(v1);
}
else
{
indices->push_back(itr->second);
}
meshlet.indices.push_back(indices->back());
itr = vxs_map.find(v2);
if (itr == vxs_map.end())
{
indices->push_back(vxs->size());
vxs_map[v2] = vxs->size();
vxs->push_back(v2);
}
else
{
indices->push_back(itr->second);
}
meshlet.indices.push_back(indices->back());
itr = vxs_map.find(v3);
if (itr == vxs_map.end())
{
indices->push_back(vxs->size());
vxs_map[v3] = vxs->size();
vxs->push_back(v3);
}
else
{
indices->push_back(itr->second);
}
meshlet.indices.push_back(indices->back());
{
Meshlet& meshlet = meshlets_from_geometry.back();
if (meshlet.count + 1 == 126)
{
vxs_start += meshlet.vertices.size();
idx_start += meshlet.indices.size();
meshlets_from_geometry.push_back(Meshlet());
Meshlet& meshlet = meshlets_from_geometry.back();
meshlet.start = vxs_start;
meshlet.index_start = idx_start;
meshlet.start = vxs_start;
meshlet.index_start = idx_start;
unique_v1 = true;
//meshlet.v_vec.push_back(v1);
unique_v2 = true;
//meshlet.v_vec.push_back(v2);
unique_v3 = true;
//meshlet.v_vec.push_back(v3);
}
{
Meshlet& meshlet = meshlets_from_geometry.back();
if (unique_v1) { meshlet.vertices.push_back(vxs_map[v1]); meshlet.v_vec.push_back(v1); }
if (unique_v2) { meshlet.vertices.push_back(vxs_map[v2]); meshlet.v_vec.push_back(v2); }
if (unique_v3) { meshlet.vertices.push_back(vxs_map[v3]); meshlet.v_vec.push_back(v3); }
}
{
Meshlet& meshlet = meshlets_from_geometry.back();
/*meshlet.indices.push_back(vxs_map[v1]);
meshlet.indices.push_back(vxs_map[v2]);
meshlet.indices.push_back(vxs_map[v3]);*/
meshlet.count++;
}
}
}
inline void set(osg::Vec3Array* vertices)
{
vxs = vertices;
}
osg::Vec3Array* vxs;
osg::ref_ptr<osg::UIntArray> indices = new osg::UIntArray;
std::map<osg::Vec3, size_t> vxs_map;
};
virtual void apply(osg::Node& node)
{
osg::ref_ptr<osgSim::LightPointNode> lpn = dynamic_cast<osgSim::LightPointNode*>(&node);
if (lpn.valid())
{
lpn->setNodeMask(0);
return;
}
traverse(node);
}
virtual void apply(osg::Geode& node)
{
for (size_t i = 0; i < node.getNumDrawables(); ++i)
{
osg::ref_ptr<osg::Geometry> g = node.getDrawable(i)->asGeometry();
if (g.valid())
{
osg::ref_ptr<osg::Vec3Array> vxs = new osg::Vec3Array;
osg::TriangleFunctor<Triangulate> t;
t.set(vxs);
g->accept(t);
if (vxs->size() < 3) continue;
if (t.indices->size() < 3) continue;
size_t maxVertices = 32;
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
geometry->setUseDisplayList(false);
size_t cnt = 0;
//for (auto i = 0; i < numMeshlets; ++i)
{
size_t numVertices = vxs->size();// osg::minimum(maxVertices, vxs->size() - cnt);
osg::ref_ptr<osg::Vec4Array> osgVertices = new osg::Vec4Array(numVertices);
osg::BoundingBox bb;
for (auto j = 0; j < numVertices; ++j) { // fill array
(*osgVertices)[j] = osg::Vec4(vxs->at(j), 1);
bb.expandBy(vxs->at(j));
}
osg::ref_ptr<osg::FloatArray> osgIndices = new osg::FloatArray(t.indices->size());
for (auto j = 0; j < t.indices->size(); ++j) { // fill array
(*osgIndices)[j] = t.indices->at(j);
}
// Create Buffer and Texture
osg::ref_ptr<osg::VertexBufferObject> verticesBufferObject = new osg::VertexBufferObject();
verticesBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
osgVertices->setBufferObject(verticesBufferObject.get());
osg::ref_ptr<osg::TextureBuffer> vertexTexture = new osg::TextureBuffer(osgVertices.get());
vertexTexture->setInternalFormat(GL_RGBA32F_ARB);
vertexTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
geometry->getOrCreateStateSet()->setTextureAttributeAndModes(MESH_VERTEX_ARRAY_TEXTURE_UNIT, vertexTexture.get());
// Create Buffer and Texture
osg::ref_ptr<osg::VertexBufferObject> indicesBufferObject = new osg::VertexBufferObject();
indicesBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
osgIndices->setBufferObject(indicesBufferObject.get());
osg::ref_ptr<osg::TextureBuffer> indexTexture = new osg::TextureBuffer(osgIndices.get());
indexTexture->setInternalFormat(GL_LUMINANCE32F_ARB);
indexTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
geometry->getOrCreateStateSet()->setTextureAttributeAndModes(MESH_INDEX_ARRAY_TEXTURE_UNIT, indexTexture.get());
geometry->setComputeBoundingBoxCallback(new MyCB(bb));
}
size_t ts = t.meshlets_from_geometry.size();
while (ts > GL_TASK_WORK_GROUP_SIZE_NV)
{
osg::ref_ptr<osg::ProxyPrimitive> proxyPrimitive = new osg::ProxyPrimitive;
proxyPrimitive->drawMeshTasks = new osg::DrawMeshTasks(0, GL_TASK_WORK_GROUP_SIZE_NV);
geometry->addPrimitiveSet(proxyPrimitive.get());
ts -= GL_TASK_WORK_GROUP_SIZE_NV;
}
osg::ref_ptr<osg::ProxyPrimitive> proxyPrimitive = new osg::ProxyPrimitive;
proxyPrimitive->drawMeshTasks = new osg::DrawMeshTasks(0, ts);
geometry->addPrimitiveSet(proxyPrimitive.get());
osg::ref_ptr<Vec4Array> MeshletInfosArray = new Vec4Array(t.meshlets_from_geometry.size());
for (auto i = 0; i < t.meshlets_from_geometry.size(); ++i)
{
(*MeshletInfosArray)[i][0] = (int)t.meshlets_from_geometry.at(i).start;
(*MeshletInfosArray)[i][1] = (int)t.meshlets_from_geometry.at(i).vertices.size();
(*MeshletInfosArray)[i][2] = (int)t.meshlets_from_geometry.at(i).index_start;
(*MeshletInfosArray)[i][3] = (int)t.meshlets_from_geometry.at(i).indices.size();
}
// Create Buffer and Texture
osg::ref_ptr<osg::VertexBufferObject> meshInfosBufferObject = new osg::VertexBufferObject();
meshInfosBufferObject->setUsage(GL_DYNAMIC_READ_ARB);
MeshletInfosArray->setBufferObject(meshInfosBufferObject.get());
osg::ref_ptr<osg::TextureBuffer> meshInfosTexture = new osg::TextureBuffer(MeshletInfosArray.get());
meshInfosTexture->setInternalFormat(GL_RGBA32F_ARB);
meshInfosTexture->setInternalFormatMode(Texture::USE_USER_DEFINED_FORMAT);
geometry->getOrCreateStateSet()->setTextureAttributeAndModes(MESH_INFOS_ARRAY_TEXTURE_UNIT, meshInfosTexture.get());
meshlets.push_back(geometry);
}
}
node.getOrCreateStateSet()->setTextureAttributeAndModes(MESH_VERTEX_ARRAY_TEXTURE_UNIT, 0);
node.removeDrawables(0, node.getNumDrawables());
for (size_t i = 0; i < meshlets.size(); ++i)
{
node.addDrawable(meshlets.at(i));
}
meshlets.clear();
traverse(node);
}
std::vector<osg::ref_ptr<osg::Geometry>> meshlets;
struct MyCB : public osg::Drawable::ComputeBoundingBoxCallback
{
MyCB(const osg::BoundingBox& bb)
: _bb(bb)
{
}
virtual BoundingBox computeBound(const osg::Drawable&) const
{
return _bb;
}
osg::BoundingBox _bb;
};
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
};
int main( int argc, char** argv )
{
osg::ArgumentParser arguments( &argc, argv );
static const char* meshSource = \
"#version 450 \n"
"#extension GL_NV_mesh_shader : enable\n"
"layout(local_size_x = 32) in;"
"layout(max_vertices = 64) out;"
"layout(max_primitives = 126) out;"
"layout(triangles) out;"
"uniform samplerBuffer vertices;"
"uniform samplerBuffer meshletsInfo;"
"uniform samplerBuffer indices;"
"uniform mat4 osg_ModelViewProjectionMatrix;"
"void main()"
"{"
"uint mi = gl_WorkGroupID.x;"
"vec4 u = texelFetch(meshletsInfo, int(mi));"
"int start = int(u.x);"
"int count = int(u.y);"
"int idx_start = int(u.z);"
"int idx_count = int(u.w);"
"uint id = gl_LocalInvocationID.x;"
"if (id < count)"
"{"
"vec4 t = texelFetch(vertices, int(start+id));"
"gl_MeshVerticesNV[id].gl_Position = osg_ModelViewProjectionMatrix* t;"
"}"
"for (int i = 0; i < idx_count; ++i)"
"{"
"uint idx = uint(texelFetch(indices,int(idx_start+i)).x);"
"gl_PrimitiveIndicesNV[i] = idx;"
"}"
//"if (id == 0)"
"gl_PrimitiveCountNV = idx_count/3;"
"}";
static const char* fragmentSource = \
"#version 450 \n"
"#extension GL_NV_fragment_shader_barycentric : enable\n"
"out vec4 color;"
"void main()"
"{"
"color = vec4(gl_BaryCoordNV, 1.0);"
"}";
osg::ref_ptr<osg::Shader> vShader = new osg::Shader( osg::Shader::MESH, meshSource );
osg::ref_ptr<osg::Shader> fShader = new osg::Shader( osg::Shader::FRAGMENT, fragmentSource );
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader( vShader.get() );
program->addShader( fShader.get() );
osg::ref_ptr<osg::Group> group = new osg::Group;
group->getOrCreateStateSet()->setAttribute( program.get() );
group->getOrCreateStateSet()->getOrCreateUniform("meshletsInfo", osg::Uniform::SAMPLER_BUFFER)->set(1);
group->getOrCreateStateSet()->getOrCreateUniform("indices", osg::Uniform::SAMPLER_BUFFER)->set(2);
// group->addChild( new osg::DrawMeshTasksIndirect(0) ); // will require a buffer to be bound.
// group->addChild( new osg::MultiDrawMeshTasksIndirect(0, 0, 0) ); // will require a buffer to be bound.
// group->addChild( new osg::MultiDrawMeshTasksIndirectCount(0, 0, 0, 0) ); // will require a buffer to be bound.
osgDB::writeNodeFile(*group, "test.osg");
osgViewer::Viewer viewer(arguments);
// add the state manipulator
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
// add the thread model handler
viewer.addEventHandler(new osgViewer::ThreadingHandler);
// add the window size toggle handler
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
// add the stats handler
viewer.addEventHandler(new osgViewer::StatsHandler);
// add the help handler
viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
// add the record camera path handler
viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
// add the LOD Scale handler
viewer.addEventHandler(new osgViewer::LODScaleHandler);
// add the screen capture handler
viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(arguments);
ToMeshletsVisitor nv;
model->accept(nv);
group->addChild( model );
viewer.setSceneData( group );
viewer.realize();
osg::setNotifyLevel(osg::NOTICE);
// for non GL3/GL4 and non GLES2 platforms we need enable the osg_ uniforms that the shaders will use,
// you don't need thse two lines on GL3/GL4 and GLES2 specific builds as these will be enable by default.
viewer.getCamera()->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(true);
viewer.getCamera()->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(true);
return( viewer.run() );
}