Game Development Community

Help me please. How could I enable a full screen shader on a GameTSCtrl control?

by Francisco Montanes · in Torque 3D Professional · 01/02/2010 (7:21 am) · 11 replies

I have a full screen shader effect working perfectly. Now I want to make It work on the render control of my playgui (just on the GameTSCtrl, not in the whole screen area.
I'm newbie. There is an easy way? I've found some resources...

http://www.torquepowered.com/community/resources/view/17465

but GameTSCtrl has to be modified. I'm currently using T3D 1.01, and those modification works on order versions of T3D.

#1
01/02/2010 (9:21 am)
Just use a PostEffect. See the core\scripts\client\postFx folder for examples of different PostEffects.
#2
01/02/2010 (9:53 am)
Thanks Tom.
Yes, this is just what I did. It's working but in the whole screen. I want have the full screen shader effect active only on the GameTSCtrl control of my playGui.
#3
01/04/2010 (1:51 pm)
Did you set the renderTime in your PostEffect to PFXEndOfFrame? That would cause it to render across the entire screen and not just your PlayGui. Try PFXAfterDiffuse.
#4
01/04/2010 (7:20 pm)
Well... I'll try to explain what's happening now. The shader is taking a snapshot of the whole screen, even areas outside the GameTSCtrl and then is rendering on the GameTSCtrl. The good thing is that the shader is working inside de GameTSCtrl, but it's rendering a GameTSCtrl inside of a GameTSCtrl.

The ghost GameTSCtrl inside the GameTSCtrl have the 3D scene.


My code:

singleton PostEffect( MyPostFx )
{
requirements = "None";
allowReflectPass = false;

renderTime = "PFXAfterDiffuse";
//renderBin = "GlowBin";
renderPriority = 0.1;

// First we down sample the glow buffer.
shader = PFX_MyShader;
stateBlock = PFX_DefaultStateBlock;
texture[0] = "$backBuffer";
target = "$backBuffer";
targetScale = "1 1";
};

singleton ShaderData( PFX_MyShader )
{
DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
DXPixelShaderFile = "shaders/common/postFx/MyShaderP.hlsl";

pixVersion = 2.0;
};


//-------------------------------------------------------------------//
MyShaderP.hlsl
//-------------------------------------------------------------------//
struct VertOut
{
float2 tc0 : TEXCOORD0;
};

struct FragOut
{
float4 col : COLOR;
};

FragOut main(VertOut vin,
uniform sampler2D tex0 : TEXUNIT0
)
{

FragOut fout;
float4 vWeightsBW=float4(0.3,0.59,0.11,0);
float4 vWeightsSepia=float4(0.1,0.8,0.1,1);
float4 cColor=tex2D(tex0,vin.tc0);
float brightness=dot(cColor,vWeightsBW);

fout.col=brightness*vWeightsSepia;

return fout;
}

#5
01/04/2010 (9:54 pm)
If you look at the other PostEffects the texture coord passed to the pixel shader is calculated special so that it can read the right input coordinates from the $backbuffer.

See shaders\common\postFx\postFxV.hlsl for a generic vertex shader which should give you the correct texture coords.
#6
01/04/2010 (11:14 pm)
I didn't found the problem, so I tried using those shaders:
DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
DXPixelShaderFile = "shaders/common/postFx/passthruP.hlsl";

But I have the same defect as before.

Do this shaders should work properly on my GameTSCtrl?
#7
01/05/2010 (6:38 pm)
Those shaders are how all the shipped post effects work, but its possible its bugged in some way.

I'll have to do some testing to check it out.
#8
01/08/2010 (8:44 am)
I think that my problem is resumed in a simple question:

Can a full screen postFX work in a particular GameTSCtrl?

On other words.

How knows a postFX on witch GameTSCtrl has to work? And how a GameTSCtrl knows witch postFX is active on it?

Thanks for your time!
#9
01/08/2010 (10:16 am)
Well... I've resolved my problem!

The postFxV.hlsl has some ShaderConsts that have info of active viewport. Those ShaderConts are initialiced on PostEffect::_setupConstants. About the line 502 is where the viewport is "selected". And then I've found that the next piece of code is commented:


/*
if ( mActiveNamedTarget[i] )
targetVp = mActiveNamedTarget[i]->getTargetViewport();
else
{
targetVp = GFX->getViewport();
//targetVp.set( 0, 0, targetSz.x, targetSz.y );
}
*/

I've tried everything to fix problem... What the hell! Let's uncomment. And voilà!, now It work perfectly.

Just for curiosity... Why they are commented?
#10
01/08/2010 (12:28 pm)
Hum... i'm unsure of why the change was made in that spot, but i think i know the issue.

The issue is that the viewport its getting is not correct. It seems that for $backbuffer as an input texture we're only using the backbuffer size and not its offset. You can see this in PostEffect::_setupTexture() where the fix really belongs.

I believe that just grabbing GFX->getViewport() could be incorrect depending on the context... but lets test that theory.

First remove or comment out the block of code you uncommented.

Now in PostEffect::_setupTexture around line 732 comment out the following 2 lines:

else if ( texFilename.compare( "$backBuffer", 0, String::NoCase ) == 0 )
   {
      theTex = PFXMGR->getBackBufferTex();
      /* CHANGED!
      if ( theTex )
         viewport.set( 0, 0, theTex->getWidth(), theTex->getHeight() );
      */
   }

Give that a shot and do some testing with your case as well as try the different PostEffects like SSAO and LightRays. Also fire up the editor and see how the material preview window works.
#11
01/08/2010 (1:28 pm)
I made the changes.

Everything works perfectly.

I enabled SSAO, LightRays and seems to be ok.
The materia preview also works right.