[Solved] Help converting a GLSL shader Topic is solved

Problems building or running the engine, queries about how to use features etc.
rpgplayerrobin
Orc Shaman
Posts: 792
Joined: Wed Mar 18, 2009 3:03 am
x 452

Re: [Solved] Help converting a GLSL shader

Post by rpgplayerrobin »

Like you have seen yourself, when you rotate your camera your results change.

With both the approaches that I mention, that should most likely never happen.

I don't even understand how you can place a camera near the water and render depth without getting artifacts (since the near plane should cut into the terrain near the water edges).
I would imagine that you can get artifacts doing it like that as well since you then try to compare that to the real render of the scene I guess?
I would also imagine it would be impossible to sample certain pixels if it actually places the camera at the water level with the direction of the normal camera, since it would then be unable to generate the depth for water behind itself.
The more I think about this, the more problems I see.
It sounds like it would just be easier to use the same Z pre pass texture as you use for other stuff instead (such as SSAO, soft particles, etc). That is what the refraction camera usually does as well, just that it instead has a render flag that makes it render only stuff that are actually under water.

As long as you rotate your depth/refraction camera with the normal camera and just sample the depth without doing something special, you are most likely never going to get correct results.
Both of my approaches should fix that though.

Just imagine that you look from a beach from above, then you would see the exact depth of the water at any one point.
But if you sit at a beach and look out on it, you could look at a terrain 100 meters away, therefore getting the incorrect height because of the camera rotation. So if you would (for example) want to fade away the water near the terrain edges, it would be impossible to do so with a simple sample, instead you would have to either look from above (0, -1, 0) or you would have to somehow raycast to the bottom of the water pixels Y value to get its real height (which is impossible to do correctly as long as it is a screen-space technique).

EDIT: Not even my technique to raycast up to the water surface would work for that scenario.

tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

@rpgplayerrobin may i ask, in your code here viewtopic.php?p=544242#p544242, nearClipDistance and farClipDistance come from uniforms near_clip_distance and far_clip_distance or there are some constants defined in your shader? And also which format you use to render your depth texture? PF_DEPTH16?

Thanks!

Btw currently i do this

Code: Select all

vec2 fragCoord = projectionCoord.xy / projectionCoord.w; // passed from vertex

float depth = texture2D(depthMap, fragCoord).r;

depth = depth * projectionCoord.z * water_depth; // water_depth take values from 0.0 to 1.0 and is an UI slider

Its generally fine, at shallow areas refraction is full, foam is shown, caustics are shown (after foam), waves are smaller, while at deeper areas refraction is very low, water color is shown, waves are bigger, no foam, no caustics

It works fine even if camera is way up, but if i go too close to the water plane goes boom:

rpgplayerrobin
Orc Shaman
Posts: 792
Joined: Wed Mar 18, 2009 3:03 am
x 452

Re: [Solved] Help converting a GLSL shader

Post by rpgplayerrobin »

nearClipDistance and farClipDistance come from uniforms near_clip_distance and far_clip_distance

Yes.

I render my depth texture as PF_FLOAT32_R, with my own custom shaders, like this:

VS:

Code: Select all

float4x4 cWorldViewProj;
float4x4 cWorldView;

struct ZPrePass_vs_out
{
	float3 oViewPos : TEXCOORD0;
};

ZPrePass_vs_out ZPrePass_vs( float4 iPosition : POSITION,
							 out float4 oPosition : POSITION )
{
	ZPrePass_vs_out Out;

oPosition = mul(cWorldViewProj, iPosition);
Out.oViewPos = mul(cWorldView, iPosition).xyz;

return Out;
}

PS:

Code: Select all

float cNearClipDistance;
float cFarClipDistance;

float4 ZPrePass_ps(float3 iViewPos : TEXCOORD0) : COLOR0
{
	float clipDistance = cFarClipDistance - cNearClipDistance;
	return float4((length(iViewPos) - cNearClipDistance) / clipDistance, 1, 1, 1);
}
tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

Ok im giving a try your approach. Switched to Ogre::PF_FLOAT32_R and:

in material

Code: Select all

