Add a sceneNode as tree?

bharling

11-01-2008 23:52:22

Hi,

Many thanks for this awesome addon JonJ

Now my question: Is it possible to add a sceneNode instead of an entity as a tree model? The tree models I wish to use are procedural and consist of both a mesh and a bilboardSet. Or is it possible to join a billboard set to an entity in Ogre? probably the wrong forum for that.


cheers,!

JohnJ

12-01-2008 00:47:07

A tree built out of a Mesh and a BillboardSet won't really work with PagedGeometry because PagedGeometry only accepts plain Mesh-style geometry.

What you'd want to do is, like you said, convert the billboard set to a mesh, and combine that with the mesh entity. Assuming the billboard set is used as camera-facing leaves, combining them is possible through the use of vertex shaders and a bit of coding. Unfortunately PagedGeometry doesn't do this for you currently, so you'd have to code it manually (which could be difficult if you don't know how, obviously). I may later add support for camera-facing leaves into PagedGeometry, but unfortunately I can't estimate when.

bharling

12-01-2008 10:40:20

Thanks JohnJ,

thats kind of what I thought, but thanks for clarifying. I've got a rough idea and some examples of billboard vertex shaders lying around, so I'll give that a go. So pagedGeomtry doesn't bypass shaders when rendering imposters etc. ?

bharling

14-01-2008 14:00:55

Ok, I did as you suggested, and used a vertex shader to create billboard leaves. This works fine, the leaves are properly oriented, and they get that orientation from the view matrix in the shader, so theres no need to update the shader parameters per frame. The imposters for these are generated correctly, with the leaves always facing the camera. Unfortunately, when the trees get to the 'Batch' level of detail, the leaves dissapear. I'm guessing that tree batches are staticGeometry objects, which don't allow vertex manipulation in a shader? Is this the case, and if so is there any way around it?

In case it helps, I'm creating the leaves as randomly positioned groups of four verts. The verts in each group all have the same position, and the shader applied to them uses the vert's uv coordinates along with the view matrix to convert the four verts into a camera-facing quad.

EDIT:
I see from the source code that the material is replaced during the batching operation. Is there any way to change this so that batch fading material is added as another pass?

JohnJ

14-01-2008 16:02:26

I see from the source code that the material is replaced during the batching operation. Is there any way to change this so that batch fading material is added as another pass?
PagedGeometry shouldn't replace the material's shader if one already exists (if not there may be a bug). You should be able to use your own shader but it will have to accept all the fade / color / etc. parameters the automatic batch fade shader uses in order to be compatible.

Unfortunately it's really hard to integrate multiple custom shaders like this and I don't know of an easier way that wouldn't sacrifice performance (like adding an extra pass would).

bharling

26-01-2008 12:13:09

Sorry to resurrect this, but I'm getting tantalizingly close to solving this now, but just cant figure out how to proceed.

So, what I've done:

Used calunetree to generate tree meshes
replaced the billboard leaves with my own mesh generation code and a billboard shader that renders the leaves as billboards, but as part of the mesh instead.
added an empty pass 0 into the leaf material, so that the billboard vertex program is loaded into the second pass, which theoretically should allow pagedGeometry to load its shader into the first pass without affecting things.

results:
imposters render correctly, nice billboarded leaves.
Unfortunately when you get close to a tree, the leaves fade out.

Heres my material file, and the billboard shader in case anyone can help!

billboardleaves.material:

vertex_program billBoardLeaves_vp cg
{
source leafboards.cg
entry_point billVertShader

profiles vs_2_0 arbvp1

default_params
{

param_named_auto wvp worldviewproj_matrix
param_named_auto viewUp view_up_vector
param_named_auto viewSide view_side_vector
param_named_auto lightPosition light_position_object_space 0
param_named_auto lightDiffuse light_diffuse_colour 0
param_named BillboardHeight float 3.0
param_named BillboardWidth float 3.0

}
}

fragment_program billBoardLeaves_fp cg
{
source leafboards.cg
entry_point billPixShader
profiles ps_2_0 arbfp1
}

material leavesBillBoards
{
technique
{
pass
{
cull_hardware none
cull_software none
scene_blend alpha_blend
}
pass
{
cull_hardware none
cull_software none
scene_blend alpha_blend
alpha_rejection greater 128
vertex_program_ref billBoardLeaves_vp
{
}
fragment_program_ref billBoardLeaves_fp
{
}

texture_unit leaf
{
texture tree_bush.png
}

}
}
}


leafboards.cg:

