Search Home Members Contacts
About Us
Products
Downloads
Community
Support
Pages: [1]
  Print  
Author Topic: Post-Process Shaders  (Read 650 times)
Soganatsu
Customers
Community Member
*****
Posts: 22


« on: March 07, 2008, 01:15:31 PM »

Hey there!
I got here a very nice DOF (actually way better than TV's integrated) shader which I want to implement into my TV-Project.
Let me say, I read the FAQ ^^

here's the shader code:

Code:
/************************************************************************/
/* Post Processing for DepthOfField                                     */
/************************************************************************/

//3x3 Gauss-Blur
float blurSampleWeights[3] = {.274069,.451863,.274069 };

//Used as buffer for downsc. and blurring, AND as Low-Res Version in Final Pass
samplerRECT bufferSamplerDEBUG = sampler_state {
MinFilter = Linear;
MagFilter = Linear;
WrapS = ClampToEdge;
WrapT = ClampToEdge;
};

samplerRECT bufferSampler = sampler_state {
MinFilter = Linear;
MagFilter = Linear;
WrapS = ClampToEdge;
WrapT = ClampToEdge;
};

samplerRECT gbufferSampler = sampler_state {
MinFilter = Nearest;
MagFilter = Nearest;
WrapS = ClampToEdge;
WrapT = ClampToEdge;
};

//Hi-Res Original Image w. Destination Alpha
samplerRECT bufferSamplerHiRes = sampler_state {
MinFilter = Linear;
MagFilter = Linear;
WrapS = ClampToEdge;
WrapT = ClampToEdge;
};

//VARS For Final DOF - PASS
//On Gef7 8, 4 other hardware
#ifdef HQDFILTER
#define NUM_TAPS 8
#else
#define NUM_TAPS 4
#endif

//NOTE: 4 Taps best Performance / Quality setting
// 6 Taps better Quality / OK Performance
// 8 Taps best Quality / better have a GeForce 7

// poisson-distributed positions
float2 poisson[8] = {
float2( 0.0, 0.0),
float2( 0.527837,-0.085868),
float2(-0.040088, 0.536087),
float2(-0.670445,-0.179949),
float2(-0.419418,-0.616039),
float2( 0.440453,-0.639399),
float2(-0.757088, 0.349334),
float2( 0.574619, 0.685879)
};
 //NOTE: Dont think we need pixel-size, as we use nv-rects...

float2 maxCoC = float2(5.0, 10.0);
//float2 maxCoC = float2(.42, .84);
float radiusScale = .4; //Used on lower res. image


//DEBUG
float fudgeLow;
float fudgeLowScale;

/*** Downsampling and appyling 4x4 Box-Filter ***/

struct downsampleVsOutput
{
float4 HPosition : POSITION;
float2 UV[4] : TEXCOORD0;
};

downsampleVsOutput DownsampleVS(float4 Position : POSITION, float2 TexCoord : TEXCOORD0) {

downsampleVsOutput OUT;

//Preparing Coords for downsampling by 4 with 4x4 box filter...
float2 s = TexCoord;// + float2(-1.0, -1.0);
OUT.HPosition = Position;

OUT.UV[0] = s;
OUT.UV[1] = s + float2(2,0);
OUT.UV[2] = s + float2(2,2);
OUT.UV[3] = s + float2(0,2);

return OUT;
}

struct simplestVsOutput
{
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
//float2 UVscaled : TEXCOORD1;
};

struct simplestVsOutputPlusScaled
{
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
float2 UV_scaled : TEXCOORD1;
};

/*** Very simple Vertex - Shader for PostProcessing ***/

simplestVsOutput PostVS(float4 Position : POSITION, float2 TexCoord : TEXCOORD0) {

simplestVsOutput OUT;

OUT.HPosition = Position;
OUT.UV = TexCoord;// + float2(fudgeLow, fudgeLow);
//note *.25 + fudge of .00178
//OUT.UVscaled = (TexCoord+1)*(0.25178);

return OUT;
}

simplestVsOutputPlusScaled simplestVP_scaled(float4 Position : POSITION, float2 TexCoord : TEXCOORD0) {
simplestVsOutputPlusScaled OUT;
OUT.HPosition = Position;
OUT.UV = TexCoord;
OUT.UV_scaled = TexCoord * 0.25;
return OUT;
}

float4 DownsamplePS(downsampleVsOutput IN, uniform samplerRECT tex) : COLOR {
half3 result;
result = h3texRECT(tex, IN.UV[0])* .25;
result += h3texRECT(tex, IN.UV[1])*.25;
result += h3texRECT(tex, IN.UV[2])*.25;
result += h3texRECT(tex, IN.UV[3])*.25;

return float4(result, 1.0f);
}

//watch out with changing the big arrays...
float4 BlurPSHoriz( simplestVsOutput IN ) : COLOR0
{
//accumulated color
half4 vAccum = half4( 0.0f, 0.0f, 0.0f, 0.0f );
//vAccum = texRECT( bufferSampler, IN.UV );// * blurSampleWeights[i+1];
for( int i = -1; i < 2; i++ )
{
float2 texCoord = IN.UV + float2(i,0);
vAccum += h4texRECT( bufferSampler, texCoord ) * (half) blurSampleWeights[i+1];
}
return vAccum;
}

float4 BlurPSVert( simplestVsOutput IN ) : COLOR0
{
//accumulated color
half4 vAccum = half4( 0.0f, 0.0f, 0.0f, 0.0f );
//vAccum = texRECT( bufferSampler, IN.UV );// * blurSampleWeights[i+1];
for( int i = -1; i < 2; i++ )
{
float2 texCoord = IN.UV + float2(0,i);
vAccum += h4texRECT( bufferSampler, texCoord ) * (half) blurSampleWeights[i+1];
}
return vAccum;
}

/*** Poisson Distributed DOF - Filter ***/

float4 PoissonDOFFilter(simplestVsOutputPlusScaled IN) : COLOR {

half4 cOut;
half discRadius;
half discRadiusLow;
half centerDepth;

//cOut = texRECT(bufferSamplerHiRes, IN.UV);

//Dirty Copy?
//half2 texCoord = IN.UV;
//half2 texCoordScaled = IN.UVscaled;
cOut = h4texRECT(bufferSamplerHiRes, IN.UV); // fetch center tap
centerDepth = cOut.a; // retrieve its depth
// convert depth into blur radius in pixels
discRadius = abs(cOut.a * maxCoC.y - maxCoC.x);
// compute disc radius on low-res image
discRadiusLow = discRadius * radiusScale;
// reuse cOut as an accumulator
cOut = 0;
for(int t = 0; t < NUM_TAPS; t++)
{
// fetch low-res tap * half2(1.01, 1.01
//watch out, lower coord are aso rect-coords, so scale down as we get 0..1024
half2 coordLow = IN.UV_scaled + ((half2) poisson[t] * discRadiusLow);
half4 tapLow = h4texRECT(bufferSampler, IN.UV_scaled);
//tapLow.x = 1.0;
// fetch high-res tap
half2 coordHigh = IN.UV.xy + ((half2) poisson[t] * discRadius);
half4 tapHigh = h4texRECT(bufferSamplerHiRes, coordHigh);
//tapHigh.z = 1.0;
// put tap blurriness into [0, 1] range
half tapBlur = abs(tapHigh.a * 2.0 - 1.0);
// mix low- and hi-res taps based on tap blurriness
half4 tap;
/*if (centerDepth > 0.0035 && centerDepth < 0.005)
tap = (tapHigh + tapLow) / 2;
else*/
tap = lerp(tapHigh, tapLow, tapBlur);
// apply leaking reduction: lower weight for taps that are
// closer than the center tap and in focus
tap.a = (tap.a >= centerDepth) ? 1.0 : abs(tap.a * 2.0 - 1.0);
// accumulate
cOut.rgb += tap.rgb * tap.a;
cOut.a += tap.a;
}
// normalize and return result
cOut = (cOut / cOut.a);
return float4(cOut);
}

/*** SIMPLE TEX OUTPUT OF BUFFER ***/

float4 ShowBufferPS(simplestVsOutput IN) : COLOR {
float4 result;
result = texRECT(bufferSamplerDEBUG, IN.UV);
result.xyz = result.aaa;
return result;
}

technique DepthOfField {

    pass Downsample{

CullfaceEnable = false;
DepthTestEnable = false;
VertexProgram = compile vp40 DownsampleVS();
        FragmentProgram = compile fp40 DownsamplePS(bufferSampler);

    }

pass BlurHoriz{

CullfaceEnable = false;
DepthTestEnable = false;
VertexProgram = compile vp40 PostVS();
FragmentProgram = compile fp40 BlurPSHoriz();

}

pass BlurVert{

CullfaceEnable = false;
DepthTestEnable = false;
VertexProgram = compile vp40 PostVS();
FragmentProgram = compile fp40 BlurPSVert();

}

pass ApplyDof{

CullfaceEnable = false;
DepthTestEnable = false;
VertexProgram = compile vp40 simplestVP_scaled();
FragmentProgram = compile fp40 PoissonDOFFilter();

}

pass ShowBuffer {

/*DepthTestEnable = false;*/
VertexProgram = compile vp40 PostVS();
FragmentProgram = compile fp40 ShowBufferPS();

}
}

Let me also say it's not mine so I only want to use it for testing purposes.

So, here are my questions:

1) Are there any limitations in TV regarding shader files? Like f.e. special structures, that can't be used, etc.
2) How would I go about including the shader to post-process my scene? I don#t have any clue on which object I should apply it.

