[HDK] GR primitive rendering GL instances

   4979   8   1
User Avatar
Member
766 posts
Joined: Sept. 2011
Offline
Hi,
just trying to get GL instancing working in GL3 via a GR primitive Hook.

I can happily create and draw one trinagle, but am unable to instance it twice..

to setup the two instances, I create two matrices, and append them to a vector of matrices, then pass them to my RE_geometry as an instanced attribute..

on a geo->draw it willwork and draw one, but a call to drawinstanced, it will crash… any advice appreciated

these are my modifications to the HDK example GUI_Primframework to test it

——— in update() ———–


bool new_geo = false;
if (!myGeometry)
{
myGeometry = new RE_Geometry(3);
new_geo = true;
}
UT_Vector3FArray pos(3, 3);
pos(0) = UT_Vector3F(0,0,0);
pos(1) = UT_Vector3F(1,0,0);
pos(2) = UT_Vector3F(0,1,0);
myGeometry->createAttribute(r, “P”, RE_GPU_FLOAT32, 3, pos.array()->data());
GR_UtilsGL3::buildInstanceObjectMatrix(r, primh, p, myGeometry, p.instance_version);
UT_Matrix4F instance;
instance.identity();
std::vector<UT_Matrix4F> instances;
instance.translate(2,0,0);
instances.push_back(instance);
instance.translate(0,2,0);
instances.push_back(instance);
//the below works with regular draw()
//myGeometry->createConstAttribute(r, “instmat”, RE_GPU_MATRIX4, 1, instances.data());


// the below fails with a crash called via ->drawinstanced() or even a ->draw() in the render()
myGeometry->createInstancedAttribute(r, “instmat”, RE_GPU_MATRIX4, 1, 0, 2, instances.data());
if (new_geo)
{
const unsigned line_connect = { 0, 1, 1, 2, 2, 0 };
myGeometry->connectIndexedPrimsI(r, 1, RE_PRIM_LINES, 6, line_connect);
}



——- in render ——

r->pushShader();
r->bindShader(theLineShader);
myGeometry->drawInstanced(r, 1, 2); // <- this fails
// myGeometry->draw(r, 1); //<-this works
r->popShader();


————————

p.s I'm assuming that once I get this going I can pass Cd/Alpha as a another instanced attribute and also get each instance to draw a difference colour..!
Miles Green, Supervising TD, Netflix Animation Studios
User Avatar
Member
766 posts
Joined: Sept. 2011
Offline
BTW: the shader we are using to test is:

static RE_ShaderHandle theLineShader(“basic/GL32/wire_color.prog”);

which does expect instmat as a mat4: i.e:

in mat4 instmat;

unlike the example here which uses vec3 to do translates:
http://www.sidefx.com/docs/hdk13.0/_h_d_k__viewport_r_e.html#HDK_ViewportRE_Instancing [sidefx.com]
Miles Green, Supervising TD, Netflix Animation Studios
User Avatar
Staff
5287 posts
Joined: July 2005
Offline
The easiest way to do this is to let buildObjectInstanceMatrix() do the work for you. Create a new GR_UpdateParms based on update()'s GR_UpdateParms parameter and assign a UT_Matrix4DArray containing your matrices to GR_UpdateParms::instances (or multiply it with the instance list, if it exists). You'll also want to substitute GR_UpdateParms::geo_version for GR_UpdateParms::instance_version so that the instance matrix array updates when the geometry changes, rather than when the object instancing parms change:


UT_Matrix4DArray inst;
inst.append(UT_Matrix4D::getIdentityTransform());
inst.last().translate(2,0,0);
inst.append(UT_Matrix4D::getIdentityTransform());
inst.last().translate(0,2,0);

GR_UpdateParms ip(p);
ip.instances = &inst;
GR_UtilsGL3::buildInstanceObjectMatrix(r, primh, ip, myGeometry, ip.geo_version);


This is just for the case where p.instances == NULL. For the non-null case, you'd basically convolve the two lists together and combine the geo_version and inst_version into a single version - RE_CacheVersion v(p); v.setElement(0, p.instance_version.getElement(0) + p.geo_version); .
User Avatar
Member
766 posts
Joined: Sept. 2011
Offline
great thanks twod, that helps a bunch… now we're able to do some basic GL instancing… essentially we're mirroring the obj instance node, but at sop level..

Plus we will try to get the instances to inherit Cd/Alpha something we've never been able to do with houdini's default fast point instancing.
Miles Green, Supervising TD, Netflix Animation Studios
User Avatar
Member
766 posts
Joined: Sept. 2011
Offline
just a quick query, all is going well but the alpha is doing something funny.

we find that the alpha value we insert gets evaluated as a binary on or off unless we insert a pushUniformData(RE_UNIFORM_ALPHA_PASS , alphavalue) around our draw instanced calls i.e:




fpreal32 tempalpha = {1.0,1.0,1.0,1};
ren.pushUniformData(RE_UNIFORM_ALPHA_PASS , tempalpha);
data.m_geo->drawInstanced(&ren, RE_GEO_SHADED_IDX, instancelist.capacity());
ren.popUniformData(RE_UNIFORM_ALPHA_PASS);


if we do this then we get floating point alpha values but the polys render in the style of hidden line invisible. i.e you can see the background grid though them but not other polys (see pic)

we are assuming we are missing a vital step to get the alpha working properly.. any suggestions

Attachments:
bad_alpha.jpg (128.2 KB)

Miles Green, Supervising TD, Netflix Animation Studios
User Avatar
Staff
5287 posts
Joined: July 2005
Offline
In your GR primitive, override:

virtual bool requiresAlphaPass() const { return true; }
virtual bool renderInAlphaPass(GR_AlphaPass a) { return true; }

You can also conditionally request an alpha pass based on your geometry (if Alpha is present or not, for example).

The second virtual specifies the exact passes to participate in, which will be unnecessary in the next major release. For now just have it return true.
User Avatar
Member
766 posts
Joined: Sept. 2011
Offline
thanks again, alpha is all working well now..
Miles Green, Supervising TD, Netflix Animation Studios
User Avatar
Member
766 posts
Joined: Sept. 2011
Offline
one last question..
can the RE hooks be added to points without a primitive, we currently create a particle system primitive with an add sop to get our hook get a register/draw via


GA_PrimitiveTypeId type(GA_PRIMPART);
dm_table->registerGEOHook(new GUI_PrimFrameworkHook(), type, priority, GUI_HOOK_FLAG_NONE);



we tried switching GA_PRIMPART to GA_PRIMNONE but then nothing renders
Miles Green, Supervising TD, Netflix Animation Studios
User Avatar
Staff
5287 posts
Joined: July 2005
Offline
No, you'd have to hook on the GT primitive type GT_PRIM_POINT_MESH and grab the data from GT_PrimPointMesh passed through the GT_PrimitiveHandle to update(). There is no GEO primitive to hook onto for unconnected points.
  • Quick Links