param_named_auto nearClipDistance near_clip_distance
param_named_auto farClipDistance far_clip_distance

param_named_auto invProj inverse_worldviewproj_matrix
param_named_auto invView inverse_view_matrix

param_named_auto cameraPosition camera_position_object_space

in fragment shader:

Code: Select all

uniform float nearClipDistance;
uniform float farClipDistance;

uniform mat4 invProj;
uniform mat4 invView;

uniform vec3 cameraPosition;


vec3 WSPositionFromDepth(vec2 uv, float depth)
{
    vec4 clipSpacePosition = vec4((uv.x * 2.0) - 1.0,
		((1.0 - uv.y) * 2.0) - 1.0,
		farClipDistance, // I first set "depth" here, but that caused errors when coming close to a surface
		1.0);
	vec4 worldSpacePosition = invProj *  clipSpacePosition;
	worldSpacePosition = invView * worldSpacePosition;
	worldSpacePosition /= worldSpacePosition.w;

	return  cameraPosition - (normalize(worldSpacePosition.xyz) * depth);
}

void main()
{

float clipDepth = farClipDistance - nearClipDistance;
float fragmentWorldDepth = texture2D(depthMap, fragCoord).r * clipDepth;
vec3 position = WSPositionFromDepth(fragCoord, fragmentWorldDepth);

gl_FragColor = vec4(sin(position), 1.0);

}

eeh im not sure what i'm looking at, how is supposed to look like?

This is what Ogre::PF_FLOAT32_R texture gives me alone

Image

which as i said before it is constant no matter the camera movement, but its not actual depth, Ogre::PF_DEPTH is but that varies with the camera movement. Also tried various approaches about it like https://www.youtube.com/watch?v=Jq3he9Lbj7M and https://www.youtube.com/watch?v=qgDPSnZPGMA, but they don't work here, i just can't make it constant.

rpgplayerrobin
Orc Shaman
Posts: 792
Joined: Wed Mar 18, 2009 3:03 am
x 452

Re: [Solved] Help converting a GLSL shader

Post by rpgplayerrobin »

If the position you debug with "sin" is not behaving correctly, debug it first and see why it is not working. There are so many variables there that you can alter and check, and I can't do it for you since that code works for me (but you are using GLSL and I am using HLSL). It can be anything, it can be that the camera position is not needed at all, or it might be something else, but only you can debug it. If Linux or your IDE does not allow that, I would change to another OS or IDE if I were you, since shader debugging is vital for development.

