Learning RTT : Render to texture

I’d be interested to see a RTT tutorial in the tech-artists wiki (I kind of struggling alone these days on this :rolleyes:)

It seems easier to put in practice with Rendermonkey than FXcomposer.

To me it looks like there’s a lot of specific semantic involved : both in the texture and sampler declaration (SAS stuff) and in the the technique / pass scripts + perhaps some #define lines ?

Of course good programers just do whatever they want simply with VisualStudio/XNA. :laugh:

It would be nice to explain these concepts to technical artists as it opens the door to post processing effect or more complicated multi-pass shading stuff… (shadow techniques, deferred shader, etc…)

Here is a quick example in Rendermonkey.
This is done just with a few clicks on the mouse :D:

It’s extremely basic but it’s a start :



It’s a little bit more complicated in FXcomposer.

ps : the reason I want to do this is that I’d like to do some image processing in the first pass before applying it on the geometry : this way you can add a proceduralish scrambled bump before doing the tex2dlod displacement and/or calculating the normal map in the second pass for example.

If you want to know more about this stuff : there’s an interesting talk here by the way :
http://developer.nvidia.com/forums/index.php?showtopic=1394&st=0&p=3012&#entry3012

sigh … when are they gonna release the next FXComposer ? :frowning:

The Nvidia SAS guide is nicely written but I’d be happy to see some clearer explainations of what’s in their “Quad.fxh” header.

If you have a copy of 3dsMax, the quad.fxh ships with it and its mostly a set of functions they use often.

It is a pretty big mess though :stuck_out_tongue:

[QUOTE=kees;1908]It is a pretty big mess though :P[/QUOTE]

OHH YES it is :D: !!!

If you plug their wizzard pre-setup post glow effect on top of your material : everything is working fine.

But I’ve never managed yet to create my own RTT from scratch : all I get is scrambled texels or pixels coming from somewhere from a buffer. In my case, I’d have to use their DECLARE_SIZED_TEX for fixed size render target.



I’ve scaled down and moved slightly to top right the screen quad vertices to keep an eye on it : the texture seems to appear fine, but I’d like it applied back on the object forwarded through “pass2” with “RTsampler” picked up by in pixel shader… weird… :?:

Here is the simple test.fx :

float4x4 WorldViewProj : WorldViewProjection <string UIWidget="None";> ;

float Script : STANDARDSGLOBAL <
    string UIWidget = "none";
    string ScriptClass = "object";
    string ScriptOrder = "standard";
    string ScriptOutput = "color";
    string Script = "Technique=Textured";
> = 0.8;

// "NVIDIA's header way of doing it"...
// you can comment/uncomment to swap with some of these to try...
// none of them worked for me :(

#include <HLSL\\include\\Quad.fxh>
//DECLARE_QUAD_TEX(RT_Tex,RTsampler,"A8R8G8B8")
//DECLARE_SQUARE_QUAD_TEX(RT_Tex,RTsampler,"A8R8G8B8",256)
//DECLARE_SIZED_TEX(RT_Tex,RTsampler,"A8R8G8B8",256,256)
//DECLARE_QUAD_TEX(RT_Tex,RTsampler,"A8R8G8B8")
//DECLARE_SIZED_QUAD_TEX(RT_Tex,RTsampler,"A8R8G8B8",1)


// My way : classic texture/sampler declaration : "the way Rendermonkey is outputing it"
texture2D RT_Tex : RENDERCOLORTARGET
<
   	//which SAS semantic is right and required or optional here ?
	
	//float2 ViewportRatio={1.0,1.0};
   	//float2 RenderTargetDimensions = {256,256};
   	//float2 Dimensions = {256,256};
   	float Width = 256;
   	float Height = 256;
   	string Format="A8R8G8B8";
   	string UIWidget = "none";
   	float  ClearDepth=1.000000f;
   	int    ClearColor=-16777216;
   	int Miplevels = 9;
>;

sampler RTsampler = sampler_state
{
   Texture = <RT_Tex>;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   MIPFILTER = LINEAR;
   MAGFILTER = LINEAR;
};

