Forum

First Shader - some problems

Hi,

Im a Vvvv-Newbie and started to program a little shader. Seems easier than I thought. But its just a 2d-Shader.

I wrote a Erode-Dilate-Shader for cleaning my Livefeed of noise at lowlevel lighting. It works well for the Dilate and the Erode-mode. But now I tried to combine both - one after the other - to get a Open-mode (like the Intel Processing Library).
-But that doesnt work, because I dont know how to save the results of the first pass (Dilate code) and grab it with the later Erode code.

Thanks Frank

Here is the code - a modified kernel example:
{CODE(ln=>1)}
// this is an effect template. use it to start writing your own effects.

// -------------------------------------------------------------------------
// PARAMETERS:
// -------------------------------------------------------------------------

//transforms
float4x4 tW: WORLD; //the models world matrix
float4x4 tV: VIEW; //view matrix as set via Renderer (DX9)
float4x4 tP: PROJECTION; //projection matrix as set via Renderer (DX9)
float4x4 tWVP: WORLDVIEWPROJECTION;

//texture
texture Tex <string uiname=“Texture”;>;
sampler Samp = sampler_state //sampler for doing the texture-lookup
{
Texture = (Tex); //apply a texture to the sampler
MipFilter = LINEAR; //set the sampler states LINEAR
MinFilter = LINEAR;
MagFilter = LINEAR;
};
//texture transformation marked with semantic TEXTUREMATRIX to achieve symmetric transformations
float4x4 tTex: TEXTUREMATRIX <string uiname=“Texture Transform”;>;

//pin for pixeldiameter
int TexWidth <string uiname=“Texture Width”;> = 512;
int TexHeight <string uiname=“Texture Height”;> = 512;

//the data structure: “vertexshader to pixelshader”
//used as output data with the VS function
//and as input data with the PS function
struct vs2ps
{
float4 Pos : POSITION;
float4 TexCd : TEXCOORD0;
float2 Pixelsize : TEXCOORD1;

};

// -------------------------------------------------------------------------
// VERTEXSHADERS
// -------------------------------------------------------------------------

vs2ps VS(float4 Pos : POSITION, float4 TexCd : TEXCOORD0) {
//inititalize all fields of output struct with 0
vs2ps Out = (vs2ps)0;

//transform position
Out.Pos = mul(Pos, tWVP);

//transform texturecoordinates
Out.TexCd = mul(TexCd, tTex);

//you can calculated things here aswell
//we calculated here the "pixelsize" = 1/texture size
Out.Pixelsize = 1 /float (TexWidth);

return Out;
}

// -------------------------------------------------------------------------
// PIXELSHADERS:
// -------------------------------------------------------------------------

// The surrounding pixels
float2 neighbours8 = {
-1, -1,
0, -1,
1, -1,
-1, 0,
1, 0,
-1, 1,
0, 1,
1, 1,
};

//Dilate - Outputs the minimum of the center and neighbours
float4 PS_erode(vs2ps In): COLOR {

float4 minSamp = tex2D(Samp, In.TexCd);
for (int i = 0; i < 8; i++) {
float4 tmpSample = tex2D(Samp, In.TexCd + In.Pixelsize * neighboursi);
minSamp = min(minSamp, tmpSample);
}

return minSamp;
}

//Dilate - Outputs the minimum of the center and neighbours
float4 PS_dilate(vs2ps In): COLOR {

float4 maxSamp = tex2D(Samp, In.TexCd);
for (int i = 0; i < 8; i++) {
float4 tmpSample = tex2D(Samp, In.TexCd + In.Pixelsize * neighboursi);
maxSamp = max(maxSamp, tmpSample);
}

return maxSamp;
}

//Open - First Dilate then Erode
float4 PS_open(vs2ps In): COLOR {

float4 minSamp = tex2D(Samp, In.TexCd);
for (int i = 0; i < 8; i++) {
float4 tmpSample = tex2D(Samp, In.TexCd + In.Pixelsize * neighboursi);
minSamp = min(minSamp, tmpSample);
}

float4 maxSamp = tex2D(Samp, In.TexCd);
for (int i = 0; i < 8; i++) {
float4 tmpSample = tex2D(Samp, In.TexCd + In.Pixelsize * neighboursi);
maxSamp = max(maxSamp, tmpSample);
}

return maxSamp;
}

// bypass
float4 PS0(vs2ps In): COLOR {
float4 col = tex2D(Samp, float2 (In.TexCd.x, In.TexCd.y));
return col;
}

// -------------------------------------------------------------------------
// TECHNIQUES:
// -------------------------------------------------------------------------

technique Erode
{
pass P0
{
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_2_0 PS_erode();
}
}

technique Dilate
{
pass P0
{
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_2_0 PS_dilate();
}
}

technique Open
{
pass P0
{
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_2_0 PS_open();
}
}

technique Bypass
{
pass P0
{
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_2_0 PS0();
}
}

^

halo frank.

i am afraid you are facing a limitation of vvvvs current implementation of the effects system. multiple consecutive passes where one passes result is passed to the next one for further processing (i.e. the first pass rendering to a rendertarget, and the second pass taking that rendertarget as input texture) are not yet feasible.

What you actually can do is render your first pass and use DX9Texture to render that with a second pass shader. Thats quite easy, and shouldnt be a much of a performance hit.

Or use the shader you already have and just switch the technique at the second renderer.

Hallo Joreg,

thanks for the fast reply. So I will skip that two-in-one pack. It works well one after the other.

Please, can you explain me or give a link for what the texturesize pin (width and height) is good for?
I want to feed the shaders with a webcam 640x480px. I had read that shaders works with 256x256, 512x512, 1024x1024,…

Thanks Frank

Hey,

like your erode / dilate code

i put it together to a simple videoadjust shader in combination with brightness,contrast, color transform, invert, point and linear filtering… (ps 3.0 needed)

you can try it here:videoAdjust

ah…sorry for being late.

the texture width and height pins are only needed because a pixelshader does not know the size of a texture it operates on. so if in a pixelshader-call you want to access several pixels (not only the one that the current texture-coordinates can acccess) you need to know how far you have to go left, right, up, down to read exactly the next pixel.

note that texture coordinates are in the range of 0 to 1. so to access individual pixels you have to access a multiple of x=1/texturewidth and y=1/textureheight.

uh. does that make sense?