help improve particle effects

Problems building or running the engine, queries about how to use features etc.
loath
Platinum Sponsor
Platinum Sponsor
Posts: 290
Joined: Tue Jan 17, 2012 5:18 am
x 67

Re: help improve particle effects

Post by loath »

paul424 wrote: Sun Apr 17, 2022 11:51 am

@loath : Yes, and my fork is called opendungeons-plus ; you can install it on linux from here https://snapcraft.io/opendungeons-plus

very cool project @paul424. thanks for bringing this subject up and for @rpgplayerrobin for the super helpful code.

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

With two textures , blended with alpha_blend I get :

Code: Select all

material Examples/Smoke
{
	technique
	{
		pass
		{
			lighting off
			scene_blend alpha_blend
			depth_write off

		texture_unit
		{
			texture Smoke15Frames.png
			tex_address_mode clamp
		}
		texture_unit
		{
			texture Smoke15Frames.png
			tex_address_mode clamp
		}			
	}
}
}

I get :

rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 355

Re: help improve particle effects

Post by rpgplayerrobin »

Hey!

I saw you e-mail (by accident, I never log into that account usually in weeks).

You will have to create a ZPrePass before you can even begin to be able to apply it on a particle.

The material of the particle is very simple, just two textures (one is the particle texture and the second you have to set manually in code to the ZPrePass texture):

Code: Select all

material FireParticle
{
	technique
	{
		pass
		{
			lighting off
			depth_write off
			scene_blend add

		vertex_program_ref SoftParticles_VS
		{
		}

        fragment_program_ref SoftParticles_PS
        {
        }

		texture_unit
		{
			texture fireParticle.png
			tex_address_mode clamp
		}

        texture_unit ZPrePass
        {
            texture white.tga // This gets filled in later
            tex_address_mode clamp
            filtering none
        }
	}
}
}

And here is the material for the already posted soft particles shader:

Code: Select all

vertex_program SoftParticles_VS hlsl
{
	source SoftParticles.hlsl
	entry_point main_vs
	target vs_3_0

default_params
{
	param_named_auto modelViewProj worldviewproj_matrix
	param_named_auto worldView worldview_matrix
}
}

fragment_program SoftParticles_PS hlsl
{
	source SoftParticles.hlsl
	entry_point main_ps
	target ps_3_0

default_params
{
	param_named fadeDistance float 0.2

	param_named_auto fogParams fog_params
	param_named_auto eyePosition camera_position_object_space
	param_named_auto nearClipDistance near_clip_distance
	param_named_auto farClipDistance far_clip_distance
	param_named_auto inverseViewportWidth inverse_viewport_width
	param_named_auto inverseViewportHeight inverse_viewport_height
}
}

If you want the shader to use "scene_blend alpha_blend" instead of "scene_blend add" in the particle material, you will have to replace this:

Code: Select all

float4 color = tex2D(DiffuseMap, uv) * vertexColour;
color.xyz *= softMultiplier;

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;
float squaredLength = dot(squaredLengthVec, squaredLengthVec);
float fogFactor = (1.0 - saturate((fogEnd - squaredLength) / (fogEnd - fogStart))) * fogEnabled;
color.xyz *= 1.0 - fogFactor;

with this:

Code: Select all

float4 color = tex2D(DiffuseMap, uv) * vertexColour;
color.a *= softMultiplier;

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;
float squaredLength = dot(squaredLengthVec, squaredLengthVec);
float fogFactor = (1.0 - saturate((fogEnd - squaredLength) / (fogEnd - fogStart))) * fogEnabled;
color.xyz = lerp(color.xyz, fogColour.xyz, fogFactor);

I use both shaders in my game, one for each.

You will clearly see the difference when particles are close to a wall if it works. It will never intersect with it.
If you want, you can try it in my game (Spellheart), just make sure Soft Particles and Replays is checked in the options menu. Then you can cast an ability like Meteor close to a wall and go into the replay of the game where you can watch it from all angles. Then you will see particles never collide with any 3D in the world at all, which is the end goal of course.
You can also try it in my in-game map editor to see how it works against the floor or a wall.

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

First question of all to all ;) is : " can I supply HLSL shaders when my favourite game engine is working in OpenGL render mode ?" , seems no ,cause Ogre3d would have to compile them to SPIR-V shader language, and I don't see any such procedure in ogre3d.
EDIT: No, because Ogre3d manual says :

OGRE supports multiple high-level program types. Notably DirectX HLSL, and OpenGL GLSL. HLSL can only be used with the DirectX rendersystem, and GLSL can only be used with the GL rendersystem.

https://ogrecave.github.io/ogre/api/13/ ... grams.html
I will continue to rewrite your shader in GLSL when I am back home ...

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

What is the variable fogColour ? Where does it come from ?

