Hello Carsten,
the attached version for GPU skinning seems to work in my cluster setup. But
I am not sure if I got it all right. Changes are done in skeletonChanged:
- added Skeleton::JointsChangedFieldMask
- removed the origin != ChangedOrigin::Sync condition (please explain, what
it should do)
- moved the updates of the shader uniforms from renderEnter directly to this
method
Thank You for the hints! Maybe some more testing is necessary... tomorrow.
Cheers,
Volker
> -----Original Message-----
> From: Carsten Neumann [mailto:carsten_neum...@gmx.net]
> Sent: Dienstag, 14. August 2012 21:41
> To: opensg-users@lists.sourceforge.net
> Subject: Re: [Opensg-users] OSG2, Ogre skinning + cluster
>
> Hello Volker,
>
> On 08/14/2012 11:16 AM, Volker Settgast wrote:
> > concerning the skinning-with-cluster problem:
> >
> > I found out, that some changes to the Ogre skinning mesh take place
> > while rendering. So the extra rendering for the shadow map triggers
> > the update, but leaving out the shadow stage will not update the
> > skinning correctly. As an example I added the following lines in the
> > displayCB method to character.cpp from the advanced examples:
> >
> > [...]
> > OSG::FrameHandler::the()->frame(currT);
> >
> > //OSG::commitChangesAndClear(); // do not
clear
> > changes now, cluster needs changes, right? (let's pretend that the
> > render call is done on a clusterwindow)
> > OSG::Thread::getCurrentChangeList()->commitChanges();
> >
> > g->mgr->idle ();
> > g->mgr->redraw();
> >
> > //OSG::Thread::getCurrentChangeList()->clear(); // not working,
> > because no commit is done, skinning mesh will not move
> > OSG::commitChangesAndClear(); // working
for
> > client, but still not working for servers, though
> >
> > [...]
> > So, the skeleton joints move correctly (rendermode 1 shows that), but
> > the skinning is doing some update which is triggered with the
> > rendering. Could this update be moved to another place?
>
> hmm, not sure how difficult it is to move it to a different place. The
idea was
> that this transfers data to the GPU (by setting uniforms) so it seemed to
make
> sense to do it from rendering.
> It seems that on the server side the data for the skinning algorithm is
not
> marked as invalid correctly and so the uniforms are not updated.
> So the test on line 246 of GPUSkinningAlgo:
>
> else if(data->getDataValid() == false)
> {
> // update uniforms
> }
>
> is not taken.
> Can you check if on the servers
> {CPU,GPU}SkinningAlgorithm::skeletonChanged() is called and does the
> data->setDataValid(false) call?
>
> Thinking some more about this, even if the call to
> data->setDataValid(false) never happens the servers should still get
> updated data. However, if your application calls
> OSG::commitChangesAndClear() after rendering, all changes that were done
> as part of rendering are lost - the only safe time to clear the
> changelist is immediately after transmitting it, but the ClusterWindow
> lumps the transmit together with rendering so that it is difficult for
> the app to clear the CL at the right time.
> It seems ClusterWindow should have an option (default: true) that
> controls if it clears the changelist after transmitting it.
>
> > (I hope the developer of the Ogre-Skinning node is still reading
this...)
> yup, still here ;)
>
> Cheers,
> Carsten
>
>
----------------------------------------------------------------------------
--
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and
> threat landscape has changed and how IT managers can respond. Discussions
> will include endpoint security, mobile security and the latest in malware
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
> _______________________________________________
> Opensg-users mailing list
> Opensg-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/opensg-users
/*---------------------------------------------------------------------------*\
* OpenSG *
* *
* *
* Copyright (C) 2000-2006 by the OpenSG Forum *
* *
* www.opensg.org *
* *
* contact: d...@opensg.org, gerrit.v...@vossg.org, jb...@zgdv.de *
* *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
* License *
* *
* This library is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Library General Public License as published *
* by the Free Software Foundation, version 2. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*\
* Changes *
* *
* *
* *
* *
* *
* *
\*---------------------------------------------------------------------------*/
//---------------------------------------------------------------------------
// Includes
//---------------------------------------------------------------------------
#include <cstdlib>
#include <cstdio>
#include <OSGConfig.h>
#include "OSGGPUSkinningAlgorithm.h"
#include "OSGGPUSkinningDataAttachment.h"
#include <boost/cast.hpp>
OSG_BEGIN_NAMESPACE
// Documentation for this class is emitted in the
// OSGGPUSkinningAlgorithmBase.cpp file.
// To modify it, please change the .fcd file (OSGGPUSkinningAlgorithm.fcd) and
// regenerate the base file.
/***************************************************************************\
* Class variables *
\***************************************************************************/
const std::string GPUSkinningAlgorithm::_vpVertexSkinning(
"#version 120\n"
"\n"
"uniform mat4 matBindShape;\n"
"uniform mat4 matJoints[85];\n"
""
"void calcSkin(inout vec4 vertPos, inout vec3 vertNorm,\n"
" in vec4 jointIdx, in vec4 jointWeight)\n"
"{\n"
" float sumWinv = 1. / dot(jointWeight, vec4(1., 1., 1., 1.));\n"
" vec4 inNorm = vec4(vertNorm, 0.);\n"
" vec4 tmpPos = vec4(0., 0., 0., 0.);\n"
" vec4 tmpNorm = vec4(0., 0., 0., 0.);\n"
"\n"
" for(int i = 0; i < 4; ++i)\n"
" {\n"
" int idxJ = int(jointIdx[i]);\n"
"\n"
" if(idxJ >= 0)\n"
" {\n"
" mat4 matJ = matJoints[idxJ] * matBindShape;\n"
"\n"
" tmpPos += jointWeight[i] * (matJ * vertPos);\n"
" tmpNorm += jointWeight[i] * (matJ * inNorm);\n"
" }\n"
" }\n"
"\n"
" vertPos = sumWinv * tmpPos;\n"
" vertNorm = sumWinv * tmpNorm.xyz;\n"
"}\n"
"\n"
"void calcSkin(inout vec4 vertPos, inout vec3 vertNorm,\n"
" inout vec3 vertTangent,\n"
" in vec4 jointIdx, in vec4 jointWeight )\n"
"{\n"
" float sumWinv = 1. / dot(jointWeight, vec4(1., 1., 1., 1.));\n"
" vec4 inNorm = vec4(vertNorm, 0.);\n"
" vec4 inTangent = vec4(vertTangent, 0.);\n"
" vec4 tmpPos = vec4(0., 0., 0., 0.);\n"
" vec4 tmpNorm = vec4(0., 0., 0., 0.);\n"
" vec4 tmpTangent = vec4(0., 0., 0., 0.);\n"
"\n"
" for(int i = 0; i < 4; ++i)\n"
" {\n"
" int idxJ = int(jointIdx[i]);\n"
"\n"
" if(idxJ >= 0)\n"
" {\n"
" mat4 matJ = matJoints[idxJ] * matBindShape;\n"
"\n"
" tmpPos += jointWeight[i] * (matJ * vertPos);\n"
" tmpNorm += jointWeight[i] * (matJ * inNorm);\n"
" tmpTangent += jointWeight[i] * (matJ * inTangent);\n"
" }\n"
" }\n"
"\n"
" vertPos = sumWinv * tmpPos;\n"
" vertNorm = sumWinv * tmpNorm.xyz;\n"
" vertTangent = sumWinv * tmpTangent.xyz;\n"
"}\n"
"\n"
"void calcSkin(inout vec4 vertPos, inout vec3 vertNorm,\n"
" inout vec3 vertTangent, inout vec3 vertBinormal,\n"
" in vec4 jointIdx, in vec4 jointWeight )\n"
"{\n"
" float sumWinv = 1. / dot(jointWeight, vec4(1., 1., 1., 1.));\n"
" vec4 inNorm = vec4(vertNorm, 0.);\n"
" vec4 inTangent = vec4(vertTangent, 0.);\n"
" vec4 inBinormal = vec4(vertBinormal, 0.);\n"
" vec4 tmpPos = vec4(0., 0., 0., 0.);\n"
" vec4 tmpNorm = vec4(0., 0., 0., 0.);\n"
" vec4 tmpTangent = vec4(0., 0., 0., 0.);\n"
" vec4 tmpBinormal = vec4(0., 0., 0., 0.);\n"
"\n"
" for(int i = 0; i < 4; ++i)\n"
" {\n"
" int idxJ = int(jointIdx[i]);\n"
"\n"
" if(idxJ >= 0)\n"
" {\n"
" mat4 matJ = matJoints[idxJ] * matBindShape;\n"
"\n"
" tmpPos += jointWeight[i] * (matJ * vertPos);\n"
" tmpNorm += jointWeight[i] * (matJ * inNorm);\n"
" tmpTangent += jointWeight[i] * (matJ * inTangent);\n"
" tmpBinormal += jointWeight[i] * (matJ * inBinormal);\n"
" }\n"
" }\n"
"\n"
" vertPos = sumWinv * tmpPos;\n"
" vertNorm = sumWinv * tmpNorm.xyz;\n"
" vertTangent = sumWinv * tmpTangent.xyz;\n"
" vertBinormal = sumWinv * tmpBinormal.xyz;\n"
"}\n"
);
/***************************************************************************\
* Class methods *
\***************************************************************************/
void GPUSkinningAlgorithm::initMethod(InitPhase ePhase)
{
Inherited::initMethod(ePhase);
if(ePhase == TypeObject::SystemPost)
{
}
}
/***************************************************************************\
* Instance methods *
\***************************************************************************/
/*-------------------------------------------------------------------------*\
- private -
\*-------------------------------------------------------------------------*/
/*----------------------- constructors & destructors ----------------------*/
GPUSkinningAlgorithm::GPUSkinningAlgorithm(void) :
Inherited()
{
}
GPUSkinningAlgorithm::GPUSkinningAlgorithm(const GPUSkinningAlgorithm &source) :
Inherited(source)
{
}
GPUSkinningAlgorithm::~GPUSkinningAlgorithm(void)
{
}
/*----------------------------- class specific ----------------------------*/
void
GPUSkinningAlgorithm::adjustVolume(Volume &volume)
{
if(_sfSkeleton.getValue() != NULL)
_sfSkeleton.getValue()->adjustVolume(volume);
}
Action::ResultE
GPUSkinningAlgorithm::renderEnter(Action *action)
{
Action::ResultE res = Action::Continue;
SkinnedGeometry *skinGeo = getSkin ();
Skeleton *skel = getSkeleton();
RenderAction *ract =
boost::polymorphic_downcast<RenderAction *>(action);
OSG_ASSERT(skinGeo != NULL);
OSG_ASSERT(skel != NULL);
GPUSkinningDataAttachmentUnrecPtr data = getGPUSkinningData(skel);
if(data == NULL)
{
data = GPUSkinningDataAttachment::create();
skel->addAttachment(data);
}
skel->renderEnter(action, skinGeo);
ShaderProgramChunkUnrecPtr shCode = data->getShaderCode();
if(shCode == NULL)
{
shCode = ShaderProgramChunk::create();
data->setShaderCode(shCode);
ShaderProgramUnrecPtr vp = ShaderProgram::createVertexShader();
vp->setProgram(_vpVertexSkinning);
shCode->addShader(vp);
vp->addUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
vp->addUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
}
/*else if(data->getDataValid() == false)
{
ShaderProgram *vp = shCode->getVertexShader(0);
OSG_ASSERT(vp != NULL);
vp->updateUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
vp->updateUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
data->setDataValid(true);
}*/
ract->pushState();
{
ract->addOverride(ShaderProgramChunk::getStaticClassId(),
shCode );
res = skinGeo->SkinnedGeometry::Inherited::renderEnter(ract);
}
ract->popState ();
return res;
}
Action::ResultE
GPUSkinningAlgorithm::renderLeave(Action *action)
{
Action::ResultE res = Action::Continue;
SkinnedGeometry *skinGeo = getSkin();
Skeleton *skel = getSkeleton();
skel->renderLeave(action, skinGeo);
res = skinGeo->SkinnedGeometry::Inherited::renderLeave(action);
return res;
}
Action::ResultE
GPUSkinningAlgorithm::intersectEnter(Action *action)
{
SkinnedGeometry *skinGeo = getSkin();
return skinGeo->SkinnedGeometry::Inherited::intersectEnter(action);
}
GPUSkinningAlgorithm::RenderModeE
GPUSkinningAlgorithm::getRenderMode(void) const
{
return SkinnedGeometry::RMSkinnedGPU;
}
void GPUSkinningAlgorithm::changed(ConstFieldMaskArg whichField,
UInt32 origin,
BitVector details)
{
if((SkeletonFieldMask & whichField) != 0 &&
_sfSkeleton.getValue() != NULL )
{
if(_sfSkeleton.getValue()->hasChangedFunctor(boost::bind(
&GPUSkinningAlgorithm::skeletonChanged,
this, _1, _2, _3 )) == false)
{
_sfSkeleton.getValue()->addChangedFunctor(boost::bind(
&GPUSkinningAlgorithm::skeletonChanged,
this, _1, _2, _3 ),
"GPUSkinningAlgorithm::skeletonChanged");
}
}
Inherited::changed(whichField, origin, details);
}
void GPUSkinningAlgorithm::dump( UInt32 ,
const BitVector ) const
{
SLOG << "Dump GPUSkinningAlgorithm NI" << std::endl;
}
void
GPUSkinningAlgorithm::skeletonChanged(FieldContainer *fc,
ConstFieldMaskArg whichField,
UInt32 origin )
{
// if the skeleton was changed by a sync we don't invalidate
// the data - it either is updated by the same sync or
// the sync marks it as invalid.
if(//origin != ChangedOrigin::Sync &&
((Skeleton::JointMatricesFieldMask |
Skeleton::JointsChangedFieldMask |
Skeleton::JointNormalMatricesFieldMask) & whichField) != 0)
{
OSG_ASSERT(fc == _sfSkeleton.getValue());
GPUSkinningDataAttachment *data =
getGPUSkinningData(_sfSkeleton.getValue());
if(data != NULL) {
ShaderProgramChunkUnrecPtr shCode = data->getShaderCode();
if (shCode!=NULL) {
ShaderProgram *vp = shCode->getVertexShader(0);
// OSG_ASSERT(vp != NULL);
if (vp!=NULL) {
SkinnedGeometry *skinGeo = getSkin ();
Skeleton *skel = getSkeleton();
vp->updateUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
vp->updateUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
}
}
}
}
}
void
GPUSkinningAlgorithm::resolveLinks(void)
{
if(_sfSkeleton.getValue() != NULL)
{
_sfSkeleton.getValue()->subChangedFunctor(boost::bind(
&GPUSkinningAlgorithm::skeletonChanged,
this, _1, _2, _3 ));
}
Inherited::resolveLinks();
}
#if 0
// renderEnter code that does not work because of problems with the
// way ProgVars are handled and how uniform locations are invalidated
ShaderProgramChunkUnrecPtr shCode = getShaderCode();
ShaderProgramVariableChunkUnrecPtr shData = getShaderData();
if(shCode == NULL)
{
shCode = ShaderProgramChunk::create();
setShaderCode(shCode);
ShaderProgramUnrecPtr vp = ShaderProgram::createVertexShader();
vp->setProgram(_vpVertexSkinning);
shCode->addShader(vp);
vp->addUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
vp->addUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
}
else
{
ShaderProgram *vp = shCode->getVertexShader(0);
vp->updateUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
vp->updateUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
}
#if 0
if(shData == NULL)
{
shData = ShaderProgramVariableChunk::create();
setShaderData(shData);
shData->addUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
shData->addUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
}
else
{
shData->updateUniformVariable(
"matBindShape", skinGeo->getBindShapeMatrix());
shData->updateUniformVariable(
"matJoints", (*skel->getMFJointMatrices()));
}
#endif
#endif
OSG_END_NAMESPACE
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users