void billVertShader(
float3 Position : POSITION0,
float3 Normal : NORMAL0,
float2 TexCoord : TEXCOORD0,
uniform float4x4 wvp,
uniform float3 viewUp,
uniform float3 viewSide,
uniform float4 lightPosition,
uniform float4 lightDiffuse,
uniform float BillboardHeight,
uniform float BillboardWidth,
out float4 oPos : POSITION,
out float2 oTexCoord : TEXCOORD0,
out float4 oColor : COLOR0)
{
float width = BillboardWidth;
float height = BillboardHeight;
float3 position = Position;
position += viewSide * (TexCoord.x - 0.5) * BillboardWidth;
position += viewUp * (1 - TexCoord.y) * BillboardHeight;
float4 vPos = float4(position, 1);
oPos = mul(wvp, vPos);
oTexCoord = TexCoord;
float diffuseLight = max(-dot(Normal, lightPosition), 0);
oColor.rgb = diffuseLight * lightDiffuse + 0.5;
oColor.a = 1;
}

void billPixShader(float2 texCoord : TEXCOORD0,
float4 color : COLOR0,
uniform sampler2D TextureSampler,

out float4 oCol: COLOR)
{
float4 col = tex2D(TextureSampler, texCoord);
oCol = col * color;
}


so, as you can see the first pass is empty, ready to be modified by pagedGeometry, but sadly this still doesn't work.

If theres no way to work around this, can I humbly make a feature request for a future version :) ?

With a view to aiding that feature request - heres the code I use to create the leaf geometry (its in python, but is almost identical to what you'd do in c++ i think. The manObj passed into this function is the result of the calunetree trunk generation) -

def createLeaves(self, manObj=None):
nl = 0
lVerts = []
lNormals = []
lUVs = []
lTriangles = []
if not manObj:
leafObj = self.sceneManager.createManualObject("leaves_mesh")
else:
leafObj = manObj
leafObj.begin("leavesBillBoards")
centre = ogre.Vector3(0.0, 1.0, 1.0)
uvs = [ [0.0, 0.0], [1.0, 1.0], [0.0, 1.0], [1.0, 0.0] ]
leafRadius = 4.0
for i in range(46):
x = random.uniform(-leafRadius, leafRadius)
y = random.uniform(-leafRadius, leafRadius)
z = random.uniform(-leafRadius, leafRadius)
vPos = [x, y+6, z]
triA = [nl, nl+2, nl+3]
triB = [nl+1, nl+2, nl+3]
norm = centre - ogre.Vector3(vPos)
norm.normalise()
for i in range(4):
leafObj.position( vPos )
leafObj.normal( norm )
leafObj.textureCoord( uvs[i] )

leafObj.triangle( *triA )
leafObj.triangle( *triB )
nl += 4

leafObj.end()
return leafObj




thanks and sorry for the biblical sized post,

JohnJ

26-01-2008 17:41:24

I'm not sure why your leaves aren't appearing at all, but your vertex shader needs to be able to handle the fade values given to it by PagedGeometry to function properly. Adding a second pass isn't going to help since fading is applied to all passes.

Here's a version of your shaders with proper fading added:
void billVertShader(
float3 Position : POSITION0,
float3 Normal : NORMAL0,
float2 TexCoord : TEXCOORD0,
uniform float4x4 wvp,
uniform float3 viewUp,
uniform float3 viewSide,
uniform float4 lightPosition,
uniform float4 lightDiffuse,
uniform float BillboardHeight,
uniform float BillboardWidth,

uniform float3 camPos,
uniform float fadeGap,
uniform float invisibleDist,

out float4 oPos : POSITION,
out float2 oTexCoord : TEXCOORD0,
out float4 oColor : COLOR0,
out float4 oFog : FOG)
{
float width = BillboardWidth;
float height = BillboardHeight;
float3 position = Position;
position += viewSide * (TexCoord.x - 0.5) * BillboardWidth;
position += viewUp * (1 - TexCoord.y) * BillboardHeight;
float4 vPos = float4(position, 1);
oPos = mul(wvp, vPos);
oTexCoord = TexCoord;
float diffuseLight = max(-dot(Normal, lightPosition), 0);
oColor.rgb = diffuseLight * lightDiffuse + 0.5;

float dist = distance(camPos.xz, Position.xz);
oColor.a = (invisibleDist - dist) / fadeGap;
oFog.x = oPos.z;
}

void billPixShader(float2 texCoord : TEXCOORD0,
float4 color : COLOR0,
uniform sampler2D TextureSampler,

out float4 oCol: COLOR)
{
float4 col = tex2D(TextureSampler, texCoord);
oCol = col * color;
}


I'm not sure if this will fix the problem yet (since I haven't tested custom shaders with BatchPage yet), but I'm sure we'll be able to solve this eventually :)

bharling

26-01-2008 18:31:22

thanks JohnJ,

didn't work unfortunately, but thanks for trying! ( TBH all i did was replace the shader without actually modifying pagedGeometry, so it was unlikely to work anyway ).

would be great to see this sometime in the future, as bilboard leaves look so much more realistic than polygons.