I hope someone can help me.

Cya,
Philipp
Logged
jviper
Community Member
*
Posts: 1280

Discipline in training


« Reply #1 on: March 08, 2008, 09:46:53 AM »

Hello
The only limitations on the shaders should be in your hardware. Oh, and there may be some semantic incompatabilities depending on which application you wrote the shader in so you may have to tweak the shader file.

To do your post-processing, what you wanna do is first render your scene to a rendersurface. After that render, you should pass this rendersurface as a texture (rendersurface.gettexture) to the TVScreen2DImmidiete's Draw_FullScreenQuadWithShader.
When rendering to the texture, use the rendersurface.BeginRender........rendersurface.EndRender outside of the TVEngine.Clear........TVEngine.RenderToScreen. Then inside the TVEngine.Clear......TVEngine.RenderToScreen, use the TVScreen2DImmidiete.Draw_FullScreenQuadWithShader. If you need help "fitting your Post-Proccessing to TV3D", follow the FullScreenShader.fx for reference on what needs to be done. This shader file should be availiable somewhere under the resource section of this site.

Good luck.
Logged

JAbstract.....Don't just imagine, make it happen!
Soganatsu
Customers
Community Member
*****
Posts: 22


« Reply #2 on: March 08, 2008, 01:04:16 PM »