EDIT: Ahh this is provided by some uniform variable provided by the SceneManager .... So tell me what specific settings of fog do I need ?

EDIT2: here's the code I have translated so far , to no avail NO PARTICLES SHOW UP :( :
PARTICLES:

Code: Select all

#version 330  core
#extension GL_ARB_separate_shader_objects : enable

uniform sampler2D DiffuseMap;
uniform sampler2D ZPrePassMap;




uniform float fadeDistance;
uniform vec4 fogParams;
uniform vec3 eyePosition;
uniform float nearClipDistance;
uniform float farClipDistance;
uniform float inverseViewportWidth;
uniform float inverseViewportHeight;
uniform vec4 fogColour;


layout (location = 8) in vec3 position;
layout (location = 9) in vec2 uv;
layout (location = 10)	in vec4 vertexColour;
layout (location = 11)	in vec3 viewPosition;
layout (location = 0) in vec4 screenPosition;
				
out vec4 color;
void main(void)
{
	const vec2 renderSystemTexelOffset = vec2(0.5, 0.5);
	vec2 zPrePassUV = vec2((screenPosition.x + renderSystemTexelOffset.x) * inverseViewportWidth,
							   (screenPosition.y + renderSystemTexelOffset.y) * inverseViewportHeight);

float pixelPositionDepth = length(viewPosition) - nearClipDistance;

float clipDistance = farClipDistance - nearClipDistance; // Convert it to world space units instead of 0-1
float zPrePassPositionDepth = texture(ZPrePassMap, zPrePassUV).r * clipDistance;

float softMultiplier = 1.0;
float distance = abs(pixelPositionDepth - zPrePassPositionDepth);
if(distance < fadeDistance)
	softMultiplier = distance / fadeDistance;

color = texture(DiffuseMap, uv) * vertexColour;
color.xyz *= softMultiplier;

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;
vec3 squaredLengthVec = eyePosition - position;
float squaredLength = dot(squaredLengthVec, squaredLengthVec);
float fogFactor = (1.0 - clamp((fogEnd - squaredLength) / (fogEnd - fogStart),0.0,1.0)) * fogEnabled;
color.xyz = mix(color.xyz, fogColour.xyz, fogFactor);
}

Code: Select all

#version 330  core
#extension GL_ARB_separate_shader_objects : enable

uniform mat4x4 modelViewProj;
uniform mat4x4 worldView;

layout (location = 0) in vec4 position ;
layout (location = 8) in vec2 iUV ;
layout (location = 3) in vec4 vertexColour;

layout (location = 0 ) out vec4 oPosition ;
layout (location = 8 ) out	vec3 oVertexPos;
layout (location = 9 ) out	vec2 oUV;
layout (location = 10 ) out	vec4 oVertexColour;
layout (location = 11 ) out	vec3 oViewPosition;



void main(void)
{

oPosition = modelViewProj *position;
oVertexPos = position.xyz;
oUV = iUV;
oViewPosition = (worldView * position).xyz;
oVertexColour = vertexColour;

}

ZPREPASS:

Code: Select all

#version 330  core
#extension GL_ARB_separate_shader_objects : enable
uniform float cNearClipDistance;
uniform float cFarClipDistance;
in vec3 iPosition;
in vec2 iUV;
in vec3 iViewPos;
out vec4 color;

void main()
{
	float clipDistance = cFarClipDistance - cNearClipDistance;
	float intensity = (length(iViewPos) - cNearClipDistance) / clipDistance;
	color = vec4(intensity,1.0,1.0,1.0);
	
}

Code: Select all

#version 330  core
#extension GL_ARB_separate_shader_objects : enable
uniform mat4 cWorldViewProj;
uniform mat4 cWorldView;

layout (location = 0) in vec4 iPosition;
layout (location = 9) in vec2 iUV;

layout (location = 0) out vec4 oPosition;
layout (location = 8) out vec2 oUV;
layout (location = 9) out vec3 oViewPos;

void main()
{
oPosition = cWorldViewProj * iPosition;
oViewPos = (cWorldView * iPosition).xyz;
oUV = iUV;

}


rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 355

Re: help improve particle effects

Post by rpgplayerrobin »

You can just remove the fog code if you don't use fog in your project.

If you use fog, you need to use that fog code on ALL shaders in your project, and I guess you have not done that, so just remove it from the particle shader as well.

If you really want fog, it is explained at the bottom of this article how to set the scene wide parameters for it:
https://ogrecave.github.io/ogre/api/1.1 ... y_fog.html

It is very hard to say why your particles do not show up.
Are there any errors in the Ogre.log?
Is your ZPrePass texture rendered each frame in your code?
Have you set the ZPrePass texture to the particle material in your code behind when you created the ZPrePass texture?
Have you tried to visualize the ZPrePass texture (hard to do, but it can be done in a shader)?

