shader - setNamedConstant

bharling

26-10-2007 17:39:08

In my continuing efforts to make a cool forests (and other technologies) demo for python-ogre, I'm trying to implement the excellent leaves shader demonstrated in 'legends of tracendia', for which the sourcecode has been published in the showcase forum. I've hit a problem with setNamedConstant which may be a PO bug, or may be my limited idea of c++ data types. Basically in the example, an array or floats is passed to the shader every frame, representing the camera view plane, so that the leaf billboard meshes are aligned to face the camera. I've converted the relevent bit of code to python, but it seems that ogre no longer accepts an array of floats, and wants a matrix object instead. However, with a matrix instead i just end up with a crash. Heres the original C++ code, followed by my python mashup. Can anyone tell if its right?

As far as I can tell, the shader that is referenced is fine, as the ogre.log contains none of the compile errors I usually see if a shader is wrong. Also the crash only occurs when I actually load the leaves mesh, (and theres no exception anywhere that I can see). If I don't load the mesh then everything works, but obviously no leaves get displayed, which leads me to believe that the material is recieving the updated params every frame just fine.

Alternatively I guess ogreforests might not support shaders on meshes that are to be batched, as the error seems to be occuring in ogreforests.pyd

C++

Vector3 vCenter( 0.0f, 0.0f, 0.0f );
Vector3 forward = mCamera->getDerivedDirection();
Vector3 vRight = forward.crossProduct(Vector3::UNIT_Y);
Vector3 vUp = mCamera->getUp();
vRight.normalise();
vUp.normalise();

Vector3 vPoint0 = vCenter + (-vRight - vUp);
Vector3 vPoint1 = vCenter + ( vRight - vUp);
Vector3 vPoint2 = vCenter + ( vRight + vUp);
Vector3 vPoint3 = vCenter + (-vRight + vUp);

//single prerotated quad oriented towards the camera
float preRotatedQuad[16] =
{
vPoint0.x, vPoint0.y, vPoint0.z, 0.0f,
vPoint1.x, vPoint1.y, vPoint1.z, 0.0f,
vPoint2.x, vPoint2.y, vPoint2.z, 0.0f,
vPoint3.x, vPoint3.y, vPoint3.z, 0.0f
};

//iterate through materials
for(uint i = 0; i < mMaterials.size(); ++i)
{
//currently assumes in first technique
if(!mMaterials[i].isNull() && mMaterials[i]->getTechnique(0)->getPass(0)->hasVertexProgram())
{

}
GpuProgramParametersSharedPtr params = mMaterials[i]->getTechnique(0)->getPass(0)->getVertexProgramParameters();
params->setNamedConstant("preRotatedQuad[0]", preRotatedQuad, 16);
}


Python

vCenter = ogre.Vector3( 0.0, 0.0, 0.0 )
forward = self.app.camera.getDerivedDirection()
vRight = forward.crossProduct(ogre.Vector3.UNIT_Y)
vUp = self.app.camera.getUp()
vRight.normalise()
vUp.normalise()

vPoint0 = vCenter + (-vRight - vUp)
vPoint1 = vCenter + ( vRight - vUp)
vPoint2 = vCenter + ( vRight + vUp)
vPoint3 = vCenter + (-vRight + vUp)

#single prerotated quad oriented towards the camera
preRotatedQuad = ogre.Matrix4(
vPoint0.x, vPoint0.y, vPoint0.z, 0.0,
vPoint1.x, vPoint1.y, vPoint1.z, 0.0,
vPoint2.x, vPoint2.y, vPoint2.z, 0.0,
vPoint3.x, vPoint3.y, vPoint3.z, 0.0
)

self.mActiveVertexParameters.setNamedConstant("preRotatedQuad[0]", preRotatedQuad, 16)


Note that I'm not iterating through materials in my version, as I grab a reference to the right material in the __init__ of the framelistener.

Finally heres the shader in case that might be the problem.

void LOTTreeLeavesNoBones_vp(
float4 position : POSITION,
float4 uv : TEXCOORD0,
float4 colour : COLOR,
out float4 oPosition : POSITION,
out float2 oUv : TEXCOORD0,
out float4 oColour : COLOR,
uniform float4x4 worldViewProj,
uniform float4 preRotatedQuad[4] )

{

float4 vCenter = float4( position.x, position.y, position.z, 1.0f );

oPosition = mul( worldViewProj, vCenter + preRotatedQuad[uv.z] * uv.w );

uv.z = 0.0f;
uv.w = 1.0f;

oColour = colour;
oUv = uv;

}


As always, any help from the more technically minded appreciated! and sorry for the lengthy post....

andy

27-10-2007 00:01:02

The problem is likely to be that you are passing the address of a Matrix Class instead of the address of a float[16] array. Try something like
FloatArray16 = ctypes.c_float * 16
preRotatedQuad = FloatArray16(
vPoint0.x, vPoint0.y, vPoint0.z, 0.0,
vPoint1.x, vPoint1.y, vPoint1.z, 0.0,
vPoint2.x, vPoint2.y, vPoint2.z, 0.0,
vPoint3.x, vPoint3.y, vPoint3.z, 0.0
)
self.mActiveVertexParameters.setNamedConstant("preRotatedQuad[0]", ctypes.addressof(preRotatedQuad), 16)

Andy

kungfoomasta

27-10-2007 00:31:30

tacendia or tracendia? I can't find any source code.. link? :)

bharling

28-10-2007 19:27:22

heres the link to the code I'm trying to get working. I think i may be flogging a dead horse though because it seems like its a bit out of date.

http://www.ogre3d.org/phpBB2/viewtopic.php?t=24918&postdays=0&postorder=asc&highlight=prerotatedquad&start=25

Thanks Andy, I'm trying that out now