Ah Thank you so much! The QuadWithShader was the thing I was looking for Wink
Logged
Soganatsu
Customers
Community Member
*****
Posts: 22


« Reply #3 on: March 09, 2008, 10:31:45 AM »

Okay,.. the problem now is that I can't just create/delete a texture every frame.. it's way too slow. If I just leave it like:

Code:
tv2d.Action_Begin2D()
            tv2d.Draw_FullscreenQuadWithShader(shader, 0, 0, 1, 1, RenderSurface.GetTexture)
            tv2d.Action_End2D()

then there's a huge memory leak. So what can I do about that? Also is it right that I'm putting the gettexture on the optionaltex1 parameter?

Cya,
Philipp

[EDIT]

Okay, I got a simple Downsampling Shader working.. but nothing else is working.. I really don't understand how TV handles FX Files..

F.e. when I try to load some galaxy creation shader I found in a book it says:

Code:
D:\Eigene Dateien\Visual Studio 2005\Projects\Map Editor\Map Editor\bin\Debug\test.fx(4): warning X3083: Truncating 4-vector to size 1
D:\Eigene Dateien\Visual Studio 2005\Projects\Map Editor\Map Editor\bin\Debug\test.fx(7): error X3000: syntax error: unexpected token 'Out'

And I don't have any clue what I can do about it.. here's the code if you wanna have a look:

Code:
float random(float2 xy,sampler2D BaseTexture)
// Index into texture filled with random values
{
float color=tex2D(BaseTexture,xy);
return color;
}
Pix Out;
float2 InputTest;
float4 center;
center.x=.5;
center.y=.5;
center.z=.0;
center.w=.0;
float d=distance(center,In.tex);
float randomtexture=random((In.tex.xy*10)+Time.xx,BaseTexture);//Random texture
d=(1-d*2)*pow(randomtexture,d*10);
Out.dif.x=d;
Out.dif.y=d;
Out.dif.z=d;

I can't even open it with the DX Viewer.
« Last Edit: March 09, 2008, 10:43:29 AM by Soganatsu » Logged
WEst
Community Member
*
Posts: 800

Daniel Martinek


WWW
« Reply #4 on: March 09, 2008, 11:44:53 AM »

There are mainly two problems with the shader:

1. The shader is written in C for Graphics (CG) and not the High Level Shading Language (HLSL) which is used in Microsofts .fx files.

2. The shader is quite complicated to use.

I solved 1. for you, but 2. you have to solve yourself because I'm currently running out of time  Wink(have to leave soon, returning in one week).