texture2D base_Tex ;
sampler Tex1 = sampler_state
{
   Texture = <base_Tex>;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   MINFILTER = LINEAR;
   MIPFILTER = LINEAR;
   MAGFILTER = LINEAR;
};

////////////
// PASS 1 //
////////////

void pass1VS (
	in float3 ipos	: POSITION,
	in float2 iuv 	: TEXCOORD,
	out float4 opos	: POSITION,
	out float2 ouv	: TEXCOORD1 )
{
	opos = float4(ipos.xz,0,1.5)+3;
	ouv = iuv*float2(1,-1);
}

float4 pass1PS( float2 uv : TEXCOORD1 ) : COLOR
{
  	return tex2D( Tex1, uv );
}

////////////
// PASS 2 //
////////////

void pass2VS( 
	in float4 ipos	: POSITION,
	in float2 iuv	: TEXCOORD,
	out float4 opos	: POSITION,
	out float2 ouv	: TEXCOORD2 )
{
   opos = mul( ipos, WorldViewProj );
   ouv = iuv;
}

float4 pass2PS( in float2 uv : TEXCOORD2 ) : COLOR
{   return tex2D( RTsampler, uv ); }

///////////////
// TECHNIQUE //
///////////////

technique Textured 

// what are we doing here ? what are thoses "scripts" ??
< string Script =
	"RenderColorTarget0=RT_Tex;"
	"ClearColor = (0, 0, 0, 255);"
	"Pass = pass1;"
	"Pass = pass2;";
>
{
	pass pass1 < string Script =
		"RenderColorTarget0=RT_Tex;"		
		"ClearColor = (0, 0, 0, 255);"
        "ClearDepth = 1.000000;";		
	>
	{
		VertexShader = compile vs_2_0 pass1VS();
		cullmode = none;
      	PixelShader = compile ps_2_0 pass1PS();
   	}
   	pass pass2		
   	{
      	VertexShader = compile vs_2_0 pass2VS();
      	PixelShader = compile ps_2_0 pass2PS();
   	}
}

I am with seb- RTT shaders are something I’ve never quite cracked. I was working on something really cool- Texture-based blendshapes in DX9 (like DX10’s version but doable in DX9), but I sputtered out on the RTT pre-processing pass. I understand the actual shader code, and how everything works in theory- I just have a grasp of how to implement it. If I sat down and took the time I am sure I could have figured it out, but this was right on job transitions and I haven’t done any shader work since. So for all the tech artists like me, some sort of comprehensive tutorial on the technical/linguistic aspects of RTT shaders would be really nice… rather than having to trial-and-error through big long code.

Here is the project spoken of above, sadly will remain unfinished until I crack the RTT egg! Texture-based Blendshapes in DX9 | RobG3d

I finally managed to make it work : (roughly understanding more or less what it does)

  • First of all : only full scene effects can work for now, effects applied on objects only should be fixed in Nvidia’s next release. (string ScriptClass = “object”; in the STANDARDGLOBAL) , so all this stuff will be appplied on all objects for now.

  • I found the tricky technique/pass scripting by trial’n’error as you said and I believe I’m not far from what it should be… here’s a tut I’ve been reading :
    Pieter Germishuys : Tutorial 7 - Render to Texture + the Nvidia SAS guide

  • The quad.fxh is a bit crazy and it takes some time to get around it but it does the job : however I couldn’t use any of their pre-defined fixed size RTT : I had to use screen quad sized methods only otherwise I still see mad pixels or broken depth buffer (inconsistent format perhaps? or smaller than the color buffer?) : maybe they’ll fix this one later… or maybe it’s my graphics card? (7600GS) : so feel free to try with yours…

Here’s the minimalist stuff I’ve come up with :


float4x4 WorldViewProj : WorldViewProjection <string UIWidget="None";> ;

float Script : STANDARDSGLOBAL <
    string UIWidget = "none";
    string ScriptClass = "scene";
    string ScriptOrder = "standard";
    string ScriptOutput = "color";
    string Script = "Technique=Main?:Main;";
