Question about use of shader for the billboard effect
-
- Goblin
- Posts: 211
- Joined: Sat Jan 23, 2016 11:26 am
- x 17
Question about use of shader for the billboard effect
Ogre Version: 1.11.8
Operating System: win10
Render System: dx9
I managed to use the entity buffer for obtain the billboard rotation effect (I cannot use the normal billboardset because of camera distance problem, billboard of different sets are ordered on the base of set position not of their position). Naturally with the entities are many like in my test the fps drop significantly. Now I wanted to try to replicate it using shaders HLSL, how much i could expect to have performances improved using them? little, much or very much? thanks
Operating System: win10
Render System: dx9
I managed to use the entity buffer for obtain the billboard rotation effect (I cannot use the normal billboardset because of camera distance problem, billboard of different sets are ordered on the base of set position not of their position). Naturally with the entities are many like in my test the fps drop significantly. Now I wanted to try to replicate it using shaders HLSL, how much i could expect to have performances improved using them? little, much or very much? thanks
-
- Gnoll
- Posts: 619
- Joined: Wed Mar 18, 2009 3:03 am
- x 355
Re: Question about use of shader for the billboard effect
What is an entity buffer specifically? Are they instanced entities? Can you show some code that shows exactly how you are rendering this?
Otherwise it will be very hard to know how a HLSL shader could make it faster or not.
Also, different billboardsets will sort independently (like particles also do) as you say, but if you use an atlas texture you can instead have all different kind of textures in one billboardset, which would sort correctly towards each other. Though as I guess the billboards are transparent, it would probably not sort correctly towards any other transparent object in the scene since it would still just sort from its position and not per-billboard.
I thought of making such a system for my game, a master class that overrides the particle system completely that batches everything together as one with an atlas texture for all the particle textures. The problem with that is different blending modes, because then you need two of these "master" classes, which will mess up with the sorting between them (alpha_blend vs add for example).
And of course, sorting it towards any other transparent object in the scene would not work either correctly for the same reasons as above.
So in the end I was happy with 1 batch per particle system (as it is per default).
Otherwise it will be very hard to know how a HLSL shader could make it faster or not.
Also, different billboardsets will sort independently (like particles also do) as you say, but if you use an atlas texture you can instead have all different kind of textures in one billboardset, which would sort correctly towards each other. Though as I guess the billboards are transparent, it would probably not sort correctly towards any other transparent object in the scene since it would still just sort from its position and not per-billboard.
I thought of making such a system for my game, a master class that overrides the particle system completely that batches everything together as one with an atlas texture for all the particle textures. The problem with that is different blending modes, because then you need two of these "master" classes, which will mess up with the sorting between them (alpha_blend vs add for example).
And of course, sorting it towards any other transparent object in the scene would not work either correctly for the same reasons as above.
So in the end I was happy with 1 batch per particle system (as it is per default).
My project: https://imagindar.com/
-
- Goblin
- Posts: 211
- Joined: Sat Jan 23, 2016 11:26 am
- x 17
Re: Question about use of shader for the billboard effect
Normal entities, not instanced.
Well essentially is a normal vertexbuffer change
Make some test i verified this part impact only for 3/4 fps in the drop of performance when I have many entities, is the rendering itself heavy, because using billboard the performance raise. The main problem of billboard is that the deep check is not at level of single billboard but of billboardset, when different billboardsets mixes the overlapping of billboard is not always respectful of 3d position of billboard. so perhaps i'll switch to entities for near views, using billboard for long distance view if possible.
I want try also with instanced entities, the only problem I verified is that they too didn't respect the deep check automatically on the base of node position in the space, perhaps is my error and something is missing in the shader.
Well essentially is a normal vertexbuffer change
Code: Select all
// Shortcut to main buffer (positions, colours, texture coords)
Ogre::HardwareVertexBufferSharedPtr mMainBuf;
Ogre::VertexData* vertexdata = subentity->getVertexDataForBinding();
mMainBuf = vertexdata->vertexBufferBinding->getBuffer(0);
mLockPtr = static_cast<float*>(
mMainBuf->lock(0, mMainBuf->getVertexSize() * 4,
mMainBuf->getUsage() & Ogre::HardwareBuffer::HBU_DYNAMIC ?
Ogre::HardwareBuffer::HBL_DISCARD : Ogre::HardwareBuffer::HBL_NORMAL));
for (int i = 0; i < mMainBuf->getNumVertices(); i++)
{
*mLockPtr++ = vOwnOffset[i].x;
*mLockPtr++ = vOwnOffset[i].y;
*mLockPtr++ = vOwnOffset[i].z;
//mLockPtr++;
//mLockPtr++;
//mLockPtr++;
// mLockPtr++;
mLockPtr++;
mLockPtr++;
mLockPtr++;
if (i == 2)
{
// Texture coords
*mLockPtr++ = u0;
*mLockPtr++ = v0;
}
if (i == 3)
{
// Texture coords
*mLockPtr++ = u0;
*mLockPtr++ = v1;
}
if (i == 0)
{
// Texture coords
*mLockPtr++ = u1;
*mLockPtr++ = v0;
}
if (i == 1)
{
// Texture coords
*mLockPtr++ = u1;
*mLockPtr++ = v1;
}
}
mMainBuf->unlock();
I want try also with instanced entities, the only problem I verified is that they too didn't respect the deep check automatically on the base of node position in the space, perhaps is my error and something is missing in the shader.
-
- Gnoll
- Posts: 619
- Joined: Wed Mar 18, 2009 3:03 am
- x 355
Re: Question about use of shader for the billboard effect
You are correct, rendering it using instancing would also be in one single batch, which would make their transparency sorting bad compared to other transparent objects in the scene.
You can not solve your issue by altering their HLSL code, as the bottleneck has nothing to do with rendering their pixels, instead it has to do with their batches count.
The issue with having many entities like you try right now is that you get too many batches. If you render 1000 billboards with each billboard as a separate entity/draw call, it will be using 1000 batches. That is very, very heavy on the CPU, since a bottleneck exists between the CPU and the GPU when it comes to batches.
My game has around 100 batches in a normal level when moving around, which is very small. So compare that to 1000 batches to just a particle system using each billboard as a draw call, that is the same as rendering my game 10 times when it comes to draw calls.
But of course, using instancing/batching will make the transparency bad compared to other transparent objects in the scene.
Path of Exile solved this issue by using alpha rejection (Ogre example: alpha_rejection greater 0) or additive blending (Ogre example: scene_blend add) on almost everything in their game instead of alpha blending (Ogre example: scene_blend alpha_blend).
By doing that, all additive blending objects fit together nicely as they don't even have to be sorted, then the alpha rejection will just be a normal object without any blending (like any 3D object really).
Any deferred shading games can also solve it like above for sure (though I am not even sure Path of Exile is using deferred shading).
Here are some other people talking about it:
https://www.khronos.org/opengl/wiki/Tra ... cy_Sorting
https://stackoverflow.com/questions/232 ... t-problems
https://forums.unrealengine.com/t/trans ... ng/84572/3
http://casual-effects.blogspot.com/2014 ... ndent.html
https://jcgt.org/published/0002/02/09/
You can not solve your issue by altering their HLSL code, as the bottleneck has nothing to do with rendering their pixels, instead it has to do with their batches count.
The issue with having many entities like you try right now is that you get too many batches. If you render 1000 billboards with each billboard as a separate entity/draw call, it will be using 1000 batches. That is very, very heavy on the CPU, since a bottleneck exists between the CPU and the GPU when it comes to batches.
My game has around 100 batches in a normal level when moving around, which is very small. So compare that to 1000 batches to just a particle system using each billboard as a draw call, that is the same as rendering my game 10 times when it comes to draw calls.
But of course, using instancing/batching will make the transparency bad compared to other transparent objects in the scene.
Path of Exile solved this issue by using alpha rejection (Ogre example: alpha_rejection greater 0) or additive blending (Ogre example: scene_blend add) on almost everything in their game instead of alpha blending (Ogre example: scene_blend alpha_blend).
By doing that, all additive blending objects fit together nicely as they don't even have to be sorted, then the alpha rejection will just be a normal object without any blending (like any 3D object really).
Any deferred shading games can also solve it like above for sure (though I am not even sure Path of Exile is using deferred shading).
Here are some other people talking about it:
https://www.khronos.org/opengl/wiki/Tra ... cy_Sorting
https://stackoverflow.com/questions/232 ... t-problems
https://forums.unrealengine.com/t/trans ... ng/84572/3
http://casual-effects.blogspot.com/2014 ... ndent.html
https://jcgt.org/published/0002/02/09/
My project: https://imagindar.com/
-
- OGRE Team Member
- Posts: 1995
- Joined: Sun Mar 30, 2014 2:51 pm
- x 1075
- Contact:
Re: Question about use of shader for the billboard effect
there is also order independent transparency, see:
https://www.ogre3d.org/2021/08/14/ogre- ... _additions
https://www.ogre3d.org/2021/08/14/ogre- ... _additions
-
- Goblin
- Posts: 211
- Joined: Sat Jan 23, 2016 11:26 am
- x 17
Re: Question about use of shader for the billboard effect
thanks, i'm trying to understand how they works, in particular is a little obscure to me the alpha rejection concept, i'm trying to understand better reading the documentation you linked. One question I saw in the ogre documentation alpha rejection works only with fixed pipeline or RTSS, so is not possible use it with instancedentities, because they use shaders, correct?rpgplayerrobin wrote: ↑Wed Jan 26, 2022 11:53 pm Path of Exile solved this issue by using alpha rejection (Ogre example: alpha_rejection greater 0) or additive blending (Ogre example: scene_blend add) on almost everything in their game instead of alpha blending (Ogre example: scene_blend alpha_blend).
By doing that, all additive blending objects fit together nicely as they don't even have to be sorted, then the alpha rejection will just be a normal object without any blending (like any 3D object really).
Any deferred shading games can also solve it like above for sure (though I am not even sure Path of Exile is using deferred shading).
Here are some other people talking about it:
https://www.khronos.org/opengl/wiki/Tra ... cy_Sorting
https://stackoverflow.com/questions/232 ... t-problems
https://forums.unrealengine.com/t/trans ... ng/84572/3
http://casual-effects.blogspot.com/2014 ... ndent.html
https://jcgt.org/published/0002/02/09/
-
- Gnoll
- Posts: 619
- Joined: Wed Mar 18, 2009 3:03 am
- x 355
Re: Question about use of shader for the billboard effect
The documentation has mostly to do with that this problem is a known problem, and it is a real problem in rendering overall. Paroj also had the same idea as some of the links, and it is cool that it works in ogre 1.13 (though I am not sure how it works here).
Alpha rejection can be used for anything.
The concept is that you can alter their alpha rejection values in the material/shader and discard a pixel when it is not needed.
You render them as normal solid objects, so you don't use anything like "scene_blend X" or "depth_write off".
The beauty of it is that you can also then use them to render shadows very easily if you just specifiy a custom shader for the shadow caster of the material.
I even have them working for particles in my game, in the shader you know the color values (alpha channel for example) and then just test that against the alpha rejection value.
If you want them working for batched objects, you need to handle them almost like particles. That means you need to specify a per-vertex value to their mesh, per frame, that controls their alpha rejection.
So if you just do it with instanced geometry using entities, it will be pretty hard to do, since you cannot change individual entities vertices like that. But since you only want quads (or simple objects at least) you can just render them using a manual object and set their color per-vertex that controls their alpha rejection in the shader.
An example of using alpha rejection in my application for particles:
Shader material:
HLSL code:
Particle material:
Example of a particle script that shows it in use:
Alpha rejection can be used for anything.
The concept is that you can alter their alpha rejection values in the material/shader and discard a pixel when it is not needed.
You render them as normal solid objects, so you don't use anything like "scene_blend X" or "depth_write off".
The beauty of it is that you can also then use them to render shadows very easily if you just specifiy a custom shader for the shadow caster of the material.
I even have them working for particles in my game, in the shader you know the color values (alpha channel for example) and then just test that against the alpha rejection value.
If you want them working for batched objects, you need to handle them almost like particles. That means you need to specify a per-vertex value to their mesh, per frame, that controls their alpha rejection.
So if you just do it with instanced geometry using entities, it will be pretty hard to do, since you cannot change individual entities vertices like that. But since you only want quads (or simple objects at least) you can just render them using a manual object and set their color per-vertex that controls their alpha rejection in the shader.
An example of using alpha rejection in my application for particles:
Shader material:
Code: Select all
vertex_program FixedFunctionShader_DiffuseVertexColorAlphaRejection_VS hlsl
{
source FixedFunctionShader_DiffuseVertexColorAlphaRejection.hlsl
entry_point main_vs
target vs_3_0
default_params
{
param_named_auto modelViewProj worldviewproj_matrix
param_named_auto texturemat texture_matrix 0
}
}
fragment_program FixedFunctionShader_DiffuseVertexColorAlphaRejection_PS hlsl
{
source FixedFunctionShader_DiffuseVertexColorAlphaRejection.hlsl
entry_point main_ps
target ps_3_0
default_params
{
param_named_auto fogColour fog_colour
param_named_auto fogParams fog_params
param_named_auto eyePosition camera_position_object_space
}
}
HLSL code:
Code: Select all
float4x4 modelViewProj;
float4x4 texturemat;
struct VS_OUTPUT
{
float4 oVertexPos : TEXCOORD0;
float2 oUV : TEXCOORD1;
float4 oVertexColour : TEXCOORD2;
};
VS_OUTPUT main_vs( float4 position : POSITION,
out float4 oPosition : POSITION,
float2 iUV : TEXCOORD0,
float4 vertexColour : COLOR0 )
{
VS_OUTPUT Out;
oPosition = mul(modelViewProj, position);
Out.oVertexPos = position;
Out.oUV = iUV;
Out.oUV = mul(texturemat,float4(Out.oUV,0,1)).xy;
Out.oVertexColour = vertexColour;
return Out;
}
float4 fogColour;
float4 fogParams;
float3 eyePosition;
sampler DiffuseMap : register(s0);
float4 main_ps( float4 position : TEXCOORD0,
float2 uv : TEXCOORD1,
float4 vertexColour : TEXCOORD2 ) : COLOR0
{
float4 color = tex2D(DiffuseMap, uv);
color.xyz *= vertexColour.xyz;
if(color.w <= 1.0 - vertexColour.w)
{
discard;
}
float fogEnabled = fogParams.x; // x is expDensity, which holds whether or not it is enabled
float fogStart = fogParams.y * fogParams.y;
float fogEnd = fogParams.z * fogParams.z;
float3 squaredLengthVec = eyePosition - position.xyz;
float squaredLength = dot(squaredLengthVec, squaredLengthVec);
float fogFactor = (1.0 - saturate((fogEnd - squaredLength) / (fogEnd - fogStart))) * fogEnabled;
color.xyz = lerp(color.xyz, fogColour.xyz, fogFactor);
return color;
}
Particle material:
Code: Select all
material AlphaRejection0
{
technique
{
pass
{
lighting off
alpha_rejection greater 0
vertex_program_ref FixedFunctionShader_DiffuseVertexColorAlphaRejection_VS
{
}
fragment_program_ref FixedFunctionShader_DiffuseVertexColorAlphaRejection_PS
{
}
texture_unit
{
texture smoke_0.tga
tex_address_mode clamp
}
}
}
}
Example of a particle script that shows it in use:
Code: Select all
particle_system testParticle
{
quota 700
material AlphaRejection0
particle_width 0.3
particle_height 0.3
cull_each false
renderer billboard
sorted true
local_space false
iteration_interval 0
nonvisible_update_timeout 0
billboard_type point
billboard_origin center
//billboard_origin bottom_right
billboard_rotation_type vertex
//billboard_rotation_type texcoord
common_up_vector 0 1 0
point_rendering false
accurate_facing true
emitter Ring
{
angle 6
colour 1 1 1 1
direction 0 0 -1
emission_rate 700
position 0 0 0
velocity_min 3
velocity_max 4
time_to_live 1
duration 0
duration_min 0
duration_max 0
repeat_delay 0
repeat_delay_min 0
repeat_delay_max 0
width 1.2
height 1.2
depth 0
inner_width 0.7
inner_height 0.7
}
affector LinearForce
{
force_vector 0 0 2.5
force_application add
}
affector Rotator
{
rotation_speed_range_start -720
rotation_speed_range_end 720
rotation_range_start 0
rotation_range_end 360
}
affector ColourInterpolator
{
time0 0
colour0 0.9 0.2 0.2 0
time1 0
colour1 0.9 0.2 0.2 0
time2 0.1
colour2 0.9 0.2 0.2 0.8 // Real colour here
time3 0.8
colour3 0.2 0.1 0.1 0.5
time4 1
colour4 0.2 0.1 0.1 0
time5 1
colour5 0.2 0.1 0.1 0
}
}
My project: https://imagindar.com/
-
- Goblin
- Posts: 211
- Joined: Sat Jan 23, 2016 11:26 am
- x 17
Re: Question about use of shader for the billboard effect
thanks, i'm not sure 100% to have understood, but essentially using the discard of transparent pixel, i can use the deep check\write in the materials permitting to have the correct deeps in the scene for objects using alpha texture, correct?
-
- OGRE Team Member
- Posts: 1995
- Joined: Sun Mar 30, 2014 2:51 pm
- x 1075
- Contact:
Re: Question about use of shader for the billboard effect
see
the main topic is not alpha-test, but it is explained at the start
the main topic is not alpha-test, but it is explained at the start