[2.1] MRT incorrect texture data

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Frankincense
Kobold
Posts: 33
Joined: Mon May 05, 2014 5:36 pm
x 3

[2.1] MRT incorrect texture data

Post by Frankincense »

Hi all,

I am setting up a shader that renders to an MRT, but the second and third outputs are having the alpha channel applied over the other channels (e.g. setting value.a = 0.5 is being multiplied with the value.rgb when read by following shaders.) I don't want these outputs interpreted as colour.

The pixel shader is setting up the outputs like this:

Code: Select all

         layout(location = FRAG_COLOR, index = 0) out vec4 outColour;
         layout(location = 1) out vec4 oNormal ;
         layout(location = 2) out vec4 oViewPos ;
If I set the alpha value of oNormal to 0.5 like this:

Code: Select all

oNormal  = vec4 ( 1, 0, 0, 0.5 );
then the next shader will read 0.5 in the red channel.

The MRT is setup like this in the first compositor:

Code: Select all

texture rtt 	target_width target_height PF_R8G8B8 PF_FLOAT32_RGBA PF_FLOAT32_RGBA depth_format PF_D32_FLOAT_X24_S8_UINT depth_texture depth_pool 1
I have two compositor nodes setup, the first renders the entire scene and writes to the rtt, the second node is simply reading from the MRT and writing to the rt_renderwindow. It is setup like this:

Code: Select all

compositor_node TestWrite
{
	in 0 rtt
	in 1 rtt_depthbuffer
	in 2 rt_renderwindow

	target rt_renderwindow
	{
		pass clear
		{
			colour_value 0 0 0 1
		}

		pass render_quad
		{
			material Ogre/Copy/4xFP32
			input 0 rtt 1
		}
	}
}

workspace TestWorkspace
{
	connect			TestRender	0	1	TestWrite	0	1
	connect_output	TestWrite	2
}
The TestWrite should just be copying the oNormal value to the target window as-is, and completely ignore the alpha value:

Code: Select all

fragColour = vec4(vec3(texture( tex, inPs.uv0 ).rgb), 1);
The Copy/4xFP32 material is the same as the default in the Ogre samples.


I do not want the oNormal output to be interpreted as a colour, I just want to read its data as individual channels. If I set the oNormal.a = 1.0 then everything is rendered as expected, but setting oNormal.a = 0.0 will set all of the RGB data to 0.0. I have tried a couple of other texture formats for the MRT with no success.

Is there something I am missing to get the RGBa values all read by the TestWrite shader the same as they are written?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.1] MRT incorrect texture data

Post by dark_sylinc »

I assume you're using alpha blending.

Because using alpha blending on deferred rendering is very uncommon, this area hasn't been given much attention.

What you want to do:
  • OpenGL needs to use glBlendFunci/glBlendFuncSeparatei instead of glBlendFunc/glBlendFuncSeparate in _hlmsBlendblockCreated
  • In D3D11 it can be achieved if _hlmsBlendblockCreated is modified to set IndependentBlendEnable = true; and specify alpha blending for each RT index individually
  • Can be done in Metal, same as D3D11: Right now we assume al RTs use the same blending mode
HlmsBlendblock doesn't have fields to support per-MRT blending modes, so either HlmsBlendblock needs to be extended, or if you're looking for a quick fix _hlmsBlendblockCreated can be hacked to always only affect the first MRT index which is what you're currently after.
Frankincense
Kobold
Posts: 33
Joined: Mon May 05, 2014 5:36 pm
x 3

Re: [2.1] MRT incorrect texture data

Post by Frankincense »

dark_sylinc wrote: Wed Oct 07, 2020 5:04 pm I assume you're using alpha blending.
Yes I am, maybe I should explain how I got to this point as I think I might be approaching my problem incorrectly.

In Ogre 1.10 I had a forward rendering setup which then had a GBuffer pass to an MRT which I used for a number of post processing effects such as SSAO, water depth, Fog, DOF, etc.
The GBuffer pass obviously had to re-render the entire scene just for the normal, depth and viewpos data.

Now under Ogre 2.1 I was looking to simplify this setup as I was thinking that I could just adapt my forward rendering pass to render to an MRT with the first channel being the normal scene output (with lighting), and then use other two channels for the normals, depths and viewpos data that I could use for post-processing effects. That way I only had to render the scene once.

Maybe I am not approaching this problem correctly? Does this seem like a sensible thing to do? Maybe the 'normal' approach would be to commit to a properly deferred render setup and process the lighting as a separate pass
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.1] MRT incorrect texture data

Post by dark_sylinc »

Pbs supports a similar setup (e.g. see our SSAO sample, we can export normals out of the box).

However it's rare to include transparents in it because it causes too many issues.

The common practice is to split in two passes, transparents being in its own pass (e.g. by having all of them live in the same renderqueue groups):
  1. Render opaque, exporting normals and other GBuffer stuff
  2. Render transparents, without exporting normals / GBuffer
In compositor terms, it would need two render_scene passes.
Frankincense
Kobold
Posts: 33
Joined: Mon May 05, 2014 5:36 pm
x 3

Re: [2.1] MRT incorrect texture data

Post by Frankincense »

I think what I will do is re-evaluate if my objects require alpha-blending and either look to use the per-MRT blending modes or use separate transparency passes depending on how many objects need it - I have temporarily disabled alpha-blending for now and that looks to have resolved my immediate issue which is good to see, thank you

I am looking to get the main compositor node and the second compositor node to both render to rt_renderwindow but I get the error:
WARNING: Node 'TestRender' has the following channels in a disconnected state. Workspace won't work until they're solved:
Channel # 0
WARNING: Node 'TestWrite' has the following channels in a disconnected state. Workspace won't work until they're solved:
Channel # 0