You must debug the code and the shader to be able to know what is wrong. I would bet it has something to do with ZPrePass, and you can control that in the particle shader code by altering the code to do this:

Code: Select all

softMultiplier *= 0.0000001;
softMultiplier += 0.9999999; // We cannot simply set it, because then other variables might not be needed and they then get removed on compile
color.xyz *= softMultiplier;

Instead of this:

Code: Select all

color.xyz *= softMultiplier;

If the particles show up then, you know you that the bug has to do with the ZPrePass texture (or the lack of setting it to the particle).

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

Folowing your advice I have removed the fog entirely from the shader equations, because OD doesn't use fog at all.
I always follow a rule not to have errors in Ogre.log.

I tried your recipe of modifing the last lines of SoftParticle. The particle still doesn't show up...

I render the ZPrepass by hooking this :

Code: Select all

    if(mRenderManager->mRenderTarget != nullptr)
        mRenderManager->mRenderTarget->update();

into

Code: Select all

bool ODFrameListener::frameStarted(const Ogre::FrameEvent& evt)

What regards to visualizing the ZPrePass Texture I do the following : I leave only one texture in Examples/Smoke material and I fill it with the command

Code: Select all

    mSmokeMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(m_texture);  

like this :

Code: Select all

material Examples/Smoke
{
	technique
	{
		pass
		{
			lighting off
			depth_write off

    texture_unit ZPrePass
    {
        texture White.png // This gets filled in later
        tex_address_mode clamp
        filtering none
    }
}
}
}

Then I get something like that :

EDIT: but of course, the more worrying is that the simplest construction such as :

Code: Select all

color = texture(DiffuseMap, uv.st).rgb;

doesn't want to work correctly ....

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

After some tinkering I have come to the conclusion that I lacked setting the gl_Position to something meaningful that is

Code: Select all

gl_Position = oPosition; 

And I can see that the problem lies at the ZPrePass. Shell the ZPrePass texture look as it looks on my video or it should be something diffrent ?

rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 355

Re: help improve particle effects

Post by rpgplayerrobin »

It is really hard to say, since since the texture should only have 1 channel (Red), which is a bit harder to visualize, and that the channel is 32 bit instead of 8 bit, which we use to set the distance to the pixel using our near and far clip distance, which in my game is between (around) 0.1 - 1000 (but that it instead maps to 0-1 in the texture).
I can visualize my version like this (grayscale instead of red and then just multiply by 10 to make it easier to see):

Code: Select all

color.xyz = tex2D(sampler, uv).r * 10.0;

Image
As a fullscreen effect like this (a simple debug compositor shader), it is much easier to debug it. It can also help later since some objects might be added to the ZPrePass when you don't want it to (which means you must hide that object when rendering, or use a viewport flag for automatic hiding) or if you want something added to the ZPrePass that is not there it can also be helpful to see the bugs regarding this.

But the particle should appear.
Try to remove the code until it appears, then you can add back stuff one line at a time.
But look out for shader compliations that remove parameters and variables if they are not used, so make sure to use all variables, parameters and textures even if they have no effect.
You can force the shader to not remove those parameters, with something like this in the end of the shader:

Code: Select all

color.xyz += softMultiplier * 0.0000001;
color.xyz += fadeDistance * 0.0000001;
color.xyz += texture(ZPrePassMap, zPrePassUV).r * clipDistance * 0.0000001;
color.xyz += texture(DiffuseMap, uv).xyz * 0.0000001;
color.xyz += vertexColour.xyz * 0.0000001;
color.xyz += zPrePassUV.x * 0.0000001;
color.xyz += zPrePassUV.y * 0.0000001;
color.xyz += pixelPositionDepth * 0.0000001;
color.xyz += clipDistance * 0.0000001;
color.xyz += zPrePassPositionDepth * 0.0000001;
color.xyz += distance * 0.0000001;
User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

Many thanks, I didn't say that clearly , but know the particle SHOWS UP due to your previous method, ONLY there seems to be problem with the ZPREPASS material. I did what you requested and I do

Code: Select all

color.rgba = vec4(texture(ZPrePassMap, uv.st).r * 5); //* vertexColour;

in this video :

Clearly there are two flaws for my eye:

1) first is the texture bibloard of particle isn't updated each frame ( seems it does update() only at start )
2) the texture quad bilboard doesn't show up what it should show ( that is it seems to contain some random piece of viewport ).

rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 355

Re: help improve particle effects

Post by rpgplayerrobin »

A compositor would show exactly how it looks (since that covers the whole screen) and will help you debug it more.

But I can say one thing for sure, that ZPrePass texture is not generated correctly.
Look at the texture and it will show even the textured surfaces on it (like the "+" signs from the floor) and even the lighting (see the edges of the stones, some of them are affected by lighting).
That is not how it should look, it should only render its depth value like my previous image showed. That means it should never have any texture or lighting information in it.

