post processing thermal vision shader

EDIT:
THIS SHADER WENT COMMERCIAL AND CAN BE DOWNLOADED FROM THE ASSET STORE.

(If you were lucky enough to grab it previously, you are free to use it anyway you want but i would appreciate your support if you buy it before using in a commercial product.)

I’m trying to learn more about image effects so this is perfect timing, thanks for sharing. I noticed that the docs on how to write image effects are pretty sparse, any suggestions on where to look for more info or maybe even a tutorial?

just look at the source files that are already supplied, finally the thing is same as any ordinary shader except that you work with 1 image file.

and for the formulas, nvidia shader library and some glsl( strangely they are more common) shaders which can be found around the internet are your friends.

The shader replacement resource also has a lot of simple examples.

where is this shader replacement resource?

http://unity3d.com/support/resources/example-projects/shader-replacement.html

You should also avoid conditionals inside shaders. They can be very slow on older cards.

Would you kindly show how else it could be written without conditionals?

float ix = (lum < 0.5) ? 0.0 : 1.0;
float4 res1 =  lerp(colors[0], colors[1], (lum - ix*0.5)/0.5);
float4 res2 = lerp(colors[1], colors[2], (lum - ix*0.5)/0.5);
float4 thermal = lerp(res1, res2, ix );

CONDITIONALS BE GONE!!

(I didn’t closely check syntax or anyhting so there might be an error. Principle remains the same though. Lerps > if’s!

Correct me if im wrong, but isnt the above still a conditional?

You are correct…

float ix = step(lum, 0.5);

That will fix it up for you for OpenGL (ARB) (it will use the SGE instruction). But that doesn’t exist on PS2.0 so it will use CMP. Getting the data into the right format to perform the CMP takes a few instructions, but the CMP itself isn’t so bad. As a note, the ternary statement seems to be compiled into a CMP on both platforms.

I’ve never really been 100% sure why conditionals are so slow though.

I assume it has something to do with branches in execution throwing a spanner in the works of a GPUs ability to process things in parallel. Like, keeping everything nice and linear with a fixed set of instructions means is can process a whole bunch of fragments at the same time but if the code branches differently for each pixel then it just all gets messed up and slows down. I could be way off there, would welcome any insight anyone else has - I just remember reading that conditionals and shaders are not mixey things.

PS2.0 does not support support Flow Control / Prediction in the pixel shader (or more specifically is not required too) which is what you are getting at there Cameron (Essentially dynamic branching).

This is from Real Time Rendering 3’nd Edition (if you are into graphics you should buy this book):

The reason you want to avoid standard if’s ect on PS2.0 is that on some hardware the CMP function has a non optimal performance characteristic. The shader you had provided is not ‘bad’ at all. All the conditionals were optimized to predicates so there was no dynamic branching. In fact I’m not sure off the top of my head what the minimal shader that would dynamic branch is.

Here is a good resource on dynamic branching:

A further note, because unity compiles Opengl shaders down to ARB shaders and there are no branching instructions for ARB. On OpenGL I believe that you don’t get any of the SM3.0 niceties you get with PS3.0. Aras said as much here:

http://forum.unity3d.com/threads/52704-Compiling-for-shader-model-3.0?p=334362&viewfull=1#post334362

Edit:

Just did some playing around with D3D9 profile, this will get you dynamic branching… will only compile on d3d and GLES though:

		CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest 
			#include "UnityCG.cginc"
			#pragma target 3.0
			#pragma only_renderers d3d9

			uniform sampler2D _MainTex;
			float4 thermal;

			float4 frag (v2f_img i) : COLOR {
				float4 pixcol = tex2D(_MainTex, i.uv);
				float4 colors[3];
				colors[0] = float4(0.0,0.0,1.0,1.0);
				colors[1] = float4(1.0,1.0,0.0,1.0);
				colors[2] = float4(1.0,0.0,0.0,1.0);
				float lum = (pixcol.r+pixcol.g+pixcol.b)/3.;
				int ix = (lum < 0.5)? 0:1;
				
				while( thermal.x < 0.5 )
				{
					thermal += lerp(colors[0], colors[1], (lum-float(ix)*0.5)/0.5);
				}
				return thermal;
			}
		ENDCG

mmm branching instructions:
loop aL, i0
break_ge r0.x, c2.x

It would be nice if Unity allowed for 3.0 marked shaders to compile into GLSL instead of ARB, then we could do dynamic branching, it does this for GLES. It becomes more of a gamble as to whether the shader will run on the hardware though, you would need to fall back to the fallback shader if the GLSL could not be compiled by the video card driver.

Thanks for taking the time to post that Stramit, makes a lot more sense now. I might have to grab a copy of that book. :slight_smile:

I second the recommendation. It’s one of the best textbooks I’ve come across in any field.

Soooo, the first posts code is optimal?

Need to remove this code on code owner’s request.

rahu

Unity pro comes with various image effects and there is a script called imageeffectbase.cs in that package. You need that one imported.