Is having multiple CompositorNode's rendering directly to rt_renderwindow not allowed?

Code: Select all

compositor_node TestRender
{
	in 0 rt_renderwindow
...
	target rt_renderwindow
	{
	}
...
	out 0 rtt
}

Code: Select all

compositor_node TestWrite
{
	in 0 rtt
	in 1 rt_renderwindow
...
	target rt_renderwindow
	{
	}
}
It doesn't seem to matter if I do or don't connect the node channels in the workspace:

Code: Select all

workspace TestWorkspace
{
	connect			TestRender	0	1	TestWrite	0	1
	connect_output	TestWrite	1
}
I am doing this because the second compositor node will alpha blend with the existing scene
Frankincense
Kobold
Posts: 33
Joined: Mon May 05, 2014 5:36 pm
x 3

Re: [2.1] MRT incorrect texture data

Post by Frankincense »

I guess I am looking for whatever would replace this from 1.10:

Code: Select all

compositor Name
{
    technique
    {
        target_output
        {
            input previous
            {
            ...
            }
        }
    }
}
An alternative might be to render on-top of the first channel of the RTT, but I assume I would have to output to all three RTT channels?

Code: Select all

compositor_node TestWrite
{
	in 0 rtt
	in 1 rt_renderwindow
...
	target rtt // Somehow only render to channel 0?
	{
	}
}
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5446
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1348

Re: [2.1] MRT incorrect texture data

Post by dark_sylinc »

Hi!
Is having multiple CompositorNode's rendering directly to rt_renderwindow not allowed?
Yes, it is allowed. But beware it is not allowed to use the render window as part of an MRT target. Also note that because it's named "rt_renderwindow" does not mean it's the window (though that's probably what's intended) if you don't plug the render window in addWorkspace for that input channel.

What you were trying to achieve can be done either with two render_pass declarations:

Code: Select all

compositor_node MyNode
{
	in 0 rt_renderwindow
	
	target rt_renderwindow
	{
		pass render_scene
		{
			rq_first	0
			rq_last		200
		}
	}
	
	//.. something here ..

	target rt_renderwindow
	{
		pass render_scene
		{
			rq_first	200
			rq_last		255
		}
	}
}
This is what SSAO does. See Samples/Media/2.0/scripts/materials/Tutorial_SSAO/SSAO_HS.compositor

Or with multiple nodes.

However your code was not working because your input and outputs are poorly declared and wrongly connected. The manual explains how it's setup. To point out your specific problems:

Code: Select all

compositor_node TestRender
{
	in 0 rt_renderwindow
...
	target rt_renderwindow
	{
	}
...
	out 0 rtt
}
You left out at lot of code so I don't know if this is correct in your code. It appears you declare an input channel rt_renderwindow, render to it (so far so good) and then send a texture 'rtt' to output channel 0. This rtt texture is neither an input channel nor declared as a local variable. Thus this is wrong (unless you do declare it in your real code)

Now as for the workspace:

Code: Select all

workspace TestWorkspace
{
	connect			TestRender	0	1	TestWrite	0	1
	connect_output	TestWrite	1
}
TestRender has only 1 output channel, but you're connecting 2 output channels from TestRender into TestWrite's 2 input channels. This is impossible (TestRender doesn't have output channel #1, it only has output channel #0).
On the next line you overwrite that mistake by hooking the texture passed to addWorkspace (usually the render window) to TestWrite's input channel #1. This means TestRender's output channel #1 mistake is avoided.

However now you have TestRender wanting an input channel... which you never hook. Without seeing more of what you're doing I can't tell you how to fix this because I don't know what you're trying to do.
For a node to be valid:
  • If it has input channels, all of them must be connected
  • A node may have no input channel. This is valid. This is possible because you may render to a locally declared texture and export that texture via an output channel
I suggest you study the "Postprocessing" sample (Postprocessing.compositor) and the HDR sample (HDR.compositor).

Postprocessing sample creates a render node called PostprocessingSampleStdRenderer which renders the main render part; then hooks more nodes in the middle to apply postprocessing, and finally "FinalComposition" outputs to the render window.

The HDR sample does the same using HdrRenderingNode to render, then HdrPostprocessingNode to apply HDR bloom & tonemapping, and then HdrRenderUi at the end to render the UI on top of everything.
Frankincense
Kobold
Posts: 33
Joined: Mon May 05, 2014 5:36 pm
x 3

Re: [2.1] MRT incorrect texture data

Post by Frankincense »

Got it, thanks - here were my mistakes:

-I didn't see any of the other (probably more useful for my use-case) compositor scripts as I was always looking in Samples/Media/2.0/scripts/Compositors
-I didn't appreciate that 'connect_output' was connecting the output of the workspace to the input of the node, I assumed that 'rt_renderwindow' had a special meaning (and was it was the output of the node being connected to the RenderWindows input)
-Following from the above, both nodes require the 'rt_renderwindow' input being connected using 'connect_output <Node>'

So my final setup is something like:

Code: Select all

compositor_node TestRender
{
	in 0 rt_renderwindow
...
	target rt_renderwindow
	{
	}
...
	out 0 rtt
}

compositor_node TestWrite
{
	in 0 rtt
	in 1 rt_renderwindow
...
	target rt_renderwindow
	{
	}
}

Code: Select all

workspace TestWorkspace
{
	connect		TestRender	0	TestWrite	0
	connect_output	TestRender	0
	connect_output	TestWrite	1
}