TSE Simple Full Screen Shader Effect
by decryptoid · 11/15/2005 (2:49 pm) · 61 comments
Download Code File
Remember to back up your files before using this example code!
Files... You may also download the files here:
Code Files
Download the code file and unzip the files as follows:
-- Unzip fullscreenEffects.cs into example/[yourmod directory]/client/scripts/
where [yourmod directory] is the name of your mod directory
-- Unzip all four .hlsl files to the /example/shaders/
-- Unzip both gameTSCtrl files to /engine/game/
Now Compile!...
Script Changes...
-- Open example/[yourmod directory]/client/init.cs and add the following code right after the IdleTimeout line...
-- Open example/[yourmod directory]/client/scripts/default.bind.cs and add the following code to the end:
Now Delete all your dso files... if you don't know how to do this just do a search on your mod directory for "*.dso" and delete all the files.
Run the game... you should be done!
Pressing "v" on the keyboard should toggle between heatvision, nightvision and regular vision.
About the shaders...
The shaders (hlsl files) are very simple. You can open them up in a text editor and see how they work. All they really do is convert the image to black and white then invert for heatvision and add all color channels to green for nightvision.
About the engine changes
Look at the new gameRenderEffect function in gameTSCtrl.cpp file for most of the changes. It's basically a copy of the regular GameRender function, but it renders to a surface then back to the screen with the shader.
What else you can do...
-- Add Bitmap "static" to the shaders
-- Write a cool custom screen shader!!
-- Look at the other shaders in the shaders directory to see how they work
-- Look in other parts of the engine code to see how to pass additional values to a custom shader. All the glowbuffer stuff is good for this
-- Modify this example code to be more dynamic. The two shaders are kinda hardcoded in there and it would be better to pass shader names in a script... that way you wouldn't have to re-compile for every shader change
NOTE: Since every one was waiting I made this example fairly quick. There may be unused variables or errors I didn't catch. Hopefully I included all the right files!
Problems:
-- The game will crash if the two shaders do not get loaded. This will happen if you put the exec line for the fullscreenEffect.cs file in the wrong place.
Remember to back up your files before using this example code!
Files... You may also download the files here:
Code Files
Download the code file and unzip the files as follows:
-- Unzip fullscreenEffects.cs into example/[yourmod directory]/client/scripts/
where [yourmod directory] is the name of your mod directory
-- Unzip all four .hlsl files to the /example/shaders/
-- Unzip both gameTSCtrl files to /engine/game/
Now Compile!...
Script Changes...
-- Open example/[yourmod directory]/client/init.cs and add the following code right after the IdleTimeout line...
// full screen effects
exec("./scripts/fullscreenEffects.cs");It is important that you place it immediately after the IdleTimeout line because the fullscreenEffects file must be loaded before the PlayGui is loaded or it will not work.-- Open example/[yourmod directory]/client/scripts/default.bind.cs and add the following code to the end:
//---------------------------------------
// fullscreen shader effects
//---------------------------------------
moveMap.bind(keyboard, "v", toggleEffectMode);
function toggleEffectMode(%val)
{
if(%val)
{
PlayGui.toggleEffectMode(0);
}
}Now Delete all your dso files... if you don't know how to do this just do a search on your mod directory for "*.dso" and delete all the files.
Run the game... you should be done!
Pressing "v" on the keyboard should toggle between heatvision, nightvision and regular vision.
About the shaders...
The shaders (hlsl files) are very simple. You can open them up in a text editor and see how they work. All they really do is convert the image to black and white then invert for heatvision and add all color channels to green for nightvision.
About the engine changes
Look at the new gameRenderEffect function in gameTSCtrl.cpp file for most of the changes. It's basically a copy of the regular GameRender function, but it renders to a surface then back to the screen with the shader.
What else you can do...
-- Add Bitmap "static" to the shaders
-- Write a cool custom screen shader!!
-- Look at the other shaders in the shaders directory to see how they work
-- Look in other parts of the engine code to see how to pass additional values to a custom shader. All the glowbuffer stuff is good for this
-- Modify this example code to be more dynamic. The two shaders are kinda hardcoded in there and it would be better to pass shader names in a script... that way you wouldn't have to re-compile for every shader change
NOTE: Since every one was waiting I made this example fairly quick. There may be unused variables or errors I didn't catch. Hopefully I included all the right files!
Problems:
-- The game will crash if the two shaders do not get loaded. This will happen if you put the exec line for the fullscreenEffect.cs file in the wrong place.
#43
Kindly help :)
10/07/2007 (6:57 am)
hey hi, what if i want only particular area of the screen to have same effect ... say only lower half of the screen ??Kindly help :)
#44
Edit: Bolding does not show up, so added comments instead
// TGEA 1.7 MOD - Begin
// TGEA 1.7 MOD - End
In the GameTSCtrl.cpp
Do NOT add the following code as it will not work.
Here is my replacement renderWorldEffect, I have BOLDED the lines I added
06/09/2008 (1:47 pm)
I have gotten this to work with TGEA 1.7, here are the code changes. You will need to implement the orginal, just need to be aware of my changes to get it to work. There maybe header includes of the standard stuff, but I figure you can find them out easily.Edit: Bolding does not show up, so added comments instead
// TGEA 1.7 MOD - Begin
// TGEA 1.7 MOD - End
//--------------------------------------- // fullscreen shader effects //--------------------------------------- ShaderData * mNightEffectShader; ShaderData * mHeatEffectShader; Point2F offsetConsts[4]; Point4F offsets; ColorF mFilterColor; GFXTexHandle mSurface[3]; // TGEA 1.7 MOD - Begin GFXTextureTargetRef mRenderTarget; // TGEA 1.7 MOD - End GFXTexHandle mBitmapObject; StringTableEntry mBitmapName; //---------------------------------------
In the GameTSCtrl.cpp
Do NOT add the following code as it will not work.
//GFXVideoMode mode = GFX->getVideoMode(); //mSurface[0].set( mode.resolution.x, mode.resolution.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, 1 );
Here is my replacement renderWorldEffect, I have BOLDED the lines I added
void GameTSCtrl::renderWorldEffect(const RectI &updateRect, ShaderData *mEffectShader, U32 objMask, GFXFillMode fMode)
{
FrameAllocator::setWaterMark(0);
// TGEA 1.7 MOD - Begin
if (mRenderTarget == NULL)
mRenderTarget = GFX->allocRenderToTextureTarget();
Point2I cursize = gClientSceneGraph->getDisplayTargetResolution();
for (int i =0; i < 3; i++)
{
if (mSurface[i].isNull())
mSurface[i] = GFX->getTextureManager()->createTexture(cursize.x, cursize.y, GFXFormatR8G8B8X8, &GFXDefaultRenderTargetProfile);
}
// TGEA 1.7 MOD - End
// rectangle points for calcs later
Point2I a = updateRect.point;
Point2I b = updateRect.point + updateRect.extent;
GFX->setZEnable( true ); //glEnable(GL_DEPTH_TEST);
GFX->setZFunc( GFXCmpLessEqual ); //glDepthFunc(GL_LEQUAL);
// Update the dynamic cubemaps on reflective objects
SimSet *reflectSet = dynamic_cast<SimSet*>( Sim::findObject( "reflectiveSet" ) );
for( SimSetIterator itr(reflectSet); *itr; ++itr )
{
if( *itr )
{
SceneObject *obj = (SceneObject*) *itr;
obj->updateReflection();
}
}
// Need to consoldate to one clear call // glClear(GL_DEPTH_BUFFER_BIT);
GFX->setCullMode( GFXCullNone );//glDisable(GL_CULL_FACE);
//************************************
//************************************
//************************************
GFX->setFillMode(fMode);
// TGEA 1.7 MOD - Begin
GFX->pushActiveRenderTarget();
// Set a starting texture so we can bind w/o any nulls.
mRenderTarget->attachTexture(GFXTextureTarget::Color0, mSurface[0]);
GFX->setActiveRenderTarget(mRenderTarget);
// TGEA 1.7 MOD - End
// if it's wireframe we have to clear every frame
if (fMode == GFXFillWireframe)
{
GFX->clear( GFXClearTarget, ColorI(0.5,0.5,0.5,0.5), 1.0f, 0 );
}
// assign the render mask if one came in
if (objMask)
{
gClientSceneGraph->renderScene( objMask );
} else {
gClientSceneGraph->renderScene( );
}
GFX->setFillMode(GFXFillSolid);
// TGEA 1.7 MOD - Begin
mRenderTarget->attachTexture(GFXTextureTarget::Color0, NULL);
GFX->popActiveRenderTarget();
// TGEA 1.7 MOD - End
//************************************
//************************************
//************************************
// set the clip
GFX->setClipRect(updateRect);
// turn off z clipping
GFX->setZEnable( false );
//************************************
//************************************
//************************************
//after this is all surfaces
//**************************************
// set ortho projection matrix
// this makes ur view of the effect appears as directly above
MatrixF proj = GFX->getProjectionMatrix();
MatrixF newMat(true);
GFX->setProjectionMatrix( newMat );
GFX->pushWorldMatrix();
GFX->setWorldMatrix( newMat );
GFX->setVertexShaderConstF( 0, (float*)&newMat, 4 ); // send the matrix to the shader
//
//**********************************
// ortho geometry
GFXVertexBuffer *vb=NULL;
PrimBuild::color4f( mFilterColor.red , mFilterColor.green , mFilterColor.blue, mFilterColor.alpha );
PrimBuild::beginToBuffer( GFXTriangleFan, 4 );
PrimBuild::texCoord2f( 0.0, 1.0 );
PrimBuild::vertex3f( -1.0 , -1.0 , 0.0 );
PrimBuild::texCoord2f( 0.0, 0.0 );
PrimBuild::vertex3f( -1.0 , 1.0 , 0.0 );
PrimBuild::texCoord2f( 1.0, 0.0 );
PrimBuild::vertex3f( 1.0 , 1.0 , 0.0 );
PrimBuild::texCoord2f( 1.0, 1.0 );
PrimBuild::vertex3f( 1.0 , -1.0 , 0.0 );
U32 numPrims;
vb = PrimBuild::endToBuffer( numPrims );
mEffectShader->shader->process();
GFX->setTexture( 0, mSurface[0] );
GFX->setVertexBuffer( vb );
GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
GFX->disableShaders();
//**********************************************
// render state cleanup
GFX->setAlphaBlendEnable( false );
GFX->setCullMode( GFXCullNone );
GFX->setLightingEnable( false );
GFX->setZWriteEnable( true );
GFX->setTextureStageColorOp( 0, GFXTOPDisable );
GFX->disableShaders();
GFX->popWorldMatrix();
FrameAllocator::setWaterMark(0);
}
#45
*Edited a Typo*
06/26/2008 (5:08 am)
Thanks for the fix, but I'm getting a lot of Z-buffer issues. Some stuff appear inside out, while other things aren't rendered at all.*Edited a Typo*
#46
Anyway, we're using this resource for full-screen fade in/from black and we noticed that when the filter is on, the image shifts down and right one pixel. This can sometimes leave a visible border on the top and left of the screen.
I can eliminate the border by increasing the vertex coordinates to say 1.01 but that creates it's own shifting problem. Is there something not being set or is it perhaps not accounting for the DirectX 0.5 pixel shift?
07/21/2008 (12:41 pm)
I have an issue with this in pre-TGEA 1.7. I haven't integrated to 1.7 yet.Anyway, we're using this resource for full-screen fade in/from black and we noticed that when the filter is on, the image shifts down and right one pixel. This can sometimes leave a visible border on the top and left of the screen.
I can eliminate the border by increasing the vertex coordinates to say 1.01 but that creates it's own shifting problem. Is there something not being set or is it perhaps not accounting for the DirectX 0.5 pixel shift?
#47
09/23/2008 (5:47 am)
Anyone found a way to fix this z-buffer issue? I tried to look through the code but didn't get any results, I guess I'm pretty rusty. Looks like some of the terrain is rendered somehow back to front order? It's weird since it doesn't seem to draw everything in this wrong order... could it also have something to do with the non-rendered object flags?
#48
any one can pls explain why vertex normals for all objects gets reversed when using the above code for torque 1.7.
the effects are working pretty nice but their is a serious texture issues that gets flipped due to vertex normals...
11/03/2008 (3:39 am)
hi ,any one can pls explain why vertex normals for all objects gets reversed when using the above code for torque 1.7.
the effects are working pretty nice but their is a serious texture issues that gets flipped due to vertex normals...
#49
I found the fix for it .
after the line
mRenderTarget->attachTexture(GFXTextureTarget::Color0, mSurface[0]);
you need to add
mRenderTarget->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil);
this will fix the z-buffer issue.
enjoy full screen effects :)
11/06/2008 (9:18 pm)
hi guys,I found the fix for it .
after the line
mRenderTarget->attachTexture(GFXTextureTarget::Color0, mSurface[0]);
you need to add
mRenderTarget->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil);
this will fix the z-buffer issue.
enjoy full screen effects :)
#50
11/11/2008 (7:42 am)
nevermind... missed where it said to ADD the above line... thought it was a replace. compiled and working in AFX + TGEA 1.7.x
#51
I'm an artist but only a budding programmer, so bear with me. I've implimented all of the things shown above into my 1.7.1 project with no compile errors and the scripts all seem fine. When I boot up the game, right after the startup GUI, I get a solid magenta color. The weird thing is that it seems to be behind one part of my GUI layer, but in front of everything else. The "v" key doesn't do anything of note, I don't get any errors in my log but nor do I get any output saying that the shaders loaded. Any ideas? Any thoughts on how I should try to debug it?
Thanks
11/21/2008 (10:12 am)
Hi All,I'm an artist but only a budding programmer, so bear with me. I've implimented all of the things shown above into my 1.7.1 project with no compile errors and the scripts all seem fine. When I boot up the game, right after the startup GUI, I get a solid magenta color. The weird thing is that it seems to be behind one part of my GUI layer, but in front of everything else. The "v" key doesn't do anything of note, I don't get any errors in my log but nor do I get any output saying that the shaders loaded. Any ideas? Any thoughts on how I should try to debug it?
Thanks
#52
11/21/2008 (2:59 pm)
OK, I understand why the full screen magenta is behind a part of GUI, because it's rendered on the PlayGui layer. The rest still evades me.
#53
11/21/2008 (3:40 pm)
I found that I had missed putting in the initShader call in my scripts. Put it in and now got the "...LOADED!!" messages, but still magenta.
#54
11/23/2008 (1:01 pm)
I get the same result. No compile or script errors, just a magenta background to my PlayGui.
#55
Edit: Ooops. renderWorld is being called just fine. N/M
Edit: Or is it? Break points don't stop there.
11/24/2008 (9:53 am)
Oh good! It's not just me. Are you also finding that GameTSCtrl::renderWorld isn't being called by anything? I'm trying to figure out where it should be.Edit: Ooops. renderWorld is being called just fine. N/M
Edit: Or is it? Break points don't stop there.
#56
11/24/2008 (11:41 am)
I'm finding that other "renderWorld"s (guiTSControl.cpp and an example from this link http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=5686) are being called in onRender. None of the above instructions list that, and when I put it in it gives me an error "Out of bounds viewport bounds". Am I getting close? Who knows.
#57
error C2027: use of undefined type 'GFXTextureManager'
error C2227: left of '->createTexture' must point to class/struct/union/generic type
error C2039: 'setZEnable' : is not a member of 'GFXDevice'
error C2039: 'setZFunc' : is not a member of 'GFXDevice'
error C2039: 'setCullMode' : is not a member of 'GFXDevice'
Etc, etc :(
It's the "GFX->xxxxx" that gives the problems.
Anyone with a solution? Thanks! :)
04/22/2009 (5:06 am)
IS there anyone who has this working for 1.8? I have applied all 1.7 changes mentioned by Simon but they don't work for 1.8. It appears that the GFX device has changed heavily since 1.7, these are the types of errors I'm getting:error C2027: use of undefined type 'GFXTextureManager'
error C2227: left of '->createTexture' must point to class/struct/union/generic type
error C2039: 'setZEnable' : is not a member of 'GFXDevice'
error C2039: 'setZFunc' : is not a member of 'GFXDevice'
error C2039: 'setCullMode' : is not a member of 'GFXDevice'
Etc, etc :(
It's the "GFX->xxxxx" that gives the problems.
Anyone with a solution? Thanks! :)
#58
http://www.garagegames.com/community/blogs/view/15436
I'll try it this way, but let me know if you have any progress! I suppose they're all working on Torque 3D.
04/27/2009 (3:36 pm)
One of the major features of 1.8 is that they now pass commands to GFX as a structure...http://www.garagegames.com/community/blogs/view/15436
I'll try it this way, but let me know if you have any progress! I suppose they're all working on Torque 3D.
#59
http://www.garagegames.com/community/forums/viewthread/90299
04/30/2009 (2:06 am)
I made a thread on the forum about it, linking to this resource. I hope to find an answer this way. Thanks for the clarification anyway Tobyn!http://www.garagegames.com/community/forums/viewthread/90299
#60
GFXStateBlockDesc desc;
desc.setCullMode( GFXCullNone );
desc.setZEnable(false);
desc.zWriteEnable = false;
desc.samplersDefined = true;
desc.samplers[0].textureColorOp = GFXTOPModulate;
desc.samplers[1].textureColorOp = GFXTOPDisable;
desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
... and so on
05/08/2009 (1:43 pm)
you need something like this GFX state block:GFXStateBlockDesc desc;
desc.setCullMode( GFXCullNone );
desc.setZEnable(false);
desc.zWriteEnable = false;
desc.samplersDefined = true;
desc.samplers[0].textureColorOp = GFXTOPModulate;
desc.samplers[1].textureColorOp = GFXTOPDisable;
desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
... and so on

Torque Owner TSK