Looking for a way to pack 4 bytes of color data into a float in shader lab

I’m attempting to transfer an array of float values to ShaderLab by packing them into a texture with each byte taking up one color channel. Four channels giving me exactly 32 bits, enough to store a single precision float.

Here’s my implementation of a float to color converter in C#;

float num;
Byte[] b = System.BitConverter.GetBytes(num);

Color32 c = new Color(b[0], b[1], b[2], b[3]);

The only problem is I have no idea how to repack this data in Shaderlab. Most methods I’ve found in other languages require some form of iteration, I know that’s just not feasible in this language. So assuming I can use any Texture Sampler and I already have the correct UV coordinates available, is there any method available to cast this data back into a float?

Use DecodeFloatRGBA in UnityCG.cginc

Here’s the full code, along with the comment about limitations:

// Encoding/decoding [0..1) floats into 8 bit/channel RGBA. Note that 1.0 will not be encoded properly.
inline float4 EncodeFloatRGBA( float v )
{
	float4 kEncodeMul = float4(1.0, 255.0, 65025.0, 160581375.0);
	float kEncodeBit = 1.0/255.0;
	float4 enc = kEncodeMul * v;
	enc = frac (enc);
	enc -= enc.yzww * kEncodeBit;
	return enc;
}
inline float DecodeFloatRGBA( float4 enc )
{
	float4 kDecodeDot = float4(1.0, 1/255.0, 1/65025.0, 1/160581375.0);
	return dot( enc, kDecodeDot );
}
6 Likes

Thanks I had no idea that function existed!

It’s a very good idea to download the built-in shader source and look through the files you’ve probably been including. Although it’s not very thoroughly documented, a lot of the functions have very clear purposes.

Thanks, I had the default shader source but I wasn’t aware all the cginc files were included.

Can anyone explain why the fourth float in this line (and any other line where it appears) has a ZERO as its third digit?
float4 kEncodeMul = float4(1.0, 255.0, 65025.0, 160581375.0);
255255255 should be 16581375, shouldn’t it?

That looks like a typo in the post. In the version of UnityCG.cginc in my version of Unity, there is no zero.

See attached project (Unity 4.6.1 Free Edition). Not optimized but works as intended.

Maximum 96 lights (directional, point) for each game object with tag “Dynamic”. See script “Custom Shader” attached to “Main Camera”. You can combine meshes (not that it makes any performance difference) into one with “Do Combine Meshes”. Do Refresh Data Texture" refreshes the data texture and assigns a new material each frame. A simple “CustomShaderEditor” is included to enable display changes in editor. Click “Refresh” button or check “Refresh active” to enable constant update while changing game objects in editor.

IEEE 754 32bit standard for encoding and decoding floating point values.
http://www.h-schmidt.net/FloatConverter/IEEE754.html

C# (CustomShader.cs)
FloatToColor
ColorToFloat

Shader (shCustomBumpedSpecular.shader)
Color2Float

The shader function uses to many math instructions to decode a color so that makes it unusable for a game.

1934631–125029–CustomShader.zip (517 KB)

1 Like

See attached project (Unity 4.6.1 Free Edition).

I optimized encoding and decoding floating points. Ranging from -500.00 to 500.00. Precision loss over performance gain. It is much faster then the original encoding by IEEE 754 standard.

I noticed an unexpected fps slowdown when I move camera close to an object. It depends on how much of the camera viewport is filled with rendered objects. See attached images. Unity shader (like BumpedSpecular) does not have the same problem. Why does this happen? Can anyone explain?

Added support for lightmaps and specular highlights when using backed lighting. View CustomShader.jpg for preview.



1940811–125659–CustomShader.7z (1.31 MB)

What IS this sorcery?! :smile:

AMAZING WORK! :slight_smile: Works beautifully on my school lappy! :slight_smile:

Also asking: this this actually deferred (i.e. my definition: rendering all lights at once?!)

Ok, confirmed: by looking at you guys source, it might as well be deferred! (well, except for the light limits! :smile:)

Because… it appears you guys manage to apply 96 lights in ONE PASS!

Yes, it does everything in one pass.

There are limitations and things to consider:

  • Only point and directional lights.
  • You can do more lights by using a larger texture (but why would you want to). If all lights are being rendered the performance drops to about 80fps on my AMD Radeon HD 6800. This can be improved by including only the lights that are “needed” around the main camera. “Light occlusion”.
  • Do not resize game objects. Use only 1:1:1 as this causes dynamic resizing and decreases framerate.
  • No dynamic shadows or light cookies. Baked lighting only.
  • No mirror reflections. Only CubeMaps are possible (simple to add them) but they look a bit strange so I don’t use them.
  • Shader uses to many instructions. I was targeting 2.0 but it is not possible without the help of UnityPro features or shader engine.
  • probably more things but you get the basic idea … can be beneficial if used as intended.

Why performance drops (must be some editor events slowing it down):

  • 2 times slower When “Inspector” window is focused and visible. Compared to when “Lightmapping” window is focused and visible.

The problem with performance slow down (camera close to game object) is due to active dynamic light calculations being made in the background by Unity. When light rendering is disabled, the framerate remains at expected values (under 0.2ms).

The solution is to use baked lightmaps or to disable the lights (to stop them from “rendering” in the background):
Render Mode = Not Important
Culling Mask = Nothing
Lightmapping = Baked only

They will still be rendered dynamically by the custom shader.

Nice! :slight_smile:

Point being, it wouldn’t be too hard to add support for shadows! (well, at least Directional light shadows!)

But then one would be entering dynamic lighting territory… :smile:

Added support for dynamic shadows. One directional light to be more precise. See attached project.

1975713–128078–CustomShaderModel.7z (1.91 MB)

Mind if I try and improve the shadow filtering? :smile: Looking good, BTW

I do not mind. Please do post your improvements here. I will look into soft shadows as they are not (really) enabled in Unity free (at least they do not work in my project). Should be able to soften them up a bit :).

I have done soft shadows in free version before actually! :slight_smile:

Also, how do you sample the shadow map? This will help! :slight_smile:

I implemented blur by overlaying shadows by mgear example here. See attached project for more info. Not really what I want but it’s a start.

1977515–128195–CustomShaderModel.7z (1.94 MB)