This is the above shader code in HLSL (only changed the syntax, don't know if there are any other things wrong):

Code:
/************************************************************************/
/* Post Processing for DepthOfField                                     */
/************************************************************************/

//3x3 Gauss-Blur
float blurSampleWeights[3] = {.274069,.451863,.274069 };

//Used as buffer for downsc. and blurring, AND as Low-Res Version in Final Pass
sampler2D bufferSamplerDEBUG = sampler_state {
MinFilter = Linear;
MagFilter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};

sampler2D bufferSampler = sampler_state {
MinFilter = Linear;
MagFilter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};

sampler2D gbufferSampler = sampler_state {
MinFilter = point;
MagFilter = point;
AddressU = Clamp;
AddressV = Clamp;
};

//Hi-Res Original Image w. Destination Alpha
sampler2D bufferSamplerHiRes = sampler_state {
MinFilter = Linear;
MagFilter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};

//VARS For Final DOF - PASS
//On Gef7 8, 4 other hardware
#ifdef HQDFILTER
#define NUM_TAPS 8
#else
#define NUM_TAPS 4
#endif

//NOTE: 4 Taps best Performance / Quality setting
// 6 Taps better Quality / OK Performance
// 8 Taps best Quality / better have a GeForce 7

// poisson-distributed positions
float2 poisson[8] = {
float2( 0.0, 0.0),
float2( 0.527837,-0.085868),
float2(-0.040088, 0.536087),
float2(-0.670445,-0.179949),
float2(-0.419418,-0.616039),
float2( 0.440453,-0.639399),
float2(-0.757088, 0.349334),
float2( 0.574619, 0.685879)
};
 //NOTE: Dont think we need pixel-size, as we use nv-rects...

float2 maxCoC = float2(5.0, 10.0);
//float2 maxCoC = float2(.42, .84);
float radiusScale = .4; //Used on lower res. image


//DEBUG
float fudgeLow;
float fudgeLowScale;

/*** Downsampling and appyling 4x4 Box-Filter ***/

struct downsampleVsOutput
{
float4 HPosition : POSITION;
float2 UV[4] : TEXCOORD0;
};

downsampleVsOutput DownsampleVS(float4 Position : POSITION, float2 TexCoord : TEXCOORD0) {

downsampleVsOutput OUT;

//Preparing Coords for downsampling by 4 with 4x4 box filter...
float2 s = TexCoord;// + float2(-1.0, -1.0);
OUT.HPosition = Position;

OUT.UV[0] = s;
OUT.UV[1] = s + float2(2,0);
OUT.UV[2] = s + float2(2,2);
OUT.UV[3] = s + float2(0,2);

return OUT;
}

struct simplestVsOutput
{
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
//float2 UVscaled : TEXCOORD1;
};

struct simplestVsOutputPlusScaled
{
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
float2 UV_scaled : TEXCOORD1;
};

/*** Very simple Vertex - Shader for PostProcessing ***/

simplestVsOutput PostVS(float4 Position : POSITION, float2 TexCoord : TEXCOORD0) {

simplestVsOutput OUT;

OUT.HPosition = Position;
OUT.UV = TexCoord;// + float2(fudgeLow, fudgeLow);
//note *.25 + fudge of .00178
//OUT.UVscaled = (TexCoord+1)*(0.25178);

return OUT;
}

simplestVsOutputPlusScaled simplestVP_scaled(float4 Position : POSITION, float2 TexCoord : TEXCOORD0) {
simplestVsOutputPlusScaled OUT;
OUT.HPosition = Position;
OUT.UV = TexCoord;
OUT.UV_scaled = TexCoord * 0.25;
return OUT;
}

float4 DownsamplePS(downsampleVsOutput IN, uniform sampler2D tex) : COLOR {
half3 result;
result = tex2D(tex, IN.UV[0])* .25;
result += tex2D(tex, IN.UV[1])*.25;
result += tex2D(tex, IN.UV[2])*.25;
result += tex2D(tex, IN.UV[3])*.25;

return float4(result, 1.0f);
}

//watch out with changing the big arrays...
float4 BlurPSHoriz( simplestVsOutput IN ) : COLOR0
{
//accumulated color
half4 vAccum = half4( 0.0f, 0.0f, 0.0f, 0.0f );
//vAccum = texRECT( bufferSampler, IN.UV );// * blurSampleWeights[i+1];
for( int i = -1; i < 2; i++ )
{
float2 texCoord = IN.UV + float2(i,0);
vAccum += tex2D( bufferSampler, texCoord ) * (half) blurSampleWeights[i+1];
}
return vAccum;
}

float4 BlurPSVert( simplestVsOutput IN ) : COLOR0
{
//accumulated color
half4 vAccum = half4( 0.0f, 0.0f, 0.0f, 0.0f );
//vAccum = texRECT( bufferSampler, IN.UV );// * blurSampleWeights[i+1];
for( int i = -1; i < 2; i++ )
{
float2 texCoord = IN.UV + float2(0,i);
vAccum += tex2D( bufferSampler, texCoord ) * (half) blurSampleWeights[i+1];
}
return vAccum;
}

/*** Poisson Distributed DOF - Filter ***/

float4 PoissonDOFFilter(simplestVsOutputPlusScaled IN) : COLOR {

half4 cOut;
half discRadius;
half discRadiusLow;
half centerDepth;

//cOut = texRECT(bufferSamplerHiRes, IN.UV);

//Dirty Copy?
//half2 texCoord = IN.UV;
//half2 texCoordScaled = IN.UVscaled;
cOut = tex2D(bufferSamplerHiRes, IN.UV); // fetch center tap
centerDepth = cOut.a; // retrieve its depth
// convert depth into blur radius in pixels
discRadius = abs(cOut.a * maxCoC.y - maxCoC.x);
// compute disc radius on low-res image
discRadiusLow = discRadius * radiusScale;
// reuse cOut as an accumulator
cOut = 0;
for(int t = 0; t < NUM_TAPS; t++)
{
// fetch low-res tap * half2(1.01, 1.01
//watch out, lower coord are aso rect-coords, so scale down as we get 0..1024
half2 coordLow = IN.UV_scaled + ((half2) poisson[t] * discRadiusLow);
half4 tapLow = tex2D(bufferSampler, IN.UV_scaled);
//tapLow.x = 1.0;
// fetch high-res tap
half2 coordHigh = IN.UV.xy + ((half2) poisson[t] * discRadius);
half4 tapHigh = tex2D(bufferSamplerHiRes, coordHigh);
//tapHigh.z = 1.0;
// put tap blurriness into [0, 1] range
half tapBlur = abs(tapHigh.a * 2.0 - 1.0);
// mix low- and hi-res taps based on tap blurriness
half4 tap;
/*if (centerDepth > 0.0035 && centerDepth < 0.005)
tap = (tapHigh + tapLow) / 2;
else*/
tap = lerp(tapHigh, tapLow, tapBlur);
// apply leaking reduction: lower weight for taps that are
// closer than the center tap and in focus
tap.a = (tap.a >= centerDepth) ? 1.0 : abs(tap.a * 2.0 - 1.0);
// accumulate
cOut.rgb += tap.rgb * tap.a;
cOut.a += tap.a;
}
// normalize and return result
cOut = (cOut / cOut.a);
return float4(cOut);
}

/*** SIMPLE TEX OUTPUT OF BUFFER ***/

float4 ShowBufferPS(simplestVsOutput IN) : COLOR {
float4 result;
result = tex2D(bufferSamplerDEBUG, IN.UV);
result.xyz = result.aaa;
return result;
}

technique DepthOfField {

    pass Downsample{

CullMode =none ;
VertexShader = compile vs_2_0 DownsampleVS();
        PixelShader = compile ps_2_0 DownsamplePS(bufferSampler);

    }

pass BlurHoriz{

CullMode =none ;
VertexShader = compile vs_2_0 PostVS();
PixelShader = compile ps_2_0 BlurPSHoriz();

}

pass BlurVert{

CullMode =none ;
VertexShader = compile vs_2_0 PostVS();
PixelShader = compile ps_2_0 BlurPSVert();

}

pass ApplyDof{

CullMode =none ;
VertexShader = compile vs_2_0 simplestVP_scaled();
PixelShader = compile ps_2_0 PoissonDOFFilter();

}

pass ShowBuffer {

/*DepthTestEnable = false;*/
VertexShader = compile vs_2_0 PostVS();
PixelShader = compile ps_2_0 ShowBufferPS();

}
}
Logged

Greetings

Daniel Martinek
Lead Programmer
Roaming Nova Studios
Soganatsu
Customers
Community Member
*****
Posts: 22


« Reply #5 on: March 10, 2008, 03:16:54 PM »

Thank you so much Wink I didn't even know that this wasn't HLSL ^^

So I'm gonna try that out by tomorrow and tell you if it worked Wink
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF 1.1.3 | SMF © 2006-2007, Simple Machines LLC
Seo4Smf v0.2 © Webmaster's Talks