I have this modified tree billboard shader where I’ve fixed the alpha so it’s cutout, and I’m trying to lock the billboard rotation to only the Y axes, currently when I look up or down with the first person controller the billboarded trees follow really wierdly. I know this has to be possible because when I roll the camera the trees do not roll with it.
I’ve tried modifying the position code but It either throws up a load of errors or the trees disappear. I’m at a loss and would much appreciate a fix. I have a feeling that I may need to go bounty hunting somewhere else, if I do then where do I need to go?
This is the code in TerrainEngine.cginc if there’s anything I need to change in there instead.
void TerrainBillboardTree( inout float4 pos, float2 offset, float offsetz )
{
float3 treePos = pos.xyz - _TreeBillboardCameraPos.xyz;
float treeDistanceSqr = dot(treePos, treePos);
if( treeDistanceSqr > _TreeBillboardDistances.x )
offset.xy = offsetz = 0.0;
// positioning of billboard vertices horizontally
pos.xyz += _TreeBillboardCameraRight.xyz * offset.x;
// tree billboards can have non-uniform scale,
// so when looking from above (or bellow) we must use
// billboard width as billboard height
// 1) non-compensating
//pos.xyz += _TreeBillboardCameraUp.xyz * offset.y;
// 2) correct compensating (?)
//float alpha = _TreeBillboardCameraPos.w;
//float a = offset.y;
//float b = offsetz;
//2a) using elipse-radius formula
//float r = abs(a * b) / sqrt(sqr(a * sin(alpha)) + sqr(b * cos(alpha))) * sign(b);
//float r = abs(a) * b / sqrt(sqr(a * sin(alpha)) + sqr(b * cos(alpha)));
//2b) sin-cos lerp
//float r = b * sin(alpha) + a * cos(alpha);
// pos.xyz += _TreeBillboardCameraUp.xyz * r;
// 3) incorrect compensating (using lerp)
// _TreeBillboardCameraPos.w contains ImposterRenderTexture::GetBillboardAngleFactor()
//float billboardAngleFactor = _TreeBillboardCameraPos.w;
//float r = lerp(offset.y, offsetz, billboardAngleFactor);
//pos.xyz += _TreeBillboardCameraUp.xyz * r;
// so now we take solution #3 and complicate it even further...
//
// case 49851: Flying trees
// The problem was that tree billboard was fixed on it's center, which means
// the root of the tree is not fixed and can float around. This can be quite visible
// on slopes (checkout the case on fogbugz for screenshots).
//
// We're fixing this by fixing billboards to the root of the tree.
// Note that root of the tree is not necessary the bottom of the tree -
// there might be significant part of the tree bellow terrain.
// This fixation mode doesn't work when looking from above/below, because
// billboard is so close to the ground, so we offset it by certain distance
// when viewing angle is bigger than certain treshold (40 deg at the moment)
// _TreeBillboardCameraPos.w contains ImposterRenderTexture::billboardAngleFactor
float billboardAngleFactor = _TreeBillboardCameraPos.w;
// The following line performs two things:
// 1) peform non-uniform scale, see "3) incorrect compensating (using lerp)" above
// 2) blend between vertical and horizontal billboard mode
float radius = lerp(offset.y, 0, billboardAngleFactor);
// positioning of billboard vertices veritally
pos.xyz += _TreeBillboardCameraUp.xyz * radius;
// _TreeBillboardCameraUp.w contains ImposterRenderTexture::billboardOffsetFactor
float billboardOffsetFactor = _TreeBillboardCameraUp.w;
// Offsetting billboad from the ground, so it doesn't get clipped by ztest.
// In theory we should use billboardCenterOffsetY instead of offset.x,
// but we can't because offset.y is not the same for all 4 vertices, so
// we use offset.x which is the same for all 4 vertices (except sign).
// And it doesn't matter a lot how much we offset, we just need to offset
// it by some distance
pos.xyz += _TreeBillboardCameraFront.xyz * abs(offset.x) * billboardOffsetFactor;
}
Thanks for pointing out the TerrainEngine.cginc
No have not t solved it so far, but i interested in improving the tree billboard / transitions from 3d to 2d , so i have maybe a chance now.
Edit:
My best bet is that this line is changing the vertical rotation
TerrainEngine.cginc
// positioning of billboard vertices veritally
pos.xyz += _TreeBillboardCameraUp.xyz * radius;
maybe to set the radius to 0 or disable the line at all could do the trick.
I think it’s crazy that this issue still hasn’t been addressed by Unity devs. I’ve searched high and low for an actual fix to the built in billboarding, and this seems to be the only thread that’s looking in the right direction. Quite often this question ends with someone pointing to Advanced Foliage Shader, which is fine, but why should Unity’s built in tree billboard shader stay broken for years?
Anyway I’m completely new to Unity and shader code, but I managed to stop the billboards from tilting by modifying the line in TerrainEngine.cginc that fffMalzbier mentioned:
This stops the x and z tilting which makes these billboards a lot more usable! I haven’t been able to work out how to stop the height from scaling with the camera angle though.
So if someone more knowledgeable can help to give this thread a more final solution that would be great.
With this change the Terrain setting “Fade Length” has to be 0 otherwise the mesh trees that fade into billboards still tilt. I don’t think there’s any need for fading if the billboards don’t move with the camera though.