Have you controlled that the HandleSchemeNotFound function gets called for all materials in the scene when you use the Setup function?
Or maybe the issue is that the Setup function is never called, or called before the scene is loaded?
Also, when you create new materials on run-time, you must make sure the HandleSchemeNotFound gets called for that material as well.
Because that function creates an additional technique (with a unique material scheme) in each material that controls the rendering of the ZPrePass.
If that material scheme is not found, the ZPrePass it might render the normal technique and that would then add its texture and color details to it.

rpgplayerrobin
Gnoll
Posts: 619
Joined: Wed Mar 18, 2009 3:03 am
x 355

Re: help improve particle effects

Post by rpgplayerrobin »

Also, it seems my code was not complete.

You need to do this as well for the preRenderTargetUpdate (make sure it is called each frame), otherwise the camera might be rendered incorrectly and will not have the correct material scheme (if you didn't set it at startup):

Code: Select all

void SetPosition(Camera* obj, const Vector3& vec)
{
	Node* tmpNode = obj->getParentNode();
	tmpNode->setPosition(vec);
}

void SetOrientation(Camera* obj, const Quaternion& q)
{
	Node* tmpNode = obj->getParentNode();
	tmpNode->setOrientation(q);
}

Vector3 GetPosition(Camera* obj)
{
	return obj->getDerivedPosition();
	//Node* tmpNode = obj->getParentNode();
	//return tmpNode->_getDerivedPosition();
}

Quaternion GetOrientation(Camera* obj)
{
	return obj->getDerivedOrientation();
	//Node* tmpNode = obj->getParentNode();
	//return tmpNode->_getDerivedOrientation();
}

// Called before a render is called to the render target
void YourClass::preRenderTargetUpdate(const RenderTargetEvent& evt)
{
	// Update the camera
	SetPosition(m_cameraRTT, GetPosition(app->m_Camera));
	SetOrientation(m_cameraRTT, GetOrientation(app->m_Camera));
	m_cameraRTT->setFOVy(app->m_Camera->getFOVy());
	m_cameraRTT->setAspectRatio(app->m_Camera->getAspectRatio());
	m_cameraRTT->setNearClipDistance(app->m_Camera->getNearClipDistance());
	m_cameraRTT->setFarClipDistance(app->m_Camera->getFarClipDistance());
	m_cameraRTT->getViewport()->setMaterialScheme(m_schemeName);
}

You must also add this to the class you are using the "m_renderTarget->addListener(this);" on: " : public RenderTargetListener".
Otherwise preRenderTargetUpdate will never get called.

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

rpgplayerrobin wrote: Tue Apr 26, 2022 12:33 pm

Have you controlled that the HandleSchemeNotFound function gets called for all materials in the scene when you use the Setup function?
Or maybe the issue is that the Setup function is never called, or called before the scene is loaded?

Well to be absolutly sure I have hooked the setup function to the console , and I run it manually after I load the level .....
After applying all your suggested code patches I get:
The smoke texture appears, but it doesn't get suppressed ( the effect is as WITHOUT your code at all ). When I try to debug as in the previous examples ( to render only ZPrepass texture) I get one big red rectangle in place of particle billboard ( so no information is being rendered to ZPrePass texture this time ) ...

User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

EDIT : THIS PROBLEM SOLVED
Ogre version -- 1.13.3.4

The never ending story is this :
following the advice of rpgplayerrobin I did created
[...]
How do I correctly use RTSS with this one ?

Last edited by paul424 on Mon May 16, 2022 10:04 pm, edited 2 times in total.
User avatar
paul424
Gnome
Posts: 314
Joined: Thu May 24, 2012 7:16 pm
x 13

Re: help improve particle effects

Post by paul424 »

The newest update to my story :

I am getting an exception regarding RTSS of an overlay material, which makes no sense.

When I render the scene normally, everything works.

But when I introduce a manually updated render target (PF_FLOAT32_R), which I update in frameStarted, the exception of the overlay occurs a couple of seconds later in the normal scene render (not from the render target).

The render target is using a specific material scheme and it is using "tmpViewport->setOverlaysEnabled(false);", which should make it not even try to render the overlay.

I don't even do anything with the render target. I never set its texture anywhere or use it in any way. Still, the overlay crashes regarding RTSS for some reason (even if it not even rendered using the render target).
And it is strange that it happens a couple of seconds after I have started to use the render target (I type in a command to activate it).

Here is the exception and call stack:
https://pastebin.com/raw/ZWEBEMrZ

What can cause this?
BTW : thanks @rpgplayerrobin for tutoring me so far to this point ! :D
EDIT: I try to achieve this on both ogre 1 12.13 as well as the newest ogre 1 13 3

Post Reply