Generating random numbers in a pixel shader

Posted By: TehV

Generating random numbers in a pixel shader - 07/14/14 22:01

Hi,
I'm in the process of learning my way around shaders and thought I'd start with something simple. What I'm trying to achieve is a simple pixel shader that will color each pixel in a model a random gray tone. The pixels should be colored independently of eachother.

So basically, I'm trying to draw a random monochrome noise onto the screen, in the shape of a 3D model, if that makes more sense.

I was able to make the whole model a solid gray color and have it flicker as a whole, but I have not been able to color individual pixels.
I've done a bit of research on this topic and came up with this:

Code:
//Flicker/Noise Shader

float4 vecTime;

float4 ps_flicker(in float2 screenSpace : VPOS): COLOR {
	return noise(float3(screenSpace.x,screenSpace.y,vecTime.w));
}

technique flicker
{
	pass p0
	{
		PixelShader = compile ps_1_1 ps_flicker();
	}
}



I'm basically trying to use the screen position of the pixel as a sort of random seed for my random number generator.

The problem is that the engine doesn't seem to recognize the : VPOS semantic. The DirectX9 documentation listed it under Pixel Shader Semantics and the examples along with it said that this is how it should be used. However, when I first look at the model, I get an error X4502: invalid ps_2_0 input semantic 'VPOS'. I've also tried the DirectX10 equivalent, 'SV_Position', but to no avail. I receive a similar error when I do that.

Can anyone help me with this?
Posted By: MasterQ32

Re: Generating random numbers in a pixel shader - 07/14/14 22:37

Use this:
Code:
float rand_1_05(in float2 uv)
{
    float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453));
    return abs(noise.x + noise.y) * 0.5;
}



There is no random option on a GPU, but you can use some "random" math functions to generate unregular fractal parts to generate numbers between 0 and 1

Just input your screen or texture coordinates.

Note that the random will stay constant until you add something like vecTime.w to your input coordinates.


To get screen coordinates you need to pass the transformed position into your pixel shader from the vertex shader

also use ps_2_0 or ps_3_0 as 1_1 is imho much too old and limiting for you
Posted By: TehV

Re: Generating random numbers in a pixel shader - 07/15/14 21:23

Thanks! That helped! I was now able to adjust the shader to my liking... somewhat. There's still a little problem that needs taking care of:



As you can see, parts of the model that overlap are darker than ones that don't overlap. I only want to see the outline of the model, filled with the noise I currently have, without any of the overlaps showing. I would like the model to be translucent. Is this possible?

If it helps (or if you want a copy of it for yourself), here's the shader I have right now:

Code:
//Flicker/Noise Shader

float4 vecTime;

float rand_1_05(in float2 uv)
{
    float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453));
    return abs(noise.x + noise.y) * 0.5;
}


float4 ps_flicker(in float2 screenSpace : VPOS): COLOR {
	float rnd = rand_1_05(screenSpace*fmod(vecTime.w,1));
	return float4(0,0,0,0.1 + (rnd * 0.5));
}

technique flicker
{
	pass p0
	{
		PixelShader = compile ps_3_0 ps_flicker();
	}
}



Thanks again for your help!
Posted By: Superku

Re: Generating random numbers in a pixel shader - 07/15/14 22:23

For non-convex objects non-overlapping transparency is not easily doable. However, you could try to render the object last (for example with a second NOSKY (?) view), then transmit the OutPos from the vertex shader to the pixel shader, import it as ProjTex and

ProjTex.xy = ProjTex.xy/ProjTex.z;
ProjTex.xy = ProjTex.xy*0.5 + 0.5;
ProjTex.y = 1.0-ProjTex.y;

use the transformed ProjTex to get the current pixel on the model on the screen and thus camera.bmap position. Now tex2D that content and you can realize improved transparency, i.e. by calculating your default Color pixel shader output and lerp() it with the ProjTex-camera.bmap result (I do something similar in my side-scroller).

Btw. in my game I've simply created a noise texture and randomize two noise values each frame which I use as a tex2D offset, this gives an acceptable noise with little to no effort and performance impact.
Posted By: sivan

Re: Generating random numbers in a pixel shader - 07/16/14 06:35

maybe using a depth view from camera position that includes only that entity, then use depth map as an inverse of in case of shadowmapping to ignore pixels or set to semi-transparent?
Posted By: MasterQ32

Re: Generating random numbers in a pixel shader - 07/16/14 10:20

AAaaah much complicatated, such work!

Simple use a two pass approach:
First pass renders only depth of your model (One + Zero), second pass renders your model as a silhuette (remove first part to see overlapping)
Code:
float4 ps() : COLOR0 {
	return float4(0.3, 0, 0, 1);
}

technique { 
	pass {
		ZEnable = true;
		ZFunc = Less;
		ZWriteEnable = true;
		AlphaBlendEnable = true;
		SrcBlend = Zero;
		DestBlend = One;
	}
	pass {
		ZEnable = true;
		ZFunc = LessEqual;
		ZWriteEnable = false;
		AlphaBlendEnable = true;
		SrcBlend = One;
		DestBlend = One;
		PixelShader = compile ps_2_0 ps();
	}
}

Posted By: Superku

Re: Generating random numbers in a pixel shader - 07/16/14 10:38

This is madness! And good to know...
Posted By: MasterQ32

Re: Generating random numbers in a pixel shader - 07/16/14 19:11

Not madness, it's depth buffer magic!

Well something like this...
The first pass renderst the model into the depth buffer so the front most polygons define the depth buffer. The second pass uses the depth buffer from the first pass rendering the model with the red shape, but only the frontside polygons.
Posted By: Superku

Re: Generating random numbers in a pixel shader - 07/16/14 21:25

Yes I got it but I never knew about the Src-/ DestBlend stuff (which I googled earlier today) or had the idea to do it that way.
Posted By: MasterQ32

Re: Generating random numbers in a pixel shader - 07/16/14 21:45

Yeah just wanted to clarify things also for not so shader affine people grin

The Src-/DestBlend stuff is awesome, you can do things you don't want to know grin

Like
SrcBlend = OneMinusDestAlpha;
DestBlend = OneMinusSrcAlpha;

grin
Posted By: sivan

Re: Generating random numbers in a pixel shader - 07/17/14 14:57

wow. maybe is it the way how in RTS games behind effect is rendered where only you see a silhouette of a unit if behind e.g. a building?
Posted By: Kartoffel

Re: Generating random numbers in a pixel shader - 07/17/14 15:07

@^: Most (if not all?) games that I saw were using pp-shaders for this effect.
Posted By: TehV

Re: Generating random numbers in a pixel shader - 07/19/14 17:15

Originally Posted By: MasterQ32
AAaaah much complicatated, such work!

Simple use a two pass approach:
First pass renders only depth of your model (One + Zero), second pass renders your model as a silhuette (remove first part to see overlapping)
Code:
float4 ps() : COLOR0 {
	return float4(0.3, 0, 0, 1);
}

technique { 
	pass {
		ZEnable = true;
		ZFunc = Less;
		ZWriteEnable = true;
		AlphaBlendEnable = true;
		SrcBlend = Zero;
		DestBlend = One;
	}
	pass {
		ZEnable = true;
		ZFunc = LessEqual;
		ZWriteEnable = false;
		AlphaBlendEnable = true;
		SrcBlend = One;
		DestBlend = One;
		PixelShader = compile ps_2_0 ps();
	}
}



That worked. The only problem I'm having is that I can't make it a transparent black (which is what I wanted). Is there a way to do this?
© 2024 lite-C Forums