The most apparent thing would be that you assumed that the cameraPosition, invView and invProj are param_named_auto, even though my post that you got it from specifically set them by code in a very specific way (viewtopic.php?p=544242#p544242).
You also used camera_position_object_space for cameraPosition, when in my code it uses a world position of the camera.

Secondly, I don't know how you set up your camera to render the depth. If it comes from the main camera it will always have issues that I detailed in the previous post.

Then you changed from your depth texture to float32_r, but I don't think there is any need to do that. You just need to convert your depth into a world position, and the code I supplied should help you do that.

Then "but its not actual depth, Ogre::PF_DEPTH is" is just confusing, as the depth in my game works perfectly.

If the below statement is correct, you should not have any problems at all with any of this, so I just don't understand it:
"which as i said before it is constant no matter the camera movement"

What I wrote about constant depth is having a camera top-down at a constant distance, which would always create a constant depth for everything.
As long as it is a camera that follows the orientation and position (even if it is offsetted towards the water), you won't have a constant depth for the water/environment.

tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

Went back again to Ogre::PF_DEPTH, i removed cameraPosition and also made invProj and invView as you did and now i get:

Image

Secondly, I don't know how you set up your camera to render the depth. If it comes from the main camera it will always have issues that I detailed in the previous post.

Yeah i think this is my main issue here

Code: Select all

        Ogre::TextureManager::getSingleton ().createManual ("RefractionDepth",
            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, res , res, 0,
            Ogre::PF_DEPTH16, Ogre::TU_RENDERTARGET, 0, false, fsaa);

            TexturePtr m_refract_depth_rtt_targetPtr = Ogre::TextureManager::getSingleton ().getByName ("RefractionDepth");
            m_refract_depth_rtt_texture = m_refract_depth_rtt_targetPtr;
            m_refract_depth_rtt_target = m_refract_depth_rtt_targetPtr->getBuffer()->getRenderTarget();
            {
                m_refract_depth_cam = App::GetGfxScene()->GetSceneManager()->createCamera("RefractDepthCam");
                m_refract_depth_cam->setNearClipDistance(App::GetCameraManager()->GetCamera()->getNearClipDistance());
                m_refract_depth_cam->setFarClipDistance(App::GetCameraManager()->GetCamera()->getFarClipDistance());
                m_refract_depth_cam->setAspectRatio(
                    (Real)RoR::App::GetAppContext()->GetRenderWindow()->getViewport(0)->getActualWidth() /
                    (Real)RoR::App::GetAppContext()->GetRenderWindow()->getViewport(0)->getActualHeight());

                m_refract_depth_rtt_viewport = m_refract_depth_rtt_target->addViewport(m_refract_depth_cam);
                m_refract_depth_rtt_viewport->setClearEveryFrame(true);
                m_refract_depth_rtt_viewport->setBackgroundColour(App::GetGfxScene()->GetSceneManager()->getFogColour());

                MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction");
                mat->getTechnique(0)->getPass(0)->getTextureUnitState(3)->setTextureName("RefractionDepth");

                m_refract_depth_rtt_viewport->setOverlaysEnabled(false);

                m_refract_depth_rtt_target->addListener(&m_refract_depth_listener);

                //optimisation
                m_refract_depth_rtt_target->setAutoUpdated(false);

                // Also clip
                m_refract_depth_cam->enableCustomNearClipPlane(m_refract_depth_plane);

then update

Code: Select all

            m_refract_depth_cam->setOrientation(App::GetCameraManager()->GetCameraNode()->getOrientation());
            m_refract_depth_cam->setPosition(App::GetCameraManager()->GetCameraNode()->getPosition());
            m_refract_depth_cam->setFOVy(App::GetCameraManager()->GetCamera()->getFOVy());
            m_refract_depth_rtt_target->update();

I will try to make it fixed position/orientation/whatever.

Thank you for your patience so far :)

paroj
OGRE Team Member
OGRE Team Member
Posts: 2251
Joined: Sun Mar 30, 2014 2:51 pm
x 1227

Re: [Solved] Help converting a GLSL shader

Post by paroj »

I dont want to interrupt, but Terrain is typically loaded from a heightmap like:
Image

if you look closely, you might notice that it looks like the "depth" that you are after.
So basically, you just need to add this texture to the quad that renders you water and you are done.

Note that this image is normalized, so you need to multiply it by a scale factor to get the real world height:
https://github.com/OGRECave/ogre/blob/c ... ain.h#L513

of course, if you need dynamic objects like ships in this, you will have to use a render texture, but now you have something to compare against.

tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

paroj wrote: Sun Feb 25, 2024 10:32 pm

if you need dynamic objects like ships in this, you will have to use a render texture

btw about this, yes i have foam around anything that penetrates the depth texture.

if i understand correctly if i want to make the foam "trail" behind a moving object like this for example https://www.shadertoy.com/view/DlfXR4, i need a buffer, is it possible to do in Ogre? Any docs/examples about using something similar to the "Buffer A" thingy? Whats the logic behind this?

paroj
OGRE Team Member
OGRE Team Member
Posts: 2251
Joined: Sun Mar 30, 2014 2:51 pm
x 1227

Re: [Solved] Help converting a GLSL shader

Post by paroj »

tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

Ok it seems in Ogre 1.11.6 PF_DEPTH16 is not supported in DirectX 9. So i guess i have to render the depth manually using a separate shader and use that. Is there an example of how to pass the output from one material (depth shader) to another material (water shader) texture unit so i can read it there as a uniform sampler2D?

rpgplayerrobin
Orc Shaman
Posts: 792
Joined: Wed Mar 18, 2009 3:03 am
x 452

Re: [Solved] Help converting a GLSL shader

Post by rpgplayerrobin »

That is also why I use PF_FLOAT32_R, since it is supported for both Direct3D9 and Direct3D11.
Here is a thread where I posted how I prepare and handle my own depth texture (ZPrePass):
viewtopic.php?t=96658

tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

rpgplayerrobin wrote: Thu Mar 14, 2024 6:13 pm

That is also why I use PF_FLOAT32_R, since it is supported for both Direct3D9 and Direct3D11.
Here is a thread where I posted how I prepare and handle my own depth texture (ZPrePass):
viewtopic.php?t=96658

Thanks for the link! Examining the code (viewtopic.php?p=552639#p552639) i see you fetch all materials in the scene, create an extra new technique/pass and assign the z-prepass material pass to it. But im failing to understand how later the m_texture is fed with the result of that pass. Maybe some code is missing? (preRenderTargetUpdate/postRenderTargetUpdate maybe)

paroj
OGRE Team Member
OGRE Team Member
Posts: 2251
Joined: Sun Mar 30, 2014 2:51 pm
x 1227

Re: [Solved] Help converting a GLSL shader

Post by paroj »

rpgplayerrobin wrote: Thu Mar 14, 2024 6:13 pm

That is also why I use PF_FLOAT32_R, since it is supported for both Direct3D9 and Direct3D11.

I am not sure on which Ogre version you are currently at, but since Ogre 13.2.1 there is PF_DEPTH16 support on D3D9 too

rpgplayerrobin
Orc Shaman
Posts: 792
Joined: Wed Mar 18, 2009 3:03 am
x 452

Re: [Solved] Help converting a GLSL shader

Post by rpgplayerrobin »

Thanks for the link! Examining the code (viewtopic.php?p=552639#p552639) i see you fetch all materials in the scene, create an extra new technique/pass and assign the z-prepass material pass to it. But im failing to understand how later the m_texture is fed with the result of that pass. Maybe some code is missing? (preRenderTargetUpdate/postRenderTargetUpdate maybe)

I am not sure on which Ogre version you are currently at, but since Ogre 13.2.1 there is PF_DEPTH16 support on D3D9 too

tritonas00, if I were you, I would then instead just upgrade to 13.2.1 and use the PF_DEPTH16.
Because setting up the thing with my code is a very complex process since it requires many new shaders and new special passes (one per type, like solids, semi-transparents, alpha rejection, etc). With the automatic PF_DEPTH16 it instead handles it for you. The only difference is that my approach should be faster since it only has 2 lines of code or so per fragment shader, while the PF_DEPTH16 has to dynamically remove/ignore code from the shader and can therefore have different results in speed on different hardware/driver (since some might handle it correctly and some might run the entire shader code would be my guess).
Imagine a very complex shader that has 20 lights and things like raymarched code. That code is probably like 500 lines in the fragment shader, but with a simplified shader only for the ZPrePass, that could be done in just 2 lines or so in the fragment shader.
But I don't really know if the automatic one in 13.2.1 renders both at the same time (with an MRT or something), in that case it could be faster for sure than my method. But the problem then is that the depth buffer is not a ZPrePass, since the ZPrePass is done before the scene is rendered normally, and not at the same time (so that it can be used for objects being rendered).

But if you really want to use my method to do it and only have a question about how to set the m_texture into another material, simply get the material you want to apply it to in code and then set the texture unit to the m_texture with setTexture, something like this:

Code: Select all

Ogre::MaterialPtr mSmokeMaterial = Ogre::MaterialManager::getSingleton().getByName("Examples/Smoke");
mSmokeMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(m_texture);

Also be sure to go through the entire forum thread (both pages), since there might be more code needed there.

tritonas00
Halfling
Posts: 89
Joined: Sun Apr 08, 2018 2:21 pm
x 42

Re: [Solved] Help converting a GLSL shader

Post by tritonas00 »

rpgplayerrobin wrote: Sat Mar 16, 2024 2:12 pm

tritonas00, if I were you, I would then instead just upgrade to 13.2.1 and use the PF_DEPTH16.

Yeah, i think that makes sense. Anyway this is my latest work on it, and i can wrap up, at least for now. :)

https://github.com/tritonas00/rigs-of-r ... s/water-2/