Question about use of shader for the billboard effect

Problems building or running the engine, queries about how to use features etc.
Post Reply
Niubbo
Goblin
Posts: 211
Joined: Sat Jan 23, 2016 11:26 am
x 17

Question about use of shader for the billboard effect

Post by Niubbo »

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
rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 353

Re: Question about use of shader for the billboard effect

Post by rpgplayerrobin »

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).
Niubbo
Goblin
Posts: 211
Joined: Sat Jan 23, 2016 11:26 am
x 17

Re: Question about use of shader for the billboard effect

Post by Niubbo »

Normal entities, not instanced.

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();
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.
rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 353

Re: Question about use of shader for the billboard effect

Post by rpgplayerrobin »

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/
paroj
OGRE Team Member
OGRE Team Member
Posts: 1994
Joined: Sun Mar 30, 2014 2:51 pm
x 1074
Contact:

Re: Question about use of shader for the billboard effect

Post by paroj »

there is also order independent transparency, see:
https://www.ogre3d.org/2021/08/14/ogre- ... _additions
Niubbo
Goblin
Posts: 211
Joined: Sat Jan 23, 2016 11:26 am
x 17

Re: Question about use of shader for the billboard effect

Post by Niubbo »

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/
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
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 353

Re: Question about use of shader for the billboard effect

Post by rpgplayerrobin »

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:

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
    }
}
Niubbo
Goblin
Posts: 211
Joined: Sat Jan 23, 2016 11:26 am
x 17

Re: Question about use of shader for the billboard effect

Post by Niubbo »

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?
paroj
OGRE Team Member
OGRE Team Member
Posts: 1994
Joined: Sun Mar 30, 2014 2:51 pm
x 1074
Contact:

Re: Question about use of shader for the billboard effect

Post by paroj »

see

the main topic is not alpha-test, but it is explained at the start
Post Reply