> = 0.8;

float4 ClearColor <
string UIWidget = "color";
string UIName = "Background color";
> = {0,0,0,1.0};

float ClearDepth <
    string UIWidget = "None";
> = 1.0;

#include <HLSL\\include\\Quad.fxh>
DECLARE_QUAD_TEX(RT_Tex,RTsampler,"X8R8G8B8")
DECLARE_QUAD_DEPTH_BUFFER(DepthBuffer,"D24S8")

texture2D base_Tex ;
sampler Tex1 = sampler_state
{
   Texture = <base_Tex>;
   ADDRESSU = WRAP;
   ADDRESSV = WRAP;
   MINFILTER = LINEAR;
   MIPFILTER = LINEAR;
   MAGFILTER = LINEAR;
};

////////////
// PASS 1 //
////////////

void pass1VS (
	in float3 ipos	: POSITION,
	in float2 iuv 	: TEXCOORD,
	out float4 opos	: POSITION,
	out float2 ouv	: TEXCOORD1 )
{
	opos = float4(ipos.xz,0,1);
	ouv = iuv;
}

float4 pass1PS( float2 uv : TEXCOORD1 ) : COLOR
{  	return tex2D( Tex1, uv );	}

////////////
// PASS 2 //
////////////

void pass2VS( 
	in float4 ipos	: POSITION,
	in float2 iuv	: TEXCOORD,
	out float4 opos	: POSITION,
	out float2 ouv	: TEXCOORD2 )
{
   opos = mul( ipos, WorldViewProj );
   ouv = iuv;
}

float4 pass2PS( in float2 uv : TEXCOORD2 ) : COLOR
{   return tex2D( RTsampler, uv); }

///////////////
// TECHNIQUE //
///////////////

technique Main < string Script =
		"RenderColorTarget0=;"
		"RenderDepthStencilTarget0=;"
			"ClearSetColor=ClearColor;"
			"ClearSetDepth=ClearDepth;"
			"Clear=Color;"
			"Clear=Depth;"
	    	"ScriptExternal=color;"	
		"Pass = pass1;"
		"Pass = pass2;";	
>
{
	pass pass1 < string Script =
		"RenderColorTarget=RT_Tex;"
		"RenderDepthStencilTarget=DepthBuffer;"
		"Clear=Color;"
		"Clear=Depth;"
		"Draw=Geometry;";
	>
	{
		VertexShader = compile vs_1_0 pass1VS();
		PixelShader = compile ps_2_0 pass1PS();
   	}
   	pass pass2 < string Script =
		"RenderColorTarget0;"		
		"Clear=Color;"
		"Clear=Depth;"		
		"Draw=Scene;";
	>
   	{
      	VertexShader = compile vs_1_0 pass2VS();
      	PixelShader = compile ps_2_0 pass2PS();
   	}
}

Once you’vee assigned a texture to “base_Tex” (material property editor) ,
you drag’n’drop this effect on the DirectX preview window and it should apply automatically an “Evaluate” node under the Scene tree (which you can toggle on/off with the little checkbox)

And you’ll end up with your texture applied happily going through the RTT on the 2nd pass.

[QUOTE=Rob Galanakis;1922]Here is the project spoken of above, sadly will remain unfinished until I crack the RTT egg! Texture-based Blendshapes in DX9 | RobG3d

Yep : I saw your article about a month ago by the way, as I’m intersted by facial animation as well : I’d be very interested to see your implementation of the sparse morph target hacked on DX9…

Might be a silly question, but it’s a bit related. I need to clear a texture in FXComposer - I’m rendering in a pre-pass to a RenderTarget texture, then sampling it in the main vertex shader to get some vertex deforming calculations done and stored on the graphics card…

But, during testing, I get some crazy values in that texture, and I’m not sure how to clear them out without re-opening FXComposer.

So I’m hoping there’s a Texture.ClearToBlack() method or something similar I can access through the scripting interface - has anyone seen